perf_regs.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <errno.h>
  3. #include <string.h>
  4. #include <regex.h>
  5. #include "../../perf.h"
  6. #include "../../util/util.h"
  7. #include "../../util/perf_regs.h"
  8. #include "../../util/debug.h"
  9. const struct sample_reg sample_reg_masks[] = {
  10. SMPL_REG(r0, PERF_REG_POWERPC_R0),
  11. SMPL_REG(r1, PERF_REG_POWERPC_R1),
  12. SMPL_REG(r2, PERF_REG_POWERPC_R2),
  13. SMPL_REG(r3, PERF_REG_POWERPC_R3),
  14. SMPL_REG(r4, PERF_REG_POWERPC_R4),
  15. SMPL_REG(r5, PERF_REG_POWERPC_R5),
  16. SMPL_REG(r6, PERF_REG_POWERPC_R6),
  17. SMPL_REG(r7, PERF_REG_POWERPC_R7),
  18. SMPL_REG(r8, PERF_REG_POWERPC_R8),
  19. SMPL_REG(r9, PERF_REG_POWERPC_R9),
  20. SMPL_REG(r10, PERF_REG_POWERPC_R10),
  21. SMPL_REG(r11, PERF_REG_POWERPC_R11),
  22. SMPL_REG(r12, PERF_REG_POWERPC_R12),
  23. SMPL_REG(r13, PERF_REG_POWERPC_R13),
  24. SMPL_REG(r14, PERF_REG_POWERPC_R14),
  25. SMPL_REG(r15, PERF_REG_POWERPC_R15),
  26. SMPL_REG(r16, PERF_REG_POWERPC_R16),
  27. SMPL_REG(r17, PERF_REG_POWERPC_R17),
  28. SMPL_REG(r18, PERF_REG_POWERPC_R18),
  29. SMPL_REG(r19, PERF_REG_POWERPC_R19),
  30. SMPL_REG(r20, PERF_REG_POWERPC_R20),
  31. SMPL_REG(r21, PERF_REG_POWERPC_R21),
  32. SMPL_REG(r22, PERF_REG_POWERPC_R22),
  33. SMPL_REG(r23, PERF_REG_POWERPC_R23),
  34. SMPL_REG(r24, PERF_REG_POWERPC_R24),
  35. SMPL_REG(r25, PERF_REG_POWERPC_R25),
  36. SMPL_REG(r26, PERF_REG_POWERPC_R26),
  37. SMPL_REG(r27, PERF_REG_POWERPC_R27),
  38. SMPL_REG(r28, PERF_REG_POWERPC_R28),
  39. SMPL_REG(r29, PERF_REG_POWERPC_R29),
  40. SMPL_REG(r30, PERF_REG_POWERPC_R30),
  41. SMPL_REG(r31, PERF_REG_POWERPC_R31),
  42. SMPL_REG(nip, PERF_REG_POWERPC_NIP),
  43. SMPL_REG(msr, PERF_REG_POWERPC_MSR),
  44. SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
  45. SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
  46. SMPL_REG(link, PERF_REG_POWERPC_LINK),
  47. SMPL_REG(xer, PERF_REG_POWERPC_XER),
  48. SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
  49. SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
  50. SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
  51. SMPL_REG(dar, PERF_REG_POWERPC_DAR),
  52. SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
  53. SMPL_REG_END
  54. };
  55. /* REG or %rREG */
  56. #define SDT_OP_REGEX1 "^(%r)?([1-2]?[0-9]|3[0-1])$"
  57. /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
  58. #define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
  59. static regex_t sdt_op_regex1, sdt_op_regex2;
  60. static int sdt_init_op_regex(void)
  61. {
  62. static int initialized;
  63. int ret = 0;
  64. if (initialized)
  65. return 0;
  66. ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
  67. if (ret)
  68. goto error;
  69. ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
  70. if (ret)
  71. goto free_regex1;
  72. initialized = 1;
  73. return 0;
  74. free_regex1:
  75. regfree(&sdt_op_regex1);
  76. error:
  77. pr_debug4("Regex compilation error.\n");
  78. return ret;
  79. }
  80. /*
  81. * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
  82. * Possible variants of OP are:
  83. * Format Example
  84. * -------------------------
  85. * NUM(REG) 48(18)
  86. * -NUM(REG) -48(18)
  87. * NUM(%rREG) 48(%r18)
  88. * -NUM(%rREG) -48(%r18)
  89. * REG 18
  90. * %rREG %r18
  91. * iNUM i0
  92. * i-NUM i-1
  93. *
  94. * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
  95. * and REG form with -mno-regnames. Here REG is general purpose register,
  96. * which is in 0 to 31 range.
  97. */
  98. int arch_sdt_arg_parse_op(char *old_op, char **new_op)
  99. {
  100. int ret, new_len;
  101. regmatch_t rm[5];
  102. char prefix;
  103. /* Constant argument. Uprobe does not support it */
  104. if (old_op[0] == 'i') {
  105. pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
  106. return SDT_ARG_SKIP;
  107. }
  108. ret = sdt_init_op_regex();
  109. if (ret < 0)
  110. return ret;
  111. if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
  112. /* REG or %rREG --> %gprREG */
  113. new_len = 5; /* % g p r NULL */
  114. new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
  115. *new_op = zalloc(new_len);
  116. if (!*new_op)
  117. return -ENOMEM;
  118. scnprintf(*new_op, new_len, "%%gpr%.*s",
  119. (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
  120. } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
  121. /*
  122. * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
  123. * +/-NUM(%gprREG)
  124. */
  125. prefix = (rm[1].rm_so == -1) ? '+' : '-';
  126. new_len = 8; /* +/- ( % g p r ) NULL */
  127. new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
  128. new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
  129. *new_op = zalloc(new_len);
  130. if (!*new_op)
  131. return -ENOMEM;
  132. scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
  133. (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
  134. (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
  135. } else {
  136. pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
  137. return SDT_ARG_SKIP;
  138. }
  139. return SDT_ARG_VALID;
  140. }