xref: /linux/tools/perf/util/disasm.h (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0
2 #ifndef __PERF_UTIL_DISASM_H
3 #define __PERF_UTIL_DISASM_H
4 
5 #include "map_symbol.h"
6 
7 #ifdef HAVE_LIBDW_SUPPORT
8 #include "dwarf-aux.h"
9 #endif
10 
11 struct annotation_options;
12 struct disasm_line;
13 struct ins;
14 struct evsel;
15 struct symbol;
16 struct data_loc_info;
17 struct type_state;
18 struct disasm_line;
19 
20 struct e_machine_and_e_flags {
21 	uint32_t e_flags;
22 	uint16_t e_machine;
23 };
24 
25 struct arch {
26 	/** @name: name such as "x86" or "powerpc". */
27 	const char		*name;
28 	const struct ins	*instructions;
29 	size_t			nr_instructions;
30 	size_t			nr_instructions_allocated;
31 	const char		*insn_suffix;
32 	unsigned int		model;
33 	unsigned int		family;
34 	/** @id: ELF machine and flags associated with arch. */
35 	struct e_machine_and_e_flags id;
36 	bool			sorted_instructions;
37 	struct		{
38 		char comment_char;
39 		char skip_functions_char;
40 		char register_char;
41 		char memory_ref_char;
42 		char imm_char;
43 	} objdump;
44 	bool		(*ins_is_fused)(const struct arch *arch, const char *ins1,
45 					const char *ins2);
46 	const struct ins_ops  *(*associate_instruction_ops)(struct arch *arch, const char *name);
47 #ifdef HAVE_LIBDW_SUPPORT
48 	void		(*update_insn_state)(struct type_state *state,
49 				struct data_loc_info *dloc, Dwarf_Die *cu_die,
50 				struct disasm_line *dl);
51 #endif
52 };
53 
54 struct ins {
55 	const char     *name;
56 	const struct ins_ops *ops;
57 };
58 
59 struct ins_operands {
60 	char	*raw;
61 	struct {
62 		char	*raw;
63 		char	*name;
64 		struct symbol *sym;
65 		u64	addr;
66 		s64	offset;
67 		bool	offset_avail;
68 		bool	outside;
69 		bool	multi_regs;
70 		bool	mem_ref;
71 	} target;
72 	union {
73 		struct {
74 			char	*raw;
75 			char	*name;
76 			u64	addr;
77 			bool	multi_regs;
78 			bool	mem_ref;
79 		} source;
80 		struct {
81 			struct ins	    ins;
82 			struct ins_operands *ops;
83 		} locked;
84 		struct {
85 			char	*raw_comment;
86 			char	*raw_func_start;
87 		} jump;
88 	};
89 };
90 
91 struct ins_ops {
92 	void (*free)(struct ins_operands *ops);
93 	int (*parse)(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
94 			struct disasm_line *dl);
95 	int (*scnprintf)(const struct ins *ins, char *bf, size_t size,
96 			 struct ins_operands *ops, int max_ins_name);
97 	bool is_jump;
98 	bool is_call;
99 };
100 
101 struct annotate_args {
102 	const struct arch	  *arch;
103 	struct map_symbol	  *ms;
104 	struct annotation_options *options;
105 	s64			  offset;
106 	char			  *line;
107 	int			  line_nr;
108 	char			  *fileloc;
109 };
110 
111 const struct arch *arch__find(uint16_t e_machine, uint32_t e_flags, const char *cpuid);
112 bool arch__is_x86(const struct arch *arch);
113 bool arch__is_powerpc(const struct arch *arch);
114 
115 extern const struct ins_ops call_ops;
116 extern const struct ins_ops dec_ops;
117 extern const struct ins_ops jump_ops;
118 extern const struct ins_ops mov_ops;
119 extern const struct ins_ops nop_ops;
120 extern const struct ins_ops lock_ops;
121 extern const struct ins_ops ret_ops;
122 
123 int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops);
124 
125 const struct arch *arch__new_arc(const struct e_machine_and_e_flags *id, const char *cpuid);
126 const struct arch *arch__new_arm(const struct e_machine_and_e_flags *id, const char *cpuid);
127 const struct arch *arch__new_arm64(const struct e_machine_and_e_flags *id, const char *cpuid);
128 const struct arch *arch__new_csky(const struct e_machine_and_e_flags *id, const char *cpuid);
129 const struct arch *arch__new_loongarch(const struct e_machine_and_e_flags *id, const char *cpuid);
130 const struct arch *arch__new_mips(const struct e_machine_and_e_flags *id, const char *cpuid);
131 const struct arch *arch__new_powerpc(const struct e_machine_and_e_flags *id, const char *cpuid);
132 const struct arch *arch__new_riscv64(const struct e_machine_and_e_flags *id, const char *cpuid);
133 const struct arch *arch__new_s390(const struct e_machine_and_e_flags *id, const char *cpuid);
134 const struct arch *arch__new_sparc(const struct e_machine_and_e_flags *id, const char *cpuid);
135 const struct arch *arch__new_x86(const struct e_machine_and_e_flags *id, const char *cpuid);
136 
137 const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
138 
139 bool ins__is_call(const struct ins *ins);
140 bool ins__is_jump(const struct ins *ins);
141 bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2);
142 bool ins__is_ret(const struct ins *ins);
143 bool ins__is_lock(const struct ins *ins);
144 
145 const struct ins_ops *check_ppc_insn(struct disasm_line *dl);
146 
147 struct disasm_line *disasm_line__new(struct annotate_args *args);
148 void disasm_line__free(struct disasm_line *dl);
149 
150 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size,
151 			   bool raw, int max_ins_name);
152 
153 int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
154 			   struct ins_operands *ops, int max_ins_name);
155 int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
156 		   struct ins_operands *ops, int max_ins_name);
157 int call__scnprintf(const struct ins *ins, char *bf, size_t size,
158 		    struct ins_operands *ops, int max_ins_name);
159 int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
160 		    struct ins_operands *ops, int max_ins_name);
161 int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
162 		   struct ins_operands *ops, int max_ins_name);
163 
164 int symbol__disassemble(struct symbol *sym, struct annotate_args *args);
165 
166 char *expand_tabs(char *line, char **storage, size_t *storage_len);
167 
168 #endif /* __PERF_UTIL_DISASM_H */
169