1 // SPDX-License-Identifier: GPL-2.0
3 * Instruction binary disassembler based on capstone.
5 * Author(s): Changbin Du <changbin.du@huawei.com>
15 #include "print_insn.h"
16 #include "dump-insn.h"
20 size_t sample__fprintf_insn_raw(struct perf_sample
*sample
, FILE *fp
)
24 for (int i
= 0; i
< sample
->insn_len
; i
++) {
25 printed
+= fprintf(fp
, "%02x", (unsigned char)sample
->insn
[i
]);
26 if (sample
->insn_len
- i
> 1)
27 printed
+= fprintf(fp
, " ");
32 #ifdef HAVE_LIBCAPSTONE_SUPPORT
33 #include <capstone/capstone.h>
35 int capstone_init(struct machine
*machine
, csh
*cs_handle
, bool is64
, bool disassembler_style
);
37 int capstone_init(struct machine
*machine
, csh
*cs_handle
, bool is64
, bool disassembler_style
)
42 if (machine__is(machine
, "x86_64") && is64
) {
45 } else if (machine__normalized_is(machine
, "x86")) {
48 } else if (machine__normalized_is(machine
, "arm64")) {
51 } else if (machine__normalized_is(machine
, "arm")) {
53 mode
= CS_MODE_ARM
+ CS_MODE_V8
;
54 } else if (machine__normalized_is(machine
, "s390")) {
56 mode
= CS_MODE_BIG_ENDIAN
;
61 if (cs_open(arch
, mode
, cs_handle
) != CS_ERR_OK
) {
62 pr_warning_once("cs_open failed\n");
66 if (machine__normalized_is(machine
, "x86")) {
68 * In case of using capstone_init while symbol__disassemble
69 * setting CS_OPT_SYNTAX_ATT depends if disassembler_style opts
70 * is set via annotation args
72 if (disassembler_style
)
73 cs_option(*cs_handle
, CS_OPT_SYNTAX
, CS_OPT_SYNTAX_ATT
);
75 * Resolving address operands to symbols is implemented
76 * on x86 by investigating instruction details.
78 cs_option(*cs_handle
, CS_OPT_DETAIL
, CS_OPT_ON
);
84 static size_t print_insn_x86(struct thread
*thread
, u8 cpumode
, cs_insn
*insn
,
85 int print_opts
, FILE *fp
)
87 struct addr_location al
;
90 if (insn
->detail
&& insn
->detail
->x86
.op_count
== 1) {
91 cs_x86_op
*op
= &insn
->detail
->x86
.operands
[0];
93 addr_location__init(&al
);
94 if (op
->type
== X86_OP_IMM
&&
95 thread__find_symbol(thread
, cpumode
, op
->imm
, &al
)) {
96 printed
+= fprintf(fp
, "%s ", insn
[0].mnemonic
);
97 printed
+= symbol__fprintf_symname_offs(al
.sym
, &al
, fp
);
98 if (print_opts
& PRINT_INSN_IMM_HEX
)
99 printed
+= fprintf(fp
, " [%#" PRIx64
"]", op
->imm
);
100 addr_location__exit(&al
);
103 addr_location__exit(&al
);
106 printed
+= fprintf(fp
, "%s %s", insn
[0].mnemonic
, insn
[0].op_str
);
110 static bool is64bitip(struct machine
*machine
, struct addr_location
*al
)
112 const struct dso
*dso
= al
->map
? map__dso(al
->map
) : NULL
;
115 return dso__is_64_bit(dso
);
117 return machine__is(machine
, "x86_64") ||
118 machine__normalized_is(machine
, "arm64") ||
119 machine__normalized_is(machine
, "s390");
122 ssize_t
fprintf_insn_asm(struct machine
*machine
, struct thread
*thread
, u8 cpumode
,
123 bool is64bit
, const uint8_t *code
, size_t code_size
,
124 uint64_t ip
, int *lenp
, int print_opts
, FILE *fp
)
132 /* TODO: Try to initiate capstone only once but need a proper place. */
133 ret
= capstone_init(machine
, &cs_handle
, is64bit
, true);
137 count
= cs_disasm(cs_handle
, code
, code_size
, ip
, 1, &insn
);
139 if (machine__normalized_is(machine
, "x86"))
140 printed
= print_insn_x86(thread
, cpumode
, &insn
[0], print_opts
, fp
);
142 printed
= fprintf(fp
, "%s %s", insn
[0].mnemonic
, insn
[0].op_str
);
145 cs_free(insn
, count
);
150 cs_close(&cs_handle
);
154 size_t sample__fprintf_insn_asm(struct perf_sample
*sample
, struct thread
*thread
,
155 struct machine
*machine
, FILE *fp
,
156 struct addr_location
*al
)
158 bool is64bit
= is64bitip(machine
, al
);
161 printed
= fprintf_insn_asm(machine
, thread
, sample
->cpumode
, is64bit
,
162 (uint8_t *)sample
->insn
, sample
->insn_len
,
163 sample
->ip
, NULL
, 0, fp
);
165 return sample__fprintf_insn_raw(sample
, fp
);
170 size_t sample__fprintf_insn_asm(struct perf_sample
*sample __maybe_unused
,
171 struct thread
*thread __maybe_unused
,
172 struct machine
*machine __maybe_unused
,
173 FILE *fp __maybe_unused
,
174 struct addr_location
*al __maybe_unused
)