[go: up one dir, main page]

File: arch.h

package info (click to toggle)
uftrace 0.18.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,356 kB
  • sloc: ansic: 49,770; python: 11,181; asm: 837; makefile: 769; sh: 637; cpp: 627; javascript: 191
file content (279 lines) | stat: -rw-r--r-- 7,742 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/*
 * Architecture specific code and data
 */
#ifndef UFTRACE_ARCH_H
#define UFTRACE_ARCH_H

#include <stdbool.h>

struct mcount_dynamic_info;
struct mcount_disasm_engine;
struct mcount_disasm_info;
struct mcount_event_info;
struct mcount_orig_insn;
struct plthook_data;
struct uftrace_elf_data;
struct uftrace_symtab;
struct uftrace_symbol;

enum mcount_arch_ops_entry {
	UFT_ARCH_OPS_MCOUNT,
	UFT_ARCH_OPS_PLTHOOK,
	UFT_ARCH_OPS_FENTRY,
	UFT_ARCH_OPS_DYNAMIC,
	UFT_ARCH_OPS_XRAY,

	UFT_ARCH_OPS_NUM,
};

/* Arch-specific callback functions for libmcount. */
struct mcount_arch_ops {
	/*
	 * Save address of arch-specific assembly functions for tracing entry and exit paths.
	 * MCOUNT and PLTHOOK are required and others are optional.
	 */
	unsigned long entry[UFT_ARCH_OPS_NUM];
	unsigned long exit[UFT_ARCH_OPS_NUM];

	/*
	 * Functions to support non-standard PLT hooking.
	 */
	/* Prepare arch-specific PLT handling and save necessary info to pd->arch. */
	void (*plthook_setup)(struct plthook_data *pd, struct uftrace_elf_data *elf);
	/* Return the address of PLT function at the given index. */
	unsigned long (*plthook_addr)(struct plthook_data *pd, int idx);
	/* Adjust and return the index of PLT function. */
	unsigned long (*child_idx)(unsigned long idx);
	/* Setup an artificial PLT if the module doesn't have one, and return a new plthook_data. */
	struct plthook_data *(*hook_no_plt)(struct uftrace_elf_data *elf, const char *module,
					    unsigned long offset);

	/* Optional functions for event processing (e.g. SDT).  Returns 0 or negative error. */
	int (*enable_event)(struct mcount_event_info *mei);

	/*
	 * Functions to support dynamic tracing.  If 'disasm_init' is defined, it assumes others
	 * (except for the last two) are defined too.
	 */
	/* Initialize the (capstone) disassembly engine. */
	void (*disasm_init)(struct mcount_disasm_engine *disasm);
	/* Finalize the (capstone) disassembly engine. */
	void (*disasm_finish)(struct mcount_disasm_engine *disasm);
	/* Setup a trampoline to jump to the entry function. Return 0 or negative error. */
	int (*setup_trampoline)(struct mcount_dynamic_info *mdi);
	/* Cleanup the trampoline if it's setup. */
	void (*cleanup_trampoline)(struct mcount_dynamic_info *mdi);
	/* Update code in the function entry to jump to the trampoline. */
	int (*patch_func)(struct mcount_dynamic_info *mdi, struct uftrace_symbol *sym,
			  struct mcount_disasm_engine *disasm, unsigned min_size);
	/* Update code in the function entry not to jump to the entry. */
	int (*unpatch_func)(struct mcount_dynamic_info *mdi, struct uftrace_symbol *sym,
			    struct mcount_disasm_engine *disasm);
	/* Check binary (module) for the mdi and set mdi->type properly. */
	void (*find_module)(struct mcount_dynamic_info *mdi, struct uftrace_symtab *symtab);
	/* Restore original code in the mdi when something bad happen. */
	void (*dynamic_recover)(struct mcount_dynamic_info *mdi,
				struct mcount_disasm_engine *disasm);
	/* Optional function to calculate size of branch tables for the original code. */
	int (*branch_table_size)(struct mcount_disasm_info *info);
	/* Optional function to handle branch instructions in the original code. */
	void (*patch_branch)(struct mcount_disasm_info *, struct mcount_orig_insn *);
};

