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