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 17 void perf_sample__init(struct perf_sample *sample, bool all) 18 { 19 if (all) { 20 memset(sample, 0, sizeof(*sample)); 21 } else { 22 sample->evsel = NULL; 23 sample->user_regs = NULL; 24 sample->intr_regs = NULL; 25 sample->merged_callchain = false; 26 sample->callchain = NULL; 27 } 28 } 29 30 void perf_sample__exit(struct perf_sample *sample) 31 { 32 zfree(&sample->user_regs); 33 zfree(&sample->intr_regs); 34 if (sample->merged_callchain) { 35 zfree(&sample->callchain); 36 sample->merged_callchain = false; 37 } 38 } 39 40 struct regs_dump *perf_sample__user_regs(struct perf_sample *sample) 41 { 42 if (!sample->user_regs) { 43 sample->user_regs = zalloc(sizeof(*sample->user_regs)); 44 if (!sample->user_regs) 45 pr_err("Failure to allocate sample user_regs"); 46 } 47 return sample->user_regs; 48 } 49 50 51 struct regs_dump *perf_sample__intr_regs(struct perf_sample *sample) 52 { 53 if (!sample->intr_regs) { 54 sample->intr_regs = zalloc(sizeof(*sample->intr_regs)); 55 if (!sample->intr_regs) 56 pr_err("Failure to allocate sample intr_regs"); 57 } 58 return sample->intr_regs; 59 } 60 61 static int elf_machine_max_instruction_length(uint16_t e_machine) 62 { 63 switch (e_machine) { 64 /* Fixed 4-byte (32-bit) architectures */ 65 case EM_AARCH64: 66 case EM_PPC: 67 case EM_PPC64: 68 case EM_MIPS: 69 case EM_SPARC: 70 case EM_SPARCV9: 71 case EM_ALPHA: 72 case EM_LOONGARCH: 73 case EM_PARISC: 74 case EM_SH: 75 return 4; 76 77 /* Variable length or mixed-mode architectures */ 78 case EM_ARM: /* Variable due to Thumb/Thumb-2 */ 79 case EM_RISCV: /* Variable due to Compressed (C) extension */ 80 case EM_CSKY: /* Variable (16 or 32 bit) */ 81 case EM_ARC: /* Variable (ARCompact) */ 82 return 4; 83 case EM_S390: /* Variable (2, 4, or 6 bytes) */ 84 return 6; 85 case EM_68K: 86 return 10; 87 case EM_386: 88 case EM_X86_64: 89 return 15; 90 case EM_XTENSA: /* Variable (FLIX) */ 91 return 16; 92 default: 93 return MAX_INSN; 94 } 95 } 96 97 void perf_sample__fetch_insn(struct perf_sample *sample, 98 struct thread *thread, 99 struct machine *machine) 100 { 101 int ret, len; 102 bool is64bit = false; 103 uint16_t e_machine; 104 105 if (!sample->ip || sample->insn_len != 0) 106 return; 107 108 e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL); 109 len = elf_machine_max_instruction_length(e_machine); 110 len = thread__memcpy(thread, machine, sample->insn, 111 sample->ip, len, 112 &is64bit); 113 if (len <= 0) 114 return; 115 116 sample->insn_len = len; 117 118 if (e_machine == EM_386 || e_machine == EM_X86_64) { 119 /* Refine the x86 instruction length with the decoder. */ 120 struct insn insn; 121 122 ret = insn_decode(&insn, sample->insn, len, 123 is64bit ? INSN_MODE_64 : INSN_MODE_32); 124 if (ret >= 0 && insn.length <= len) 125 sample->insn_len = insn.length; 126 } 127 } 128