/* Arch-specific operations used by both uftrace and libmcount */
struct uftrace_arch_ops {
	/*
	 * Load dynamic symbols from ELF data when they are not in the PLT relocation table.
	 * It may reset the symbol table.  It should return the number of symbols loaded.
	 */
	int (*load_dynsymtab)(struct uftrace_symtab *symtab, struct uftrace_elf_data *elf,
			      unsigned long offset, unsigned long flags);
};

/* Each architecture should provide these. */
extern const struct mcount_arch_ops mcount_arch_ops;
extern const struct uftrace_arch_ops uftrace_arch_ops;

enum uftrace_cpu_arch {
	UFT_CPU_NONE,
	UFT_CPU_X86_64,
	UFT_CPU_ARM,
	UFT_CPU_AARCH64,
	UFT_CPU_I386,
	UFT_CPU_RISCV64,
};

static inline enum uftrace_cpu_arch host_cpu_arch(void)
{
#if defined(__x86_64__)
	return UFT_CPU_X86_64;
#elif defined(__arm__)
	return UFT_CPU_ARM;
#elif defined(__aarch64__)
	return UFT_CPU_AARCH64;
#elif defined(__i386__)
	return UFT_CPU_I386;
#elif defined(__riscv) && __riscv_xlen == 64
	return UFT_CPU_RISCV64;
#else
	return UFT_CPU_NONE;
#endif
}

static inline bool arch_is_lp64(enum uftrace_cpu_arch arch)
{
	switch (arch) {
	case UFT_CPU_X86_64:
	case UFT_CPU_AARCH64:
	case UFT_CPU_RISCV64:
		return true;
	default:
		return false;
	}
}

enum uftrace_x86_64_reg_index {
	UFT_X86_64_REG_INT_BASE = 0,
	/* integer registers */
	UFT_X86_64_REG_RDI,
	UFT_X86_64_REG_RSI,
	UFT_X86_64_REG_RDX,
	UFT_X86_64_REG_RCX,
	UFT_X86_64_REG_R8,
	UFT_X86_64_REG_R9,

	UFT_X86_64_REG_FLOAT_BASE = 100,
	/* floating-point registers */
	UFT_X86_64_REG_XMM0,
	UFT_X86_64_REG_XMM1,
	UFT_X86_64_REG_XMM2,
	UFT_X86_64_REG_XMM3,
	UFT_X86_64_REG_XMM4,
	UFT_X86_64_REG_XMM5,
	UFT_X86_64_REG_XMM6,
	UFT_X86_64_REG_XMM7,
};

enum uftrace_arm_reg_index {
	UFT_ARM_REG_INT_BASE = 0,
	/* integer registers */
	UFT_ARM_REG_R0,
	UFT_ARM_REG_R1,
	UFT_ARM_REG_R2,
	UFT_ARM_REG_R3,

	UFT_ARM_REG_FLOAT_BASE = 100,
	/* (single-precision) floating-point registers */
	UFT_ARM_REG_S0,
	UFT_ARM_REG_S1,
	UFT_ARM_REG_S2,
	UFT_ARM_REG_S3,
	UFT_ARM_REG_S4,
	UFT_ARM_REG_S5,
	UFT_ARM_REG_S6,
	UFT_ARM_REG_S7,
	UFT_ARM_REG_S8,
	UFT_ARM_REG_S9,
	UFT_ARM_REG_S10,
	UFT_ARM_REG_S11,
	UFT_ARM_REG_S12,
	UFT_ARM_REG_S13,
	UFT_ARM_REG_S14,
	UFT_ARM_REG_S15,
	/* double-precision registers */
	UFT_ARM_REG_DOUBLE_BASE = 200,
	UFT_ARM_REG_D0,
	UFT_ARM_REG_D1,
	UFT_ARM_REG_D2,
	UFT_ARM_REG_D3,
	UFT_ARM_REG_D4,
	UFT_ARM_REG_D5,
	UFT_ARM_REG_D6,
	UFT_ARM_REG_D7,
};

