summaryrefslogtreecommitdiff
path: root/src/lj_gdbjit.c
diff options
context:
space:
mode:
authorMike Pall <mike>2009-12-08 19:46:35 +0100
committerMike Pall <mike>2009-12-08 19:46:35 +0100
commit55b16959717084884fd4a0cbae6d19e3786c20c7 (patch)
treec8a07a43c13679751ed25a9d06796e9e7b2134a6 /src/lj_gdbjit.c
downloadluajit-2.0.0-beta1.tar.gz
luajit-2.0.0-beta1.tar.bz2
luajit-2.0.0-beta1.zip
RELEASE LuaJIT-2.0.0-beta1v2.0.0-beta1
Diffstat (limited to 'src/lj_gdbjit.c')
-rw-r--r--src/lj_gdbjit.c739
1 files changed, 739 insertions, 0 deletions
diff --git a/src/lj_gdbjit.c b/src/lj_gdbjit.c
new file mode 100644
index 00000000..dfec188a
--- /dev/null
+++ b/src/lj_gdbjit.c
@@ -0,0 +1,739 @@
1/*
2** Client for the GDB JIT API.
3** Copyright (C) 2005-2009 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_str.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
61for outer=1,100 do
62 for inner=1,100 do end
63end
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
72Function "TRACE_1" not defined.
73Temporary breakpoint 1 (TRACE_1) pending.
74(gdb) run
75Starting program: luajit x.lua
76
77Temporary breakpoint 1, TRACE_1 () at x.lua:2
782 for inner=1,100 do end
79(gdb) list
801 for outer=1,100 do
812 for inner=1,100 do end
823 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
89Dump of assembler code for function TRACE_1:
900xf7fd9fba <TRACE_1+0>: mov DWORD PTR ds:0xf7e0e2a0,0x1
910xf7fd9fc4 <TRACE_1+10>: movsd xmm7,QWORD PTR [edx+0x20]
92[...]
930xf7fd9ff8 <TRACE_1+62>: jmp 0xf7fd2014
94End of assembler dump.
95(gdb) tbreak TRACE_2
96Function "TRACE_2" not defined.
97Temporary breakpoint 2 (TRACE_2) pending.
98(gdb) cont
99Continuing.
100
101Temporary breakpoint 2, TRACE_2 () at x.lua:1
1021 for outer=1,100 do
103(gdb) info frame
104Stack 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. */
121enum {
122 GDBJIT_NOACTION = 0,
123 GDBJIT_REGISTER,
124 GDBJIT_UNREGISTER
125};
126
127/* GDB JIT entry. */
128typedef 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. */
136typedef struct GDBJITdesc {
137 uint32_t version;
138 uint32_t action_flag;
139 GDBJITentry *relevant_entry;
140 GDBJITentry *first_entry;
141} GDBJITdesc;
142
143GDBJITdesc __jit_debug_descriptor = {
144 1, GDBJIT_NOACTION, NULL, NULL
145};
146
147/* GDB sets a breakpoint at this function. */
148void LJ_NOINLINE __jit_debug_register_code()
149{
150 __asm__ __volatile__("");
151};
152
153/* -- In-memory ELF object definitions ------------------------------------ */
154
155/* ELF definitions. */
156typedef 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
179typedef 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
194enum {
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
205typedef 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
223enum {
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
233enum {
234 DW_CFA_nop = 0x0,
235 DW_CFA_def_cfa = 0xc,
236 DW_CFA_def_cfa_offset = 0xe,
237 DW_CFA_advance_loc = 0x40,
238 DW_CFA_offset = 0x80
239};
240
241enum {
242 DW_EH_PE_udata4 = 3,
243 DW_EH_PE_textrel = 0x20
244};
245
246enum {
247 DW_TAG_compile_unit = 0x11
248};
249
250enum {
251 DW_children_no = 0,
252 DW_children_yes = 1
253};
254
255enum {
256 DW_AT_name = 0x03,
257 DW_AT_stmt_list = 0x10,
258 DW_AT_low_pc = 0x11,
259 DW_AT_high_pc = 0x12
260};
261
262enum {
263 DW_FORM_addr = 0x01,
264 DW_FORM_data4 = 0x06,
265 DW_FORM_string = 0x08
266};
267
268enum {
269 DW_LNS_extended_op = 0,
270 DW_LNS_copy = 1,
271 DW_LNS_advance_pc = 2,
272 DW_LNS_advance_line = 3
273};
274
275enum {
276 DW_LNE_end_sequence = 1,
277 DW_LNE_set_address = 2
278};
279
280enum {
281#if LJ_TARGET_X86
282 DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX,
283 DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI,
284 DW_REG_RA,
285#elif LJ_TARGET_X64
286 /* Yes, the order is strange, but correct. */
287 DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX,
288 DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP,
289 DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11,
290 DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15,
291 DW_REG_RA,
292#else
293#error "Unsupported target architecture"
294#endif
295};
296
297/* Minimal list of sections for the in-memory ELF object. */
298enum {
299 GDBJIT_SECT_NULL,
300 GDBJIT_SECT_text,
301 GDBJIT_SECT_eh_frame,
302 GDBJIT_SECT_shstrtab,
303 GDBJIT_SECT_strtab,
304 GDBJIT_SECT_symtab,
305 GDBJIT_SECT_debug_info,
306 GDBJIT_SECT_debug_abbrev,
307 GDBJIT_SECT_debug_line,
308 GDBJIT_SECT__MAX
309};
310
311enum {
312 GDBJIT_SYM_UNDEF,
313 GDBJIT_SYM_FILE,
314 GDBJIT_SYM_FUNC,
315 GDBJIT_SYM__MAX
316};
317
318/* In-memory ELF object. */
319typedef struct GDBJITobj {
320 ELFheader hdr; /* ELF header. */
321 ELFsectheader sect[GDBJIT_SECT__MAX]; /* ELF sections. */
322 ELFsymbol sym[GDBJIT_SYM__MAX]; /* ELF symbol table. */
323 uint8_t space[4096]; /* Space for various section data. */
324} GDBJITobj;
325
326/* Combined structure for GDB JIT entry and ELF object. */
327typedef struct GDBJITentryobj {
328 GDBJITentry entry;
329 size_t sz;
330 GDBJITobj obj;
331} GDBJITentryobj;
332
333/* Template for in-memory ELF header. */
334static const ELFheader elfhdr_template = {
335 .emagic = { 0x7f, 'E', 'L', 'F' },
336 .eclass = LJ_64 ? 2 : 1,
337 .eendian = LJ_ENDIAN_SELECT(1, 2),
338 .eversion = 1,
339#if defined(__linux__)
340 .eosabi = 0, /* Nope, it's not 3. */
341#elif defined(__FreeBSD__)
342 .eosabi = 9,
343#elif defined(__NetBSD__)
344 .eosabi = 2,
345#elif defined(__OpenBSD__)
346 .eosabi = 12,
347#elif defined(__solaris__)
348 .eosabi = 6,
349#else
350 .eosabi = 0,
351#endif
352 .eabiversion = 0,
353 .epad = { 0, 0, 0, 0, 0, 0, 0 },
354 .type = 1,
355#if LJ_TARGET_X86
356 .machine = 3,
357#elif LJ_TARGET_X64
358 .machine = 62,
359#else
360#error "Unsupported target architecture"
361#endif
362 .version = 1,
363 .entry = 0,
364 .phofs = 0,
365 .shofs = offsetof(GDBJITobj, sect),
366 .flags = 0,
367 .ehsize = sizeof(ELFheader),
368 .phentsize = 0,
369 .phnum = 0,
370 .shentsize = sizeof(ELFsectheader),
371 .shnum = GDBJIT_SECT__MAX,
372 .shstridx = GDBJIT_SECT_shstrtab
373};
374
375/* -- In-memory ELF object generation ------------------------------------- */
376
377/* Context for generating the ELF object for the GDB JIT API. */
378typedef struct GDBJITctx {
379 uint8_t *p; /* Pointer to next address in obj.space. */
380 uint8_t *startp; /* Pointer to start address in obj.space. */
381 Trace *T; /* Generate symbols for this trace. */
382 uintptr_t mcaddr; /* Machine code address. */
383 MSize szmcode; /* Size of machine code. */
384 MSize spadjp; /* Stack adjustment for parent trace or interpreter. */
385 MSize spadj; /* Stack adjustment for trace itself. */
386 BCLine lineno; /* Starting line number. */
387 const char *filename; /* Starting file name. */
388 const char *trname; /* Name of trace. */
389 size_t objsize; /* Final size of ELF object. */
390 GDBJITobj obj; /* In-memory ELF object. */
391} GDBJITctx;
392
393/* Add a zero-terminated string. */
394static uint32_t gdbjit_strz(GDBJITctx *ctx, const char *str)
395{
396 uint8_t *p = ctx->p;
397 uint32_t ofs = (uint32_t)(p - ctx->startp);
398 do {
399 *p++ = (uint8_t)*str;
400 } while (*str++);
401 ctx->p = p;
402 return ofs;
403}
404
405/* Add a ULEB128 value. */
406static void gdbjit_uleb128(GDBJITctx *ctx, uint32_t v)
407{
408 uint8_t *p = ctx->p;
409 for (; v >= 0x80; v >>= 7)
410 *p++ = (uint8_t)((v & 0x7f) | 0x80);
411 *p++ = (uint8_t)v;
412 ctx->p = p;
413}
414
415/* Add a SLEB128 value. */
416static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
417{
418 uint8_t *p = ctx->p;
419 for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7)
420 *p++ = (uint8_t)((v & 0x7f) | 0x80);
421 *p++ = (uint8_t)(v & 0x7f);
422 ctx->p = p;
423}
424
425/* Shortcuts to generate DWARF structures. */
426#define DB(x) (*p++ = (x))
427#define DI8(x) (*(int8_t *)p = (x), p++)
428#define DU16(x) (*(uint16_t *)p = (x), p += 2)
429#define DU32(x) (*(uint32_t *)p = (x), p += 4)
430#define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t))
431#define DUV(x) (ctx->p = p, gdbjit_uleb128(ctx, (x)), p = ctx->p)
432#define DSV(x) (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p)
433#define DSTR(str) (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p)
434#define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
435#define DSECT(name, stmt) \
436 { uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
437 *szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); } \
438
439/* Initialize ELF section headers. */
440static void LJ_FASTCALL gdbjit_secthdr(GDBJITctx *ctx)
441{
442 ELFsectheader *sect;
443
444 *ctx->p++ = '\0'; /* Empty string at start of string table. */
445
446#define SECTDEF(id, tp, al) \
447 sect = &ctx->obj.sect[GDBJIT_SECT_##id]; \
448 sect->name = gdbjit_strz(ctx, "." #id); \
449 sect->type = ELFSECT_TYPE_##tp; \
450 sect->align = (al)
451
452 SECTDEF(text, NOBITS, 16);
453 sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC;
454 sect->addr = ctx->mcaddr;
455 sect->ofs = 0;
456 sect->size = ctx->szmcode;
457
458 SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t));
459 sect->flags = ELFSECT_FLAGS_ALLOC;
460
461 SECTDEF(shstrtab, STRTAB, 1);
462 SECTDEF(strtab, STRTAB, 1);
463
464 SECTDEF(symtab, SYMTAB, sizeof(uintptr_t));
465 sect->ofs = offsetof(GDBJITobj, sym);
466 sect->size = sizeof(ctx->obj.sym);
467 sect->link = GDBJIT_SECT_strtab;
468 sect->entsize = sizeof(ELFsymbol);
469 sect->info = GDBJIT_SYM_FUNC;
470
471 SECTDEF(debug_info, PROGBITS, 1);
472 SECTDEF(debug_abbrev, PROGBITS, 1);
473 SECTDEF(debug_line, PROGBITS, 1);
474
475#undef SECTDEF
476}
477
478/* Initialize symbol table. */
479static void LJ_FASTCALL gdbjit_symtab(GDBJITctx *ctx)
480{
481 ELFsymbol *sym;
482
483 *ctx->p++ = '\0'; /* Empty string at start of string table. */
484
485 sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
486 sym->name = gdbjit_strz(ctx, "JIT mcode");
487 sym->sectidx = ELFSECT_IDX_ABS;
488 sym->info = ELFSYM_TYPE_FILE|ELFSYM_BIND_LOCAL;
489
490 sym = &ctx->obj.sym[GDBJIT_SYM_FUNC];
491 sym->name = gdbjit_strz(ctx, ctx->trname);
492 sym->sectidx = GDBJIT_SECT_text;
493 sym->value = 0;
494 sym->size = ctx->szmcode;
495 sym->info = ELFSYM_TYPE_FUNC|ELFSYM_BIND_GLOBAL;
496}
497
498/* Initialize .eh_frame section. */
499static void LJ_FASTCALL gdbjit_ehframe(GDBJITctx *ctx)
500{
501 uint8_t *p = ctx->p;
502 uint8_t *framep = p;
503
504 /* Emit DWARF EH CIE. */
505 DSECT(CIE,
506 DU32(0); /* Offset to CIE itself. */
507 DB(DW_CIE_VERSION);
508 DSTR("zR"); /* Augmentation. */
509 DUV(1); /* Code alignment factor. */
510 DSV(-(int32_t)sizeof(uintptr_t)); /* Data alignment factor. */
511 DB(DW_REG_RA); /* Return address register. */
512 DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4); /* Augmentation data. */
513 DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
514 DB(DW_CFA_offset|DW_REG_RA); DUV(1);
515 DALIGNNOP(sizeof(uintptr_t));
516 )
517
518 /* Emit DWARF EH FDE. */
519 DSECT(FDE,
520 DU32((uint32_t)(p-framep)); /* Offset to CIE. */
521 DU32(0); /* Machine code offset relative to .text. */
522 DU32(ctx->szmcode); /* Machine code length. */
523 DB(0); /* Augmentation data. */
524 /* Registers saved in CFRAME. */
525#if LJ_TARGET_X86
526 DB(DW_CFA_offset|DW_REG_BP); DUV(2);
527 DB(DW_CFA_offset|DW_REG_DI); DUV(3);
528 DB(DW_CFA_offset|DW_REG_SI); DUV(4);
529 DB(DW_CFA_offset|DW_REG_BX); DUV(5);
530#elif LJ_TARGET_X64
531 /* Add saved registers for x64 CFRAME. */
532#else
533#error "Unsupported target architecture"
534#endif
535 if (ctx->spadjp != ctx->spadj) { /* Parent/interpreter stack frame size. */
536 DB(DW_CFA_def_cfa_offset); DUV(ctx->spadjp);
537 DB(DW_CFA_advance_loc|1); /* Only an approximation. */
538 }
539 DB(DW_CFA_def_cfa_offset); DUV(ctx->spadj); /* Trace stack frame size. */
540 DALIGNNOP(sizeof(uintptr_t));
541 )
542
543 ctx->p = p;
544}
545
546/* Initialize .debug_info section. */
547static void LJ_FASTCALL gdbjit_debuginfo(GDBJITctx *ctx)
548{
549 uint8_t *p = ctx->p;
550
551 DSECT(info,
552 DU16(2); /* DWARF version. */
553 DU32(0); /* Abbrev offset. */
554 DB(sizeof(uintptr_t)); /* Pointer size. */
555
556 DUV(1); /* Abbrev #1: DW_TAG_compile_unit. */
557 DSTR(ctx->filename); /* DW_AT_name. */
558 DADDR(ctx->mcaddr); /* DW_AT_low_pc. */
559 DADDR(ctx->mcaddr + ctx->szmcode); /* DW_AT_high_pc. */
560 DU32(0); /* DW_AT_stmt_list. */
561 )
562
563 ctx->p = p;
564}
565
566/* Initialize .debug_abbrev section. */
567static void LJ_FASTCALL gdbjit_debugabbrev(GDBJITctx *ctx)
568{
569 uint8_t *p = ctx->p;
570
571 /* Abbrev #1: DW_TAG_compile_unit. */
572 DUV(1); DUV(DW_TAG_compile_unit);
573 DB(DW_children_no);
574 DUV(DW_AT_name); DUV(DW_FORM_string);
575 DUV(DW_AT_low_pc); DUV(DW_FORM_addr);
576 DUV(DW_AT_high_pc); DUV(DW_FORM_addr);
577 DUV(DW_AT_stmt_list); DUV(DW_FORM_data4);
578 DB(0); DB(0);
579
580 ctx->p = p;
581}
582
583#define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
584
585/* Initialize .debug_line section. */
586static void LJ_FASTCALL gdbjit_debugline(GDBJITctx *ctx)
587{
588 uint8_t *p = ctx->p;
589
590 DSECT(line,
591 DU16(2); /* DWARF version. */
592 DSECT(header,
593 DB(1); /* Minimum instruction length. */
594 DB(1); /* is_stmt. */
595 DI8(0); /* Line base for special opcodes. */
596 DB(2); /* Line range for special opcodes. */
597 DB(3+1); /* Opcode base at DW_LNS_advance_line+1. */
598 DB(0); DB(1); DB(1); /* Standard opcode lengths. */
599 /* Directory table. */
600 DB(0);
601 /* File name table. */
602 DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
603 DB(0);
604 )
605
606 DLNE(DW_LNE_set_address, sizeof(uintptr_t)); DADDR(ctx->mcaddr);
607 if (ctx->lineno) {
608 DB(DW_LNS_advance_line); DSV(ctx->lineno-1);
609 }
610 DB(DW_LNS_copy);
611 DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
612 DLNE(DW_LNE_end_sequence, 0);
613 )
614
615 ctx->p = p;
616}
617
618#undef DLNE
619
620/* Undef shortcuts. */
621#undef DB
622#undef DI8
623#undef DU16
624#undef DU32
625#undef DADDR
626#undef DUV
627#undef DSV
628#undef DSTR
629#undef DALIGNNOP
630#undef DSECT
631
632/* Type of a section initializer callback. */
633typedef void (LJ_FASTCALL *GDBJITinitf)(GDBJITctx *ctx);
634
635/* Call section initializer and set the section offset and size. */
636static void gdbjit_initsect(GDBJITctx *ctx, int sect, GDBJITinitf initf)
637{
638 ctx->startp = ctx->p;
639 ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
640 initf(ctx);
641 ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
642}
643
644#define SECTALIGN(p, a) \
645 ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
646
647/* Build in-memory ELF object. */
648static void gdbjit_buildobj(GDBJITctx *ctx)
649{
650 GDBJITobj *obj = &ctx->obj;
651 /* Fill in ELF header and clear structures. */
652 memcpy(&obj->hdr, &elfhdr_template, sizeof(ELFheader));
653 memset(&obj->sect, 0, sizeof(ELFsectheader)*GDBJIT_SECT__MAX);
654 memset(&obj->sym, 0, sizeof(ELFsymbol)*GDBJIT_SYM__MAX);
655 /* Initialize sections. */
656 ctx->p = obj->space;
657 gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab, gdbjit_secthdr);
658 gdbjit_initsect(ctx, GDBJIT_SECT_strtab, gdbjit_symtab);
659 gdbjit_initsect(ctx, GDBJIT_SECT_debug_info, gdbjit_debuginfo);
660 gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev, gdbjit_debugabbrev);
661 gdbjit_initsect(ctx, GDBJIT_SECT_debug_line, gdbjit_debugline);
662 SECTALIGN(ctx->p, sizeof(uintptr_t));
663 gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame, gdbjit_ehframe);
664 ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
665 lua_assert(ctx->objsize < sizeof(GDBJITobj));
666}
667
668#undef SECTALIGN
669
670/* -- Interface to GDB JIT API -------------------------------------------- */
671
672/* Add new entry to GDB JIT symbol chain. */
673static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
674{
675 /* Allocate memory for GDB JIT entry and ELF object. */
676 MSize sz = (MSize)(sizeof(GDBJITentryobj) - sizeof(GDBJITobj) + ctx->objsize);
677 GDBJITentryobj *eo = lj_mem_newt(L, sz, GDBJITentryobj);
678 memcpy(&eo->obj, &ctx->obj, ctx->objsize); /* Copy ELF object. */
679 eo->sz = sz;
680 ctx->T->gdbjit_entry = (void *)eo;
681 /* Link new entry to chain and register it. */
682 eo->entry.prev_entry = NULL;
683 eo->entry.next_entry = __jit_debug_descriptor.first_entry;
684 if (eo->entry.next_entry)
685 eo->entry.next_entry->prev_entry = &eo->entry;
686 eo->entry.symfile_addr = (const char *)&eo->obj;
687 eo->entry.symfile_size = ctx->objsize;
688 __jit_debug_descriptor.first_entry = &eo->entry;
689 __jit_debug_descriptor.relevant_entry = &eo->entry;
690 __jit_debug_descriptor.action_flag = GDBJIT_REGISTER;
691 __jit_debug_register_code();
692}
693
694/* Add debug info for newly compiled trace and notify GDB. */
695void lj_gdbjit_addtrace(jit_State *J, Trace *T, TraceNo traceno)
696{
697 GDBJITctx ctx;
698 lua_State *L = J->L;
699 GCproto *pt = &gcref(T->startpt)->pt;
700 TraceNo parent = T->ir[REF_BASE].op1;
701 uintptr_t pcofs = (uintptr_t)(T->snap[0].mapofs+T->snap[0].nslots);
702 const BCIns *startpc = (const BCIns *)(uintptr_t)T->snapmap[pcofs];
703 ctx.T = T;
704 ctx.mcaddr = (uintptr_t)T->mcode;
705 ctx.szmcode = T->szmcode;
706 ctx.spadjp = CFRAME_SIZE + (MSize)(parent ? J->trace[parent]->spadjust : 0);
707 ctx.spadj = CFRAME_SIZE + T->spadjust;
708 ctx.lineno = pt->lineinfo ? pt->lineinfo[startpc - pt->bc] : 0;
709 ctx.filename = strdata(pt->chunkname);
710 if (*ctx.filename == '@' || *ctx.filename == '=')
711 ctx.filename++;
712 else
713 ctx.filename = "(string)";
714 ctx.trname = lj_str_pushf(L, "TRACE_%d", traceno);
715 L->top--;
716 gdbjit_buildobj(&ctx);
717 gdbjit_newentry(L, &ctx);
718}
719
720/* Delete debug info for trace and notify GDB. */
721void lj_gdbjit_deltrace(jit_State *J, Trace *T)
722{
723 GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry;
724 if (eo) {
725 if (eo->entry.prev_entry)
726 eo->entry.prev_entry->next_entry = eo->entry.next_entry;
727 else
728 __jit_debug_descriptor.first_entry = eo->entry.next_entry;
729 if (eo->entry.next_entry)
730 eo->entry.next_entry->prev_entry = eo->entry.prev_entry;
731 __jit_debug_descriptor.relevant_entry = &eo->entry;
732 __jit_debug_descriptor.action_flag = GDBJIT_UNREGISTER;
733 __jit_debug_register_code();
734 lj_mem_free(J2G(J), eo, eo->sz);
735 }
736}
737
738#endif
739#endif