1 | /* |
2 | ** Client for the GDB JIT API. |
3 | ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h |
4 | */ |
5 | |
6 | #define lj_gdbjit_c |
7 | #define LUA_CORE |
8 | |
9 | #include "lj_obj.h" |
10 | |
11 | #if LJ_HASJIT |
12 | |
13 | #include "lj_gc.h" |
14 | #include "lj_err.h" |
15 | #include "lj_debug.h" |
16 | #include "lj_frame.h" |
17 | #include "lj_jit.h" |
18 | #include "lj_dispatch.h" |
19 | |
20 | /* This is not compiled in by default. |
21 | ** Enable with -DLUAJIT_USE_GDBJIT in the Makefile and recompile everything. |
22 | */ |
23 | #ifdef LUAJIT_USE_GDBJIT |
24 | |
25 | /* The GDB JIT API allows JIT compilers to pass debug information about |
26 | ** JIT-compiled code back to GDB. You need at least GDB 7.0 or higher |
27 | ** to see it in action. |
28 | ** |
29 | ** This is a passive API, so it works even when not running under GDB |
30 | ** or when attaching to an already running process. Alas, this implies |
31 | ** enabling it always has a non-negligible overhead -- do not use in |
32 | ** release mode! |
33 | ** |
34 | ** The LuaJIT GDB JIT client is rather minimal at the moment. It gives |
35 | ** each trace a symbol name and adds a source location and frame unwind |
36 | ** information. Obviously LuaJIT itself and any embedding C application |
37 | ** should be compiled with debug symbols, too (see the Makefile). |
38 | ** |
39 | ** Traces are named TRACE_1, TRACE_2, ... these correspond to the trace |
40 | ** numbers from -jv or -jdump. Use "break TRACE_1" or "tbreak TRACE_1" etc. |
41 | ** to set breakpoints on specific traces (even ahead of their creation). |
42 | ** |
43 | ** The source location for each trace allows listing the corresponding |
44 | ** source lines with the GDB command "list" (but only if the Lua source |
45 | ** has been loaded from a file). Currently this is always set to the |
46 | ** location where the trace has been started. |
47 | ** |
48 | ** Frame unwind information can be inspected with the GDB command |
49 | ** "info frame". This also allows proper backtraces across JIT-compiled |
50 | ** code with the GDB command "bt". |
51 | ** |
52 | ** You probably want to add the following settings to a .gdbinit file |
53 | ** (or add them to ~/.gdbinit): |
54 | ** set disassembly-flavor intel |
55 | ** set breakpoint pending on |
56 | ** |
57 | ** Here's a sample GDB session: |
58 | ** ------------------------------------------------------------------------ |
59 | |
60 | $ cat >x.lua |
61 | for outer=1,100 do |
62 | for inner=1,100 do end |
63 | end |
64 | ^D |
65 | |
66 | $ luajit -jv x.lua |
67 | [TRACE 1 x.lua:2] |
68 | [TRACE 2 (1/3) x.lua:1 -> 1] |
69 | |
70 | $ gdb --quiet --args luajit x.lua |
71 | (gdb) tbreak TRACE_1 |
72 | Function "TRACE_1" not defined. |
73 | Temporary breakpoint 1 (TRACE_1) pending. |
74 | (gdb) run |
75 | Starting program: luajit x.lua |
76 | |
77 | Temporary breakpoint 1, TRACE_1 () at x.lua:2 |
78 | 2 for inner=1,100 do end |
79 | (gdb) list |
80 | 1 for outer=1,100 do |
81 | 2 for inner=1,100 do end |
82 | 3 end |
83 | (gdb) bt |
84 | #0 TRACE_1 () at x.lua:2 |
85 | #1 0x08053690 in lua_pcall [...] |
86 | [...] |
87 | #7 0x0806ff90 in main [...] |
88 | (gdb) disass TRACE_1 |
89 | Dump of assembler code for function TRACE_1: |
90 | 0xf7fd9fba <TRACE_1+0>: mov DWORD PTR ds:0xf7e0e2a0,0x1 |
91 | 0xf7fd9fc4 <TRACE_1+10>: movsd xmm7,QWORD PTR [edx+0x20] |
92 | [...] |
93 | 0xf7fd9ff8 <TRACE_1+62>: jmp 0xf7fd2014 |
94 | End of assembler dump. |
95 | (gdb) tbreak TRACE_2 |
96 | Function "TRACE_2" not defined. |
97 | Temporary breakpoint 2 (TRACE_2) pending. |
98 | (gdb) cont |
99 | Continuing. |
100 | |
101 | Temporary breakpoint 2, TRACE_2 () at x.lua:1 |
102 | 1 for outer=1,100 do |
103 | (gdb) info frame |
104 | Stack level 0, frame at 0xffffd7c0: |
105 | eip = 0xf7fd9f60 in TRACE_2 (x.lua:1); saved eip 0x8053690 |
106 | called by frame at 0xffffd7e0 |
107 | source language unknown. |
108 | Arglist at 0xffffd78c, args: |
109 | Locals at 0xffffd78c, Previous frame's sp is 0xffffd7c0 |
110 | Saved registers: |
111 | ebx at 0xffffd7ac, ebp at 0xffffd7b8, esi at 0xffffd7b0, edi at 0xffffd7b4, |
112 | eip at 0xffffd7bc |
113 | (gdb) |
114 | |
115 | ** ------------------------------------------------------------------------ |
116 | */ |
117 | |
118 | /* -- GDB JIT API --------------------------------------------------------- */ |
119 | |
120 | /* GDB JIT actions. */ |
121 | enum { |
122 | GDBJIT_NOACTION = 0, |
123 | GDBJIT_REGISTER, |
124 | GDBJIT_UNREGISTER |
125 | }; |
126 | |
127 | /* GDB JIT entry. */ |
128 | typedef struct GDBJITentry { |
129 | struct GDBJITentry *next_entry; |
130 | struct GDBJITentry *prev_entry; |
131 | const char *symfile_addr; |
132 | uint64_t symfile_size; |
133 | } GDBJITentry; |
134 | |
135 | /* GDB JIT descriptor. */ |
136 | typedef struct GDBJITdesc { |
137 | uint32_t version; |
138 | uint32_t action_flag; |
139 | GDBJITentry *relevant_entry; |
140 | GDBJITentry *first_entry; |
141 | } GDBJITdesc; |
142 | |
143 | GDBJITdesc __jit_debug_descriptor = { |
144 | 1, GDBJIT_NOACTION, NULL, NULL |
145 | }; |
146 | |
147 | /* GDB sets a breakpoint at this function. */ |
148 | void LJ_NOINLINE __jit_debug_register_code() |
149 | { |
150 | __asm__ __volatile__("" ); |
151 | }; |
152 | |
153 | /* -- In-memory ELF object definitions ------------------------------------ */ |
154 | |
155 | /* ELF definitions. */ |
156 | typedef struct ELFheader { |
157 | uint8_t emagic[4]; |
158 | uint8_t eclass; |
159 | uint8_t eendian; |
160 | uint8_t eversion; |
161 | uint8_t eosabi; |
162 | uint8_t eabiversion; |
163 | uint8_t epad[7]; |
164 | uint16_t type; |
165 | uint16_t machine; |
166 | uint32_t version; |
167 | uintptr_t entry; |
168 | uintptr_t phofs; |
169 | uintptr_t shofs; |
170 | uint32_t flags; |
171 | uint16_t ehsize; |
172 | uint16_t phentsize; |
173 | uint16_t phnum; |
174 | uint16_t shentsize; |
175 | uint16_t shnum; |
176 | uint16_t shstridx; |
177 | } ELFheader; |
178 | |
179 | typedef struct ELFsectheader { |
180 | uint32_t name; |
181 | uint32_t type; |
182 | uintptr_t flags; |
183 | uintptr_t addr; |
184 | uintptr_t ofs; |
185 | uintptr_t size; |
186 | uint32_t link; |
187 | uint32_t info; |
188 | uintptr_t align; |
189 | uintptr_t entsize; |
190 | } ELFsectheader; |
191 | |
192 | #define ELFSECT_IDX_ABS 0xfff1 |
193 | |
194 | enum { |
195 | ELFSECT_TYPE_PROGBITS = 1, |
196 | ELFSECT_TYPE_SYMTAB = 2, |
197 | ELFSECT_TYPE_STRTAB = 3, |
198 | ELFSECT_TYPE_NOBITS = 8 |
199 | }; |
200 | |
201 | #define ELFSECT_FLAGS_WRITE 1 |
202 | #define ELFSECT_FLAGS_ALLOC 2 |
203 | #define ELFSECT_FLAGS_EXEC 4 |
204 | |
205 | typedef struct ELFsymbol { |
206 | #if LJ_64 |
207 | uint32_t name; |
208 | uint8_t info; |
209 | uint8_t other; |
210 | uint16_t sectidx; |
211 | uintptr_t value; |
212 | uint64_t size; |
213 | #else |
214 | uint32_t name; |
215 | uintptr_t value; |
216 | uint32_t size; |
217 | uint8_t info; |
218 | uint8_t other; |
219 | uint16_t sectidx; |
220 | #endif |
221 | } ELFsymbol; |
222 | |
223 | enum { |
224 | ELFSYM_TYPE_FUNC = 2, |
225 | ELFSYM_TYPE_FILE = 4, |
226 | ELFSYM_BIND_LOCAL = 0 << 4, |
227 | ELFSYM_BIND_GLOBAL = 1 << 4, |
228 | }; |
229 | |
230 | /* DWARF definitions. */ |
231 | #define DW_CIE_VERSION 1 |
232 | |
233 | enum { |
234 | DW_CFA_nop = 0x0, |
235 | DW_CFA_offset_extended = 0x5, |
236 | DW_CFA_def_cfa = 0xc, |
237 | DW_CFA_def_cfa_offset = 0xe, |
238 | DW_CFA_offset_extended_sf = 0x11, |
239 | DW_CFA_advance_loc = 0x40, |
240 | DW_CFA_offset = 0x80 |
241 | }; |
242 | |
243 | enum { |
244 | DW_EH_PE_udata4 = 3, |
245 | DW_EH_PE_textrel = 0x20 |
246 | }; |
247 | |
248 | enum { |
249 | DW_TAG_compile_unit = 0x11 |
250 | }; |
251 | |
252 | enum { |
253 | DW_children_no = 0, |
254 | DW_children_yes = 1 |
255 | }; |
256 | |
257 | enum { |
258 | DW_AT_name = 0x03, |
259 | DW_AT_stmt_list = 0x10, |
260 | DW_AT_low_pc = 0x11, |
261 | DW_AT_high_pc = 0x12 |
262 | }; |
263 | |
264 | enum { |
265 | DW_FORM_addr = 0x01, |
266 | DW_FORM_data4 = 0x06, |
267 | DW_FORM_string = 0x08 |
268 | }; |
269 | |
270 | enum { |
271 | DW_LNS_extended_op = 0, |
272 | DW_LNS_copy = 1, |
273 | DW_LNS_advance_pc = 2, |
274 | DW_LNS_advance_line = 3 |
275 | }; |
276 | |
277 | enum { |
278 | DW_LNE_end_sequence = 1, |
279 | DW_LNE_set_address = 2 |
280 | }; |
281 | |
282 | enum { |
283 | #if LJ_TARGET_X86 |
284 | DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX, |
285 | DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI, |
286 | DW_REG_RA, |
287 | #elif LJ_TARGET_X64 |
288 | /* Yes, the order is strange, but correct. */ |
289 | DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX, |
290 | DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP, |
291 | DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11, |
292 | DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15, |
293 | DW_REG_RA, |
294 | #elif LJ_TARGET_ARM |
295 | DW_REG_SP = 13, |
296 | DW_REG_RA = 14, |
297 | #elif LJ_TARGET_PPC |
298 | DW_REG_SP = 1, |
299 | DW_REG_RA = 65, |
300 | DW_REG_CR = 70, |
301 | #elif LJ_TARGET_MIPS |
302 | DW_REG_SP = 29, |
303 | DW_REG_RA = 31, |
304 | #else |
305 | #error "Unsupported target architecture" |
306 | #endif |
307 | }; |
308 | |
309 | /* Minimal list of sections for the in-memory ELF object. */ |
310 | enum { |
311 | GDBJIT_SECT_NULL, |
312 | GDBJIT_SECT_text, |
313 | GDBJIT_SECT_eh_frame, |
314 | GDBJIT_SECT_shstrtab, |
315 | GDBJIT_SECT_strtab, |
316 | GDBJIT_SECT_symtab, |
317 | GDBJIT_SECT_debug_info, |
318 | GDBJIT_SECT_debug_abbrev, |
319 | GDBJIT_SECT_debug_line, |
320 | GDBJIT_SECT__MAX |
321 | }; |
322 | |
323 | enum { |
324 | GDBJIT_SYM_UNDEF, |
325 | GDBJIT_SYM_FILE, |
326 | GDBJIT_SYM_FUNC, |
327 | GDBJIT_SYM__MAX |
328 | }; |
329 | |
330 | /* In-memory ELF object. */ |
331 | typedef struct GDBJITobj { |
332 | ELFheader hdr; /* ELF header. */ |
333 | ELFsectheader sect[GDBJIT_SECT__MAX]; /* ELF sections. */ |
334 | ELFsymbol sym[GDBJIT_SYM__MAX]; /* ELF symbol table. */ |
335 | uint8_t space[4096]; /* Space for various section data. */ |
336 | } GDBJITobj; |
337 | |
338 | /* Combined structure for GDB JIT entry and ELF object. */ |
339 | typedef struct GDBJITentryobj { |
340 | GDBJITentry entry; |
341 | size_t sz; |
342 | GDBJITobj obj; |
343 | } GDBJITentryobj; |
344 | |
345 | /* Template for in-memory ELF header. */ |
346 | static const ELFheader elfhdr_template = { |
347 | .emagic = { 0x7f, 'E', 'L', 'F' }, |
348 | .eclass = LJ_64 ? 2 : 1, |
349 | .eendian = LJ_ENDIAN_SELECT(1, 2), |
350 | .eversion = 1, |
351 | #if LJ_TARGET_LINUX |
352 | .eosabi = 0, /* Nope, it's not 3. */ |
353 | #elif defined(__FreeBSD__) |
354 | .eosabi = 9, |
355 | #elif defined(__NetBSD__) |
356 | .eosabi = 2, |
357 | #elif defined(__OpenBSD__) |
358 | .eosabi = 12, |
359 | #elif (defined(__sun__) && defined(__svr4__)) |
360 | .eosabi = 6, |
361 | #else |
362 | .eosabi = 0, |
363 | #endif |
364 | .eabiversion = 0, |
365 | .epad = { 0, 0, 0, 0, 0, 0, 0 }, |
366 | .type = 1, |
367 | #if LJ_TARGET_X86 |
368 | .machine = 3, |
369 | #elif LJ_TARGET_X64 |
370 | .machine = 62, |
371 | #elif LJ_TARGET_ARM |
372 | .machine = 40, |
373 | #elif LJ_TARGET_PPC |
374 | .machine = 20, |
375 | #elif LJ_TARGET_MIPS |
376 | .machine = 8, |
377 | #else |
378 | #error "Unsupported target architecture" |
379 | #endif |
380 | .version = 1, |
381 | .entry = 0, |
382 | .phofs = 0, |
383 | .shofs = offsetof(GDBJITobj, sect), |
384 | .flags = 0, |
385 | .ehsize = sizeof(ELFheader), |
386 | .phentsize = 0, |
387 | .phnum = 0, |
388 | .shentsize = sizeof(ELFsectheader), |
389 | .shnum = GDBJIT_SECT__MAX, |
390 | .shstridx = GDBJIT_SECT_shstrtab |
391 | }; |
392 | |
393 | /* -- In-memory ELF object generation ------------------------------------- */ |
394 | |
395 | /* Context for generating the ELF object for the GDB JIT API. */ |
396 | typedef struct GDBJITctx { |
397 | uint8_t *p; /* Pointer to next address in obj.space. */ |
398 | uint8_t *startp; /* Pointer to start address in obj.space. */ |
399 | GCtrace *T; /* Generate symbols for this trace. */ |
400 | uintptr_t mcaddr; /* Machine code address. */ |
401 | MSize szmcode; /* Size of machine code. */ |
402 | MSize spadjp; /* Stack adjustment for parent trace or interpreter. */ |
403 | MSize spadj; /* Stack adjustment for trace itself. */ |
404 | BCLine lineno; /* Starting line number. */ |
405 | const char *filename; /* Starting file name. */ |
406 | size_t objsize; /* Final size of ELF object. */ |
407 | GDBJITobj obj; /* In-memory ELF object. */ |
408 | } GDBJITctx; |
409 | |
410 | /* Add a zero-terminated string. */ |
411 | static uint32_t gdbjit_strz(GDBJITctx *ctx, const char *str) |
412 | { |
413 | uint8_t *p = ctx->p; |
414 | uint32_t ofs = (uint32_t)(p - ctx->startp); |
415 | do { |
416 | *p++ = (uint8_t)*str; |
417 | } while (*str++); |
418 | ctx->p = p; |
419 | return ofs; |
420 | } |
421 | |
422 | /* Append a decimal number. */ |
423 | static void gdbjit_catnum(GDBJITctx *ctx, uint32_t n) |
424 | { |
425 | if (n >= 10) { uint32_t m = n / 10; n = n % 10; gdbjit_catnum(ctx, m); } |
426 | *ctx->p++ = '0' + n; |
427 | } |
428 | |
429 | /* Add a ULEB128 value. */ |
430 | static void gdbjit_uleb128(GDBJITctx *ctx, uint32_t v) |
431 | { |
432 | uint8_t *p = ctx->p; |
433 | for (; v >= 0x80; v >>= 7) |
434 | *p++ = (uint8_t)((v & 0x7f) | 0x80); |
435 | *p++ = (uint8_t)v; |
436 | ctx->p = p; |
437 | } |
438 | |
439 | /* Add a SLEB128 value. */ |
440 | static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v) |
441 | { |
442 | uint8_t *p = ctx->p; |
443 | for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7) |
444 | *p++ = (uint8_t)((v & 0x7f) | 0x80); |
445 | *p++ = (uint8_t)(v & 0x7f); |
446 | ctx->p = p; |
447 | } |
448 | |
449 | /* Shortcuts to generate DWARF structures. */ |
450 | #define DB(x) (*p++ = (x)) |
451 | #define DI8(x) (*(int8_t *)p = (x), p++) |
452 | #define DU16(x) (*(uint16_t *)p = (x), p += 2) |
453 | #define DU32(x) (*(uint32_t *)p = (x), p += 4) |
454 | #define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t)) |
455 | #define DUV(x) (ctx->p = p, gdbjit_uleb128(ctx, (x)), p = ctx->p) |
456 | #define DSV(x) (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p) |
457 | #define DSTR(str) (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p) |
458 | #define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop |
459 | #define DSECT(name, stmt) \ |
460 | { uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \ |
461 | *szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); } \ |
462 | |
463 | /* Initialize ELF section headers. */ |
464 | static void LJ_FASTCALL gdbjit_secthdr(GDBJITctx *ctx) |
465 | { |
466 | ELFsectheader *sect; |
467 | |
468 | *ctx->p++ = '\0'; /* Empty string at start of string table. */ |
469 | |
470 | #define SECTDEF(id, tp, al) \ |
471 | sect = &ctx->obj.sect[GDBJIT_SECT_##id]; \ |
472 | sect->name = gdbjit_strz(ctx, "." #id); \ |
473 | sect->type = ELFSECT_TYPE_##tp; \ |
474 | sect->align = (al) |
475 | |
476 | SECTDEF(text, NOBITS, 16); |
477 | sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC; |
478 | sect->addr = ctx->mcaddr; |
479 | sect->ofs = 0; |
480 | sect->size = ctx->szmcode; |
481 | |
482 | SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t)); |
483 | sect->flags = ELFSECT_FLAGS_ALLOC; |
484 | |
485 | SECTDEF(shstrtab, STRTAB, 1); |
486 | SECTDEF(strtab, STRTAB, 1); |
487 | |
488 | SECTDEF(symtab, SYMTAB, sizeof(uintptr_t)); |
489 | sect->ofs = offsetof(GDBJITobj, sym); |
490 | sect->size = sizeof(ctx->obj.sym); |
491 | sect->link = GDBJIT_SECT_strtab; |
492 | sect->entsize = sizeof(ELFsymbol); |
493 | sect->info = GDBJIT_SYM_FUNC; |
494 | |
495 | SECTDEF(debug_info, PROGBITS, 1); |
496 | SECTDEF(debug_abbrev, PROGBITS, 1); |
497 | SECTDEF(debug_line, PROGBITS, 1); |
498 | |
499 | #undef SECTDEF |
500 | } |
501 | |
502 | /* Initialize symbol table. */ |
503 | static void LJ_FASTCALL gdbjit_symtab(GDBJITctx *ctx) |
504 | { |
505 | ELFsymbol *sym; |
506 | |
507 | *ctx->p++ = '\0'; /* Empty string at start of string table. */ |
508 | |
509 | sym = &ctx->obj.sym[GDBJIT_SYM_FILE]; |
510 | sym->name = gdbjit_strz(ctx, "JIT mcode" ); |
511 | sym->sectidx = ELFSECT_IDX_ABS; |
512 | sym->info = ELFSYM_TYPE_FILE|ELFSYM_BIND_LOCAL; |
513 | |
514 | sym = &ctx->obj.sym[GDBJIT_SYM_FUNC]; |
515 | sym->name = gdbjit_strz(ctx, "TRACE_" ); ctx->p--; |
516 | gdbjit_catnum(ctx, ctx->T->traceno); *ctx->p++ = '\0'; |
517 | sym->sectidx = GDBJIT_SECT_text; |
518 | sym->value = 0; |
519 | sym->size = ctx->szmcode; |
520 | sym->info = ELFSYM_TYPE_FUNC|ELFSYM_BIND_GLOBAL; |
521 | } |
522 | |
523 | /* Initialize .eh_frame section. */ |
524 | static void LJ_FASTCALL gdbjit_ehframe(GDBJITctx *ctx) |
525 | { |
526 | uint8_t *p = ctx->p; |
527 | uint8_t *framep = p; |
528 | |
529 | /* Emit DWARF EH CIE. */ |
530 | DSECT(CIE, |
531 | DU32(0); /* Offset to CIE itself. */ |
532 | DB(DW_CIE_VERSION); |
533 | DSTR("zR" ); /* Augmentation. */ |
534 | DUV(1); /* Code alignment factor. */ |
535 | DSV(-(int32_t)sizeof(uintptr_t)); /* Data alignment factor. */ |
536 | DB(DW_REG_RA); /* Return address register. */ |
537 | DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4); /* Augmentation data. */ |
538 | DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t)); |
539 | #if LJ_TARGET_PPC |
540 | DB(DW_CFA_offset_extended_sf); DB(DW_REG_RA); DSV(-1); |
541 | #else |
542 | DB(DW_CFA_offset|DW_REG_RA); DUV(1); |
543 | #endif |
544 | DALIGNNOP(sizeof(uintptr_t)); |
545 | ) |
546 | |
547 | /* Emit DWARF EH FDE. */ |
548 | DSECT(FDE, |
549 | DU32((uint32_t)(p-framep)); /* Offset to CIE. */ |
550 | DU32(0); /* Machine code offset relative to .text. */ |
551 | DU32(ctx->szmcode); /* Machine code length. */ |
552 | DB(0); /* Augmentation data. */ |
553 | /* Registers saved in CFRAME. */ |
554 | #if LJ_TARGET_X86 |
555 | DB(DW_CFA_offset|DW_REG_BP); DUV(2); |
556 | DB(DW_CFA_offset|DW_REG_DI); DUV(3); |
557 | DB(DW_CFA_offset|DW_REG_SI); DUV(4); |
558 | DB(DW_CFA_offset|DW_REG_BX); DUV(5); |
559 | #elif LJ_TARGET_X64 |
560 | DB(DW_CFA_offset|DW_REG_BP); DUV(2); |
561 | DB(DW_CFA_offset|DW_REG_BX); DUV(3); |
562 | DB(DW_CFA_offset|DW_REG_15); DUV(4); |
563 | DB(DW_CFA_offset|DW_REG_14); DUV(5); |
564 | /* Extra registers saved for JIT-compiled code. */ |
565 | DB(DW_CFA_offset|DW_REG_13); DUV(9); |
566 | DB(DW_CFA_offset|DW_REG_12); DUV(10); |
567 | #elif LJ_TARGET_ARM |
568 | { |
569 | int i; |
570 | for (i = 11; i >= 4; i--) { DB(DW_CFA_offset|i); DUV(2+(11-i)); } |
571 | } |
572 | #elif LJ_TARGET_PPC |
573 | { |
574 | int i; |
575 | DB(DW_CFA_offset_extended); DB(DW_REG_CR); DUV(55); |
576 | for (i = 14; i <= 31; i++) { |
577 | DB(DW_CFA_offset|i); DUV(37+(31-i)); |
578 | DB(DW_CFA_offset|32|i); DUV(2+2*(31-i)); |
579 | } |
580 | } |
581 | #elif LJ_TARGET_MIPS |
582 | { |
583 | int i; |
584 | DB(DW_CFA_offset|30); DUV(2); |
585 | for (i = 23; i >= 16; i--) { DB(DW_CFA_offset|i); DUV(26-i); } |
586 | for (i = 30; i >= 20; i -= 2) { DB(DW_CFA_offset|32|i); DUV(42-i); } |
587 | } |
588 | #else |
589 | #error "Unsupported target architecture" |
590 | #endif |
591 | if (ctx->spadjp != ctx->spadj) { /* Parent/interpreter stack frame size. */ |
592 | DB(DW_CFA_def_cfa_offset); DUV(ctx->spadjp); |
593 | DB(DW_CFA_advance_loc|1); /* Only an approximation. */ |
594 | } |
595 | DB(DW_CFA_def_cfa_offset); DUV(ctx->spadj); /* Trace stack frame size. */ |
596 | DALIGNNOP(sizeof(uintptr_t)); |
597 | ) |
598 | |
599 | ctx->p = p; |
600 | } |
601 | |
602 | /* Initialize .debug_info section. */ |
603 | static void LJ_FASTCALL gdbjit_debuginfo(GDBJITctx *ctx) |
604 | { |
605 | uint8_t *p = ctx->p; |
606 | |
607 | DSECT(info, |
608 | DU16(2); /* DWARF version. */ |
609 | DU32(0); /* Abbrev offset. */ |
610 | DB(sizeof(uintptr_t)); /* Pointer size. */ |
611 | |
612 | DUV(1); /* Abbrev #1: DW_TAG_compile_unit. */ |
613 | DSTR(ctx->filename); /* DW_AT_name. */ |
614 | DADDR(ctx->mcaddr); /* DW_AT_low_pc. */ |
615 | DADDR(ctx->mcaddr + ctx->szmcode); /* DW_AT_high_pc. */ |
616 | DU32(0); /* DW_AT_stmt_list. */ |
617 | ) |
618 | |
619 | ctx->p = p; |
620 | } |
621 | |
622 | /* Initialize .debug_abbrev section. */ |
623 | static void LJ_FASTCALL gdbjit_debugabbrev(GDBJITctx *ctx) |
624 | { |
625 | uint8_t *p = ctx->p; |
626 | |
627 | /* Abbrev #1: DW_TAG_compile_unit. */ |
628 | DUV(1); DUV(DW_TAG_compile_unit); |
629 | DB(DW_children_no); |
630 | DUV(DW_AT_name); DUV(DW_FORM_string); |
631 | DUV(DW_AT_low_pc); DUV(DW_FORM_addr); |
632 | DUV(DW_AT_high_pc); DUV(DW_FORM_addr); |
633 | DUV(DW_AT_stmt_list); DUV(DW_FORM_data4); |
634 | DB(0); DB(0); |
635 | |
636 | ctx->p = p; |
637 | } |
638 | |
639 | #define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op))) |
640 | |
641 | /* Initialize .debug_line section. */ |
642 | static void LJ_FASTCALL gdbjit_debugline(GDBJITctx *ctx) |
643 | { |
644 | uint8_t *p = ctx->p; |
645 | |
646 | DSECT(line, |
647 | DU16(2); /* DWARF version. */ |
648 | DSECT(header, |
649 | DB(1); /* Minimum instruction length. */ |
650 | DB(1); /* is_stmt. */ |
651 | DI8(0); /* Line base for special opcodes. */ |
652 | DB(2); /* Line range for special opcodes. */ |
653 | DB(3+1); /* Opcode base at DW_LNS_advance_line+1. */ |
654 | DB(0); DB(1); DB(1); /* Standard opcode lengths. */ |
655 | /* Directory table. */ |
656 | DB(0); |
657 | /* File name table. */ |
658 | DSTR(ctx->filename); DUV(0); DUV(0); DUV(0); |
659 | DB(0); |
660 | ) |
661 | |
662 | DLNE(DW_LNE_set_address, sizeof(uintptr_t)); DADDR(ctx->mcaddr); |
663 | if (ctx->lineno) { |
664 | DB(DW_LNS_advance_line); DSV(ctx->lineno-1); |
665 | } |
666 | DB(DW_LNS_copy); |
667 | DB(DW_LNS_advance_pc); DUV(ctx->szmcode); |
668 | DLNE(DW_LNE_end_sequence, 0); |
669 | ) |
670 | |
671 | ctx->p = p; |
672 | } |
673 | |
674 | #undef DLNE |
675 | |
676 | /* Undef shortcuts. */ |
677 | #undef DB |
678 | #undef DI8 |
679 | #undef DU16 |
680 | #undef DU32 |
681 | #undef DADDR |
682 | #undef DUV |
683 | #undef DSV |
684 | #undef DSTR |
685 | #undef DALIGNNOP |
686 | #undef DSECT |
687 | |
688 | /* Type of a section initializer callback. */ |
689 | typedef void (LJ_FASTCALL *GDBJITinitf)(GDBJITctx *ctx); |
690 | |
691 | /* Call section initializer and set the section offset and size. */ |
692 | static void gdbjit_initsect(GDBJITctx *ctx, int sect, GDBJITinitf initf) |
693 | { |
694 | ctx->startp = ctx->p; |
695 | ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj); |
696 | initf(ctx); |
697 | ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp); |
698 | } |
699 | |
700 | #define SECTALIGN(p, a) \ |
701 | ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1))) |
702 | |
703 | /* Build in-memory ELF object. */ |
704 | static void gdbjit_buildobj(GDBJITctx *ctx) |
705 | { |
706 | GDBJITobj *obj = &ctx->obj; |
707 | /* Fill in ELF header and clear structures. */ |
708 | memcpy(&obj->hdr, &elfhdr_template, sizeof(ELFheader)); |
709 | memset(&obj->sect, 0, sizeof(ELFsectheader)*GDBJIT_SECT__MAX); |
710 | memset(&obj->sym, 0, sizeof(ELFsymbol)*GDBJIT_SYM__MAX); |
711 | /* Initialize sections. */ |
712 | ctx->p = obj->space; |
713 | gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab, gdbjit_secthdr); |
714 | gdbjit_initsect(ctx, GDBJIT_SECT_strtab, gdbjit_symtab); |
715 | gdbjit_initsect(ctx, GDBJIT_SECT_debug_info, gdbjit_debuginfo); |
716 | gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev, gdbjit_debugabbrev); |
717 | gdbjit_initsect(ctx, GDBJIT_SECT_debug_line, gdbjit_debugline); |
718 | SECTALIGN(ctx->p, sizeof(uintptr_t)); |
719 | gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame, gdbjit_ehframe); |
720 | ctx->objsize = (size_t)((char *)ctx->p - (char *)obj); |
721 | lua_assert(ctx->objsize < sizeof(GDBJITobj)); |
722 | } |
723 | |
724 | #undef SECTALIGN |
725 | |
726 | /* -- Interface to GDB JIT API -------------------------------------------- */ |
727 | |
728 | /* Add new entry to GDB JIT symbol chain. */ |
729 | static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx) |
730 | { |
731 | /* Allocate memory for GDB JIT entry and ELF object. */ |
732 | MSize sz = (MSize)(sizeof(GDBJITentryobj) - sizeof(GDBJITobj) + ctx->objsize); |
733 | GDBJITentryobj *eo = lj_mem_newt(L, sz, GDBJITentryobj); |
734 | memcpy(&eo->obj, &ctx->obj, ctx->objsize); /* Copy ELF object. */ |
735 | eo->sz = sz; |
736 | ctx->T->gdbjit_entry = (void *)eo; |
737 | /* Link new entry to chain and register it. */ |
738 | eo->entry.prev_entry = NULL; |
739 | eo->entry.next_entry = __jit_debug_descriptor.first_entry; |
740 | if (eo->entry.next_entry) |
741 | eo->entry.next_entry->prev_entry = &eo->entry; |
742 | eo->entry.symfile_addr = (const char *)&eo->obj; |
743 | eo->entry.symfile_size = ctx->objsize; |
744 | __jit_debug_descriptor.first_entry = &eo->entry; |
745 | __jit_debug_descriptor.relevant_entry = &eo->entry; |
746 | __jit_debug_descriptor.action_flag = GDBJIT_REGISTER; |
747 | __jit_debug_register_code(); |
748 | } |
749 | |
750 | /* Add debug info for newly compiled trace and notify GDB. */ |
751 | void lj_gdbjit_addtrace(jit_State *J, GCtrace *T) |
752 | { |
753 | GDBJITctx ctx; |
754 | GCproto *pt = &gcref(T->startpt)->pt; |
755 | TraceNo parent = T->ir[REF_BASE].op1; |
756 | const BCIns *startpc = mref(T->startpc, const BCIns); |
757 | ctx.T = T; |
758 | ctx.mcaddr = (uintptr_t)T->mcode; |
759 | ctx.szmcode = T->szmcode; |
760 | ctx.spadjp = CFRAME_SIZE_JIT + |
761 | (MSize)(parent ? traceref(J, parent)->spadjust : 0); |
762 | ctx.spadj = CFRAME_SIZE_JIT + T->spadjust; |
763 | lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc); |
764 | ctx.lineno = lj_debug_line(pt, proto_bcpos(pt, startpc)); |
765 | ctx.filename = proto_chunknamestr(pt); |
766 | if (*ctx.filename == '@' || *ctx.filename == '=') |
767 | ctx.filename++; |
768 | else |
769 | ctx.filename = "(string)" ; |
770 | gdbjit_buildobj(&ctx); |
771 | gdbjit_newentry(J->L, &ctx); |
772 | } |
773 | |
774 | /* Delete debug info for trace and notify GDB. */ |
775 | void lj_gdbjit_deltrace(jit_State *J, GCtrace *T) |
776 | { |
777 | GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry; |
778 | if (eo) { |
779 | if (eo->entry.prev_entry) |
780 | eo->entry.prev_entry->next_entry = eo->entry.next_entry; |
781 | else |
782 | __jit_debug_descriptor.first_entry = eo->entry.next_entry; |
783 | if (eo->entry.next_entry) |
784 | eo->entry.next_entry->prev_entry = eo->entry.prev_entry; |
785 | __jit_debug_descriptor.relevant_entry = &eo->entry; |
786 | __jit_debug_descriptor.action_flag = GDBJIT_UNREGISTER; |
787 | __jit_debug_register_code(); |
788 | lj_mem_free(J2G(J), eo, eo->sz); |
789 | } |
790 | } |
791 | |
792 | #endif |
793 | #endif |
794 | |