enum uftrace_aarch64_reg_index {
	UFT_AARCH64_REG_INT_BASE = 0,
	/* integer registers */
	UFT_AARCH64_REG_X0,
	UFT_AARCH64_REG_X1,
	UFT_AARCH64_REG_X2,
	UFT_AARCH64_REG_X3,
	UFT_AARCH64_REG_X4,
	UFT_AARCH64_REG_X5,
	UFT_AARCH64_REG_X6,
	UFT_AARCH64_REG_X7,

	UFT_AARCH64_REG_FLOAT_BASE = 100,
	/* (single-precision) floating-point registers */
	UFT_AARCH64_REG_S0,
	UFT_AARCH64_REG_S1,
	UFT_AARCH64_REG_S2,
	UFT_AARCH64_REG_S3,
	UFT_AARCH64_REG_S4,
	UFT_AARCH64_REG_S5,
	UFT_AARCH64_REG_S6,
	UFT_AARCH64_REG_S7,

	UFT_AARCH64_REG_DOUBLE_BASE = 200,
	/* (double-precision) floating-point registers */
	UFT_AARCH64_REG_D0,
	UFT_AARCH64_REG_D1,
	UFT_AARCH64_REG_D2,
	UFT_AARCH64_REG_D3,
	UFT_AARCH64_REG_D4,
	UFT_AARCH64_REG_D5,
	UFT_AARCH64_REG_D6,
	UFT_AARCH64_REG_D7,
};

enum uftrace_i386_reg_index {
	UFT_I386_REG_INT_BASE = 0,
	/* integer registers */
	UFT_I386_REG_ECX,
	UFT_I386_REG_EDX,

	UFT_I386_REG_FLOAT_BASE = 100,
	/* floating-point registers */
	UFT_I386_REG_XMM0,
	UFT_I386_REG_XMM1,
	UFT_I386_REG_XMM2,
	UFT_I386_REG_XMM3,
	UFT_I386_REG_XMM4,
	UFT_I386_REG_XMM5,
	UFT_I386_REG_XMM6,
	UFT_I386_REG_XMM7,
};

enum uftrace_riscv64_reg_index {
	UFT_RISCV64_REG_INT_BASE = 0,
	/* integer argument registers */
	UFT_RISCV64_REG_A0,
	UFT_RISCV64_REG_A1,
	UFT_RISCV64_REG_A2,
	UFT_RISCV64_REG_A3,
	UFT_RISCV64_REG_A4,
	UFT_RISCV64_REG_A5,
	UFT_RISCV64_REG_A6,
	UFT_RISCV64_REG_A7,

	UFT_RISCV64_REG_FLOAT_BASE = 100,
	/* floating-point argument registers */
	UFT_RISCV64_REG_FA0,
	UFT_RISCV64_REG_FA1,
	UFT_RISCV64_REG_FA2,
	UFT_RISCV64_REG_FA3,
	UFT_RISCV64_REG_FA4,
	UFT_RISCV64_REG_FA5,
	UFT_RISCV64_REG_FA6,
	UFT_RISCV64_REG_FA7,
};

int arch_register_number(enum uftrace_cpu_arch arch, char *reg_name);
int arch_register_at(enum uftrace_cpu_arch arch, bool integer, int idx);
int arch_register_index(enum uftrace_cpu_arch arch, int idx);

const char *arch_register_dwarf_name(enum uftrace_cpu_arch arch, int dwarf_reg);
const char *arch_register_argspec_name(enum uftrace_cpu_arch arch, bool integer, int idx);

#endif /* UFTRACE_ARCH_H */