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