sample.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include "sample.h"
  3. #include "debug.h"
  4. #include "thread.h"
  5. #include <elf.h>
  6. #ifndef EM_CSKY
  7. #define EM_CSKY 252
  8. #endif
  9. #ifndef EM_LOONGARCH
  10. #define EM_LOONGARCH 258
  11. #endif
  12. #include <linux/zalloc.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "../../arch/x86/include/asm/insn.h"
  16. void perf_sample__init(struct perf_sample *sample, bool all)
  17. {
  18. if (all) {
  19. memset(sample, 0, sizeof(*sample));
  20. } else {
  21. sample->user_regs = NULL;
  22. sample->intr_regs = NULL;
  23. }
  24. }
  25. void perf_sample__exit(struct perf_sample *sample)
  26. {
  27. free(sample->user_regs);
  28. free(sample->intr_regs);
  29. }
  30. struct regs_dump *perf_sample__user_regs(struct perf_sample *sample)
  31. {
  32. if (!sample->user_regs) {
  33. sample->user_regs = zalloc(sizeof(*sample->user_regs));
  34. if (!sample->user_regs)
  35. pr_err("Failure to allocate sample user_regs");
  36. }
  37. return sample->user_regs;
  38. }
  39. struct regs_dump *perf_sample__intr_regs(struct perf_sample *sample)
  40. {
  41. if (!sample->intr_regs) {
  42. sample->intr_regs = zalloc(sizeof(*sample->intr_regs));
  43. if (!sample->intr_regs)
  44. pr_err("Failure to allocate sample intr_regs");
  45. }
  46. return sample->intr_regs;
  47. }
  48. static int elf_machine_max_instruction_length(uint16_t e_machine)
  49. {
  50. switch (e_machine) {
  51. /* Fixed 4-byte (32-bit) architectures */
  52. case EM_AARCH64:
  53. case EM_PPC:
  54. case EM_PPC64:
  55. case EM_MIPS:
  56. case EM_SPARC:
  57. case EM_SPARCV9:
  58. case EM_ALPHA:
  59. case EM_LOONGARCH:
  60. case EM_PARISC:
  61. case EM_SH:
  62. return 4;
  63. /* Variable length or mixed-mode architectures */
  64. case EM_ARM: /* Variable due to Thumb/Thumb-2 */
  65. case EM_RISCV: /* Variable due to Compressed (C) extension */
  66. case EM_CSKY: /* Variable (16 or 32 bit) */
  67. case EM_ARC: /* Variable (ARCompact) */
  68. return 4;
  69. case EM_S390: /* Variable (2, 4, or 6 bytes) */
  70. return 6;
  71. case EM_68K:
  72. return 10;
  73. case EM_386:
  74. case EM_X86_64:
  75. return 15;
  76. case EM_XTENSA: /* Variable (FLIX) */
  77. return 16;
  78. default:
  79. return MAX_INSN;
  80. }
  81. }
  82. void perf_sample__fetch_insn(struct perf_sample *sample,
  83. struct thread *thread,
  84. struct machine *machine)
  85. {
  86. int ret, len;
  87. bool is64bit = false;
  88. uint16_t e_machine;
  89. if (!sample->ip || sample->insn_len != 0)
  90. return;
  91. e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL);
  92. len = elf_machine_max_instruction_length(e_machine);
  93. len = thread__memcpy(thread, machine, sample->insn,
  94. sample->ip, len,
  95. &is64bit);
  96. if (len <= 0)
  97. return;
  98. sample->insn_len = len;
  99. if (e_machine == EM_386 || e_machine == EM_X86_64) {
  100. /* Refine the x86 instruction length with the decoder. */
  101. struct insn insn;
  102. ret = insn_decode(&insn, sample->insn, len,
  103. is64bit ? INSN_MODE_64 : INSN_MODE_32);
  104. if (ret >= 0 && insn.length <= len)
  105. sample->insn_len = insn.length;
  106. }
  107. }