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