perf_event_open.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: LGPL-2.1
  2. #ifndef PERF_FLAG_FD_NO_GROUP
  3. # define PERF_FLAG_FD_NO_GROUP (1UL << 0)
  4. #endif
  5. #ifndef PERF_FLAG_FD_OUTPUT
  6. # define PERF_FLAG_FD_OUTPUT (1UL << 1)
  7. #endif
  8. #ifndef PERF_FLAG_PID_CGROUP
  9. # define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
  10. #endif
  11. #ifndef PERF_FLAG_FD_CLOEXEC
  12. # define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
  13. #endif
  14. static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
  15. struct syscall_arg *arg)
  16. {
  17. bool show_prefix = arg->show_string_prefix;
  18. const char *prefix = "PERF_";
  19. int printed = 0, flags = arg->val;
  20. if (flags == 0)
  21. return 0;
  22. #define P_FLAG(n) \
  23. if (flags & PERF_FLAG_##n) { \
  24. printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \
  25. flags &= ~PERF_FLAG_##n; \
  26. }
  27. P_FLAG(FD_NO_GROUP);
  28. P_FLAG(FD_OUTPUT);
  29. P_FLAG(PID_CGROUP);
  30. P_FLAG(FD_CLOEXEC);
  31. #undef P_FLAG
  32. if (flags)
  33. printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  34. return printed;
  35. }
  36. #define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
  37. struct attr_fprintf_args {
  38. size_t size, printed;
  39. char *bf;
  40. bool first;
  41. };
  42. static int attr__fprintf(FILE *fp __maybe_unused, const char *name, const char *val, void *priv)
  43. {
  44. struct attr_fprintf_args *args = priv;
  45. size_t printed = scnprintf(args->bf + args->printed , args->size - args->printed, "%s%s: %s", args->first ? "" : ", ", name, val);
  46. args->first = false;
  47. args->printed += printed;
  48. return printed;
  49. }
  50. static size_t perf_event_attr___scnprintf(struct perf_event_attr *attr, char *bf, size_t size, bool show_zeros __maybe_unused)
  51. {
  52. struct attr_fprintf_args args = {
  53. .printed = scnprintf(bf, size, "{ "),
  54. .size = size,
  55. .first = true,
  56. .bf = bf,
  57. };
  58. perf_event_attr__fprintf(stdout, attr, attr__fprintf, &args);
  59. return args.printed + scnprintf(bf + args.printed, size - args.printed, " }");
  60. }
  61. static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_arg *arg, char *bf, size_t size)
  62. {
  63. return perf_event_attr___scnprintf((void *)arg->augmented.args->value, bf, size, arg->trace->show_zeros);
  64. }
  65. static size_t syscall_arg__scnprintf_perf_event_attr(char *bf, size_t size, struct syscall_arg *arg)
  66. {
  67. if (arg->augmented.args)
  68. return syscall_arg__scnprintf_augmented_perf_event_attr(arg, bf, size);
  69. return scnprintf(bf, size, "%#lx", arg->val);
  70. }
  71. #define SCA_PERF_ATTR syscall_arg__scnprintf_perf_event_attr
  72. // 'argname' is just documentational at this point, to remove the previous comment with that info
  73. #define SCA_PERF_ATTR_FROM_USER(argname) \
  74. { .scnprintf = SCA_PERF_ATTR, \
  75. .from_user = true, }