instructions.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/compiler.h>
  3. #include <sys/types.h>
  4. #include <regex.h>
  5. struct arm64_annotate {
  6. regex_t call_insn,
  7. jump_insn;
  8. };
  9. static int arm64_mov__parse(struct arch *arch __maybe_unused,
  10. struct ins_operands *ops,
  11. struct map_symbol *ms __maybe_unused)
  12. {
  13. char *s = strchr(ops->raw, ','), *target, *endptr;
  14. if (s == NULL)
  15. return -1;
  16. *s = '\0';
  17. ops->source.raw = strdup(ops->raw);
  18. *s = ',';
  19. if (ops->source.raw == NULL)
  20. return -1;
  21. target = ++s;
  22. ops->target.raw = strdup(target);
  23. if (ops->target.raw == NULL)
  24. goto out_free_source;
  25. ops->target.addr = strtoull(target, &endptr, 16);
  26. if (endptr == target)
  27. goto out_free_target;
  28. s = strchr(endptr, '<');
  29. if (s == NULL)
  30. goto out_free_target;
  31. endptr = strchr(s + 1, '>');
  32. if (endptr == NULL)
  33. goto out_free_target;
  34. *endptr = '\0';
  35. *s = ' ';
  36. ops->target.name = strdup(s);
  37. *s = '<';
  38. *endptr = '>';
  39. if (ops->target.name == NULL)
  40. goto out_free_target;
  41. return 0;
  42. out_free_target:
  43. zfree(&ops->target.raw);
  44. out_free_source:
  45. zfree(&ops->source.raw);
  46. return -1;
  47. }
  48. static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
  49. struct ins_operands *ops);
  50. static struct ins_ops arm64_mov_ops = {
  51. .parse = arm64_mov__parse,
  52. .scnprintf = mov__scnprintf,
  53. };
  54. static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
  55. {
  56. struct arm64_annotate *arm = arch->priv;
  57. struct ins_ops *ops;
  58. regmatch_t match[2];
  59. if (!regexec(&arm->jump_insn, name, 2, match, 0))
  60. ops = &jump_ops;
  61. else if (!regexec(&arm->call_insn, name, 2, match, 0))
  62. ops = &call_ops;
  63. else if (!strcmp(name, "ret"))
  64. ops = &ret_ops;
  65. else
  66. ops = &arm64_mov_ops;
  67. arch__associate_ins_ops(arch, name, ops);
  68. return ops;
  69. }
  70. static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
  71. {
  72. struct arm64_annotate *arm;
  73. int err;
  74. if (arch->initialized)
  75. return 0;
  76. arm = zalloc(sizeof(*arm));
  77. if (!arm)
  78. return -1;
  79. /* bl, blr */
  80. err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
  81. if (err)
  82. goto out_free_arm;
  83. /* b, b.cond, br, cbz/cbnz, tbz/tbnz */
  84. err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl)?n?z?$",
  85. REG_EXTENDED);
  86. if (err)
  87. goto out_free_call;
  88. arch->initialized = true;
  89. arch->priv = arm;
  90. arch->associate_instruction_ops = arm64__associate_instruction_ops;
  91. arch->objdump.comment_char = '/';
  92. arch->objdump.skip_functions_char = '+';
  93. return 0;
  94. out_free_call:
  95. regfree(&arm->call_insn);
  96. out_free_arm:
  97. free(arm);
  98. return -1;
  99. }