]>
Commit | Line | Data |
---|---|---|
39791af2 JM |
1 | /* Target-dependent code for BPF. |
2 | ||
4a94e368 | 3 | Copyright (C) 2020-2022 Free Software Foundation, Inc. |
39791af2 JM |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "arch-utils.h" | |
22 | #include "dis-asm.h" | |
23 | #include "frame.h" | |
24 | #include "frame-unwind.h" | |
25 | #include "trad-frame.h" | |
26 | #include "symtab.h" | |
27 | #include "value.h" | |
28 | #include "gdbcmd.h" | |
29 | #include "breakpoint.h" | |
30 | #include "inferior.h" | |
31 | #include "regcache.h" | |
32 | #include "target.h" | |
33 | #include "dwarf2/frame.h" | |
34 | #include "osabi.h" | |
35 | #include "target-descriptions.h" | |
36 | #include "remote.h" | |
76eb8ef1 | 37 | #include "gdbarch.h" |
39791af2 JM |
38 | |
39 | \f | |
40 | /* eBPF registers. */ | |
41 | ||
42 | enum bpf_regnum | |
43 | { | |
44 | BPF_R0_REGNUM, /* return value */ | |
45 | BPF_R1_REGNUM, | |
46 | BPF_R2_REGNUM, | |
47 | BPF_R3_REGNUM, | |
48 | BPF_R4_REGNUM, | |
49 | BPF_R5_REGNUM, | |
50 | BPF_R6_REGNUM, | |
51 | BPF_R7_REGNUM, | |
52 | BPF_R8_REGNUM, | |
53 | BPF_R9_REGNUM, | |
54 | BPF_R10_REGNUM, /* sp */ | |
55 | BPF_PC_REGNUM, | |
56 | }; | |
57 | ||
58 | #define BPF_NUM_REGS (BPF_PC_REGNUM + 1) | |
59 | ||
60 | /* Target-dependent structure in gdbarch. */ | |
345bd07c | 61 | struct bpf_gdbarch_tdep : gdbarch_tdep |
39791af2 JM |
62 | { |
63 | }; | |
64 | ||
65 | \f | |
66 | /* Internal debugging facilities. */ | |
67 | ||
68 | /* When this is set to non-zero debugging information will be | |
69 | printed. */ | |
70 | ||
71 | static unsigned int bpf_debug_flag = 0; | |
72 | ||
73 | /* The show callback for 'show debug bpf'. */ | |
74 | ||
75 | static void | |
76 | show_bpf_debug (struct ui_file *file, int from_tty, | |
dda83cd7 | 77 | struct cmd_list_element *c, const char *value) |
39791af2 | 78 | { |
6cb06a8c | 79 | gdb_printf (file, _("Debugging of BPF is %s.\n"), value); |
39791af2 JM |
80 | } |
81 | ||
82 | \f | |
83 | /* BPF registers. */ | |
84 | ||
85 | static const char *bpf_register_names[] = | |
86 | { | |
87 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | |
88 | "r8", "r9", "r10", "pc" | |
89 | }; | |
90 | ||
91 | /* Return the name of register REGNUM. */ | |
92 | ||
93 | static const char * | |
94 | bpf_register_name (struct gdbarch *gdbarch, int reg) | |
95 | { | |
96 | if (reg >= 0 && reg < BPF_NUM_REGS) | |
97 | return bpf_register_names[reg]; | |
98 | return NULL; | |
99 | } | |
100 | ||
101 | /* Return the GDB type of register REGNUM. */ | |
102 | ||
103 | static struct type * | |
104 | bpf_register_type (struct gdbarch *gdbarch, int reg) | |
105 | { | |
106 | if (reg == BPF_R10_REGNUM) | |
107 | return builtin_type (gdbarch)->builtin_data_ptr; | |
108 | else if (reg == BPF_PC_REGNUM) | |
109 | return builtin_type (gdbarch)->builtin_func_ptr; | |
110 | return builtin_type (gdbarch)->builtin_int64; | |
111 | } | |
112 | ||
113 | /* Return the GDB register number corresponding to DWARF's REG. */ | |
114 | ||
115 | static int | |
116 | bpf_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) | |
117 | { | |
118 | if (reg >= 0 && reg < BPF_NUM_REGS) | |
119 | return reg; | |
120 | return -1; | |
121 | } | |
122 | ||
123 | /* Implement the "print_insn" gdbarch method. */ | |
124 | ||
125 | static int | |
126 | bpf_gdb_print_insn (bfd_vma memaddr, disassemble_info *info) | |
127 | { | |
128 | info->symbols = NULL; | |
129 | return default_print_insn (memaddr, info); | |
130 | } | |
131 | ||
132 | \f | |
133 | /* Return PC of first real instruction of the function starting at | |
134 | START_PC. */ | |
135 | ||
136 | static CORE_ADDR | |
137 | bpf_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) | |
138 | { | |
6cb06a8c TT |
139 | gdb_printf (gdb_stdlog, |
140 | "Skipping prologue: start_pc=%s\n", | |
141 | paddress (gdbarch, start_pc)); | |
39791af2 JM |
142 | /* XXX: to be completed. */ |
143 | return start_pc + 0; | |
144 | } | |
145 | ||
146 | \f | |
147 | /* Frame unwinder. | |
148 | ||
149 | XXX it is not clear how to unwind in eBPF, since the stack is not | |
150 | guaranteed to be contiguous, and therefore no relative stack | |
151 | addressing can be done in the callee in order to access the | |
152 | caller's stack frame. To explore with xBPF, which will relax this | |
153 | restriction. */ | |
154 | ||
155 | /* Given THIS_FRAME, return its ID. */ | |
156 | ||
157 | static void | |
158 | bpf_frame_this_id (struct frame_info *this_frame, | |
159 | void **this_prologue_cache, | |
160 | struct frame_id *this_id) | |
161 | { | |
162 | /* Note that THIS_ID defaults to the outermost frame if we don't set | |
163 | anything here. See frame.c:compute_frame_id. */ | |
164 | } | |
165 | ||
166 | /* Return the reason why we can't unwind past THIS_FRAME. */ | |
167 | ||
168 | static enum unwind_stop_reason | |
169 | bpf_frame_unwind_stop_reason (struct frame_info *this_frame, | |
170 | void **this_cache) | |
171 | { | |
172 | return UNWIND_OUTERMOST; | |
173 | } | |
174 | ||
175 | /* Ask THIS_FRAME to unwind its register. */ | |
176 | ||
177 | static struct value * | |
178 | bpf_frame_prev_register (struct frame_info *this_frame, | |
179 | void **this_prologue_cache, int regnum) | |
180 | { | |
181 | return frame_unwind_got_register (this_frame, regnum, regnum); | |
182 | } | |
183 | ||
184 | /* Frame unwinder machinery for BPF. */ | |
185 | ||
186 | static const struct frame_unwind bpf_frame_unwind = | |
187 | { | |
a154d838 | 188 | "bpf prologue", |
39791af2 JM |
189 | NORMAL_FRAME, |
190 | bpf_frame_unwind_stop_reason, | |
191 | bpf_frame_this_id, | |
192 | bpf_frame_prev_register, | |
193 | NULL, | |
194 | default_frame_sniffer | |
195 | }; | |
196 | ||
197 | \f | |
198 | /* Breakpoints. */ | |
199 | ||
200 | /* Enum describing the different kinds of breakpoints. We currently | |
201 | just support one, implemented by the brkpt xbpf instruction. */ | |
202 | ||
203 | enum bpf_breakpoint_kinds | |
204 | { | |
205 | BPF_BP_KIND_BRKPT = 0, | |
206 | }; | |
207 | ||
208 | /* Implement the breakpoint_kind_from_pc gdbarch method. */ | |
209 | ||
210 | static int | |
211 | bpf_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *start_pc) | |
212 | { | |
213 | /* We support just one kind of breakpoint. */ | |
214 | return BPF_BP_KIND_BRKPT; | |
215 | } | |
216 | ||
217 | /* Implement the sw_breakpoint_from_kind gdbarch method. */ | |
218 | ||
219 | static const gdb_byte * | |
220 | bpf_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) | |
221 | { | |
222 | static unsigned char brkpt_insn[] | |
223 | = {0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
224 | ||
225 | switch (kind) | |
226 | { | |
227 | case BPF_BP_KIND_BRKPT: | |
228 | *size = 8; | |
229 | return brkpt_insn; | |
230 | default: | |
231 | gdb_assert_not_reached ("unexpected BPF breakpoint kind"); | |
232 | } | |
233 | } | |
234 | ||
235 | \f | |
236 | /* Assuming THIS_FRAME is a dummy frame, return its frame ID. */ | |
237 | ||
238 | static struct frame_id | |
239 | bpf_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) | |
240 | { | |
241 | CORE_ADDR sp = get_frame_register_unsigned (this_frame, | |
242 | gdbarch_sp_regnum (gdbarch)); | |
243 | return frame_id_build (sp, get_frame_pc (this_frame)); | |
244 | } | |
245 | ||
246 | /* Implement the push dummy call gdbarch callback. */ | |
247 | ||
248 | static CORE_ADDR | |
249 | bpf_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | |
250 | struct regcache *regcache, CORE_ADDR bp_addr, | |
251 | int nargs, struct value **args, CORE_ADDR sp, | |
252 | function_call_return_method return_method, | |
253 | CORE_ADDR struct_addr) | |
254 | { | |
6cb06a8c TT |
255 | gdb_printf (gdb_stdlog, "Pushing dummy call: sp=%s\n", |
256 | paddress (gdbarch, sp)); | |
39791af2 JM |
257 | /* XXX writeme */ |
258 | return sp; | |
259 | } | |
260 | ||
261 | /* Extract a function return value of TYPE from REGCACHE, | |
262 | and copy it into VALBUF. */ | |
263 | ||
264 | static void | |
265 | bpf_extract_return_value (struct type *type, struct regcache *regcache, | |
266 | gdb_byte *valbuf) | |
267 | { | |
268 | int len = TYPE_LENGTH (type); | |
269 | gdb_byte vbuf[8]; | |
270 | ||
271 | gdb_assert (len <= 8); | |
272 | regcache->cooked_read (BPF_R0_REGNUM, vbuf); | |
273 | memcpy (valbuf, vbuf + 8 - len, len); | |
274 | } | |
275 | ||
276 | /* Store the function return value of type TYPE from VALBUF into REGNAME. */ | |
277 | ||
278 | static void | |
279 | bpf_store_return_value (struct type *type, struct regcache *regcache, | |
280 | const gdb_byte *valbuf) | |
281 | { | |
282 | int len = TYPE_LENGTH (type); | |
283 | gdb_byte vbuf[8]; | |
284 | ||
285 | gdb_assert (len <= 8); | |
286 | memset (vbuf, 0, sizeof (vbuf)); | |
287 | memcpy (vbuf + 8 - len, valbuf, len); | |
288 | regcache->cooked_write (BPF_R0_REGNUM, vbuf); | |
289 | } | |
290 | ||
291 | /* Handle function's return value. */ | |
292 | ||
293 | static enum return_value_convention | |
294 | bpf_return_value (struct gdbarch *gdbarch, struct value *function, | |
295 | struct type *type, struct regcache *regcache, | |
296 | gdb_byte *readbuf, const gdb_byte *writebuf) | |
297 | { | |
298 | int len = TYPE_LENGTH (type); | |
299 | ||
300 | if (len > 8) | |
301 | return RETURN_VALUE_STRUCT_CONVENTION; | |
302 | ||
303 | if (readbuf != NULL) | |
304 | bpf_extract_return_value (type, regcache, readbuf); | |
305 | if (writebuf != NULL) | |
306 | bpf_store_return_value (type, regcache, writebuf); | |
307 | ||
308 | return RETURN_VALUE_REGISTER_CONVENTION; | |
309 | } | |
310 | ||
311 | \f | |
312 | /* Initialize the current architecture based on INFO. If possible, re-use an | |
313 | architecture from ARCHES, which is a list of architectures already created | |
314 | during this debugging session. */ | |
315 | ||
316 | static struct gdbarch * | |
317 | bpf_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | |
318 | { | |
319 | /* If there is already a candidate, use it. */ | |
320 | arches = gdbarch_list_lookup_by_info (arches, &info); | |
321 | if (arches != NULL) | |
322 | return arches->gdbarch; | |
323 | ||
324 | /* Allocate space for the new architecture. */ | |
345bd07c | 325 | bpf_gdbarch_tdep *tdep = new bpf_gdbarch_tdep; |
39791af2 JM |
326 | struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep); |
327 | ||
328 | /* Information about registers, etc. */ | |
329 | set_gdbarch_num_regs (gdbarch, BPF_NUM_REGS); | |
330 | set_gdbarch_register_name (gdbarch, bpf_register_name); | |
331 | set_gdbarch_register_type (gdbarch, bpf_register_type); | |
332 | ||
333 | /* Register numbers of various important registers. */ | |
334 | set_gdbarch_sp_regnum (gdbarch, BPF_R10_REGNUM); | |
335 | set_gdbarch_pc_regnum (gdbarch, BPF_PC_REGNUM); | |
336 | ||
337 | /* Map DWARF2 registers to GDB registers. */ | |
338 | set_gdbarch_dwarf2_reg_to_regnum (gdbarch, bpf_dwarf2_reg_to_regnum); | |
339 | ||
340 | /* Call dummy code. */ | |
341 | set_gdbarch_call_dummy_location (gdbarch, ON_STACK); | |
342 | set_gdbarch_dummy_id (gdbarch, bpf_dummy_id); | |
343 | set_gdbarch_push_dummy_call (gdbarch, bpf_push_dummy_call); | |
344 | ||
345 | /* Returning results. */ | |
346 | set_gdbarch_return_value (gdbarch, bpf_return_value); | |
347 | ||
348 | /* Advance PC across function entry code. */ | |
349 | set_gdbarch_skip_prologue (gdbarch, bpf_skip_prologue); | |
350 | ||
351 | /* Stack grows downward. */ | |
352 | set_gdbarch_inner_than (gdbarch, core_addr_lessthan); | |
353 | ||
354 | /* Breakpoint manipulation. */ | |
355 | set_gdbarch_breakpoint_kind_from_pc (gdbarch, bpf_breakpoint_kind_from_pc); | |
356 | set_gdbarch_sw_breakpoint_from_kind (gdbarch, bpf_sw_breakpoint_from_kind); | |
357 | ||
358 | /* Frame handling. */ | |
359 | set_gdbarch_frame_args_skip (gdbarch, 8); | |
360 | ||
361 | /* Disassembly. */ | |
362 | set_gdbarch_print_insn (gdbarch, bpf_gdb_print_insn); | |
363 | ||
364 | /* Hook in ABI-specific overrides, if they have been registered. */ | |
365 | gdbarch_init_osabi (info, gdbarch); | |
366 | ||
367 | /* Install unwinders. */ | |
368 | frame_unwind_append_unwinder (gdbarch, &bpf_frame_unwind); | |
369 | ||
370 | return gdbarch; | |
371 | } | |
372 | ||
373 | void _initialize_bpf_tdep (); | |
374 | void | |
f39632d9 | 375 | _initialize_bpf_tdep () |
39791af2 JM |
376 | { |
377 | register_gdbarch_init (bfd_arch_bpf, bpf_gdbarch_init); | |
378 | ||
379 | /* Add commands 'set/show debug bpf'. */ | |
380 | add_setshow_zuinteger_cmd ("bpf", class_maintenance, | |
381 | &bpf_debug_flag, | |
382 | _("Set BPF debugging."), | |
383 | _("Show BPF debugging."), | |
384 | _("Enables BPF specific debugging output."), | |
385 | NULL, | |
386 | &show_bpf_debug, | |
387 | &setdebuglist, &showdebuglist); | |
388 | } |