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