One Level Up
Top Level
src/lj_gdbjit.c - luajit-2.0-src
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #define lj_gdbjit_c
- #define LUA_CORE
- #include "lj_obj.h"
- #if LJ_HASJIT
- #include "lj_gc.h"
- #include "lj_err.h"
- #include "lj_debug.h"
- #include "lj_frame.h"
- #include "lj_buf.h"
- #include "lj_strfmt.h"
- #include "lj_jit.h"
- #include "lj_dispatch.h"
- #ifdef LUAJIT_USE_GDBJIT
- enum {
- GDBJIT_NOACTION = 0,
- GDBJIT_REGISTER,
- GDBJIT_UNREGISTER
- };
- typedef struct GDBJITentry {
- struct GDBJITentry *next_entry;
- struct GDBJITentry *prev_entry;
- const char *symfile_addr;
- uint64_t symfile_size;
- } GDBJITentry;
- typedef struct GDBJITdesc {
- uint32_t version;
- uint32_t action_flag;
- GDBJITentry *relevant_entry;
- GDBJITentry *first_entry;
- } GDBJITdesc;
- GDBJITdesc __jit_debug_descriptor = {
- 1, GDBJIT_NOACTION, NULL, NULL
- };
- void LJ_NOINLINE __jit_debug_register_code()
- {
- __asm__ __volatile__("");
- };
- typedef struct ELFheader {
- uint8_t emagic[4];
- uint8_t eclass;
- uint8_t eendian;
- uint8_t eversion;
- uint8_t eosabi;
- uint8_t eabiversion;
- uint8_t epad[7];
- uint16_t type;
- uint16_t machine;
- uint32_t version;
- uintptr_t entry;
- uintptr_t phofs;
- uintptr_t shofs;
- uint32_t flags;
- uint16_t ehsize;
- uint16_t phentsize;
- uint16_t phnum;
- uint16_t shentsize;
- uint16_t shnum;
- uint16_t shstridx;
- } ELFheader;
- typedef struct ELFsectheader {
- uint32_t name;
- uint32_t type;
- uintptr_t flags;
- uintptr_t addr;
- uintptr_t ofs;
- uintptr_t size;
- uint32_t link;
- uint32_t info;
- uintptr_t align;
- uintptr_t entsize;
- } ELFsectheader;
- #define ELFSECT_IDX_ABS 0xfff1
- enum {
- ELFSECT_TYPE_PROGBITS = 1,
- ELFSECT_TYPE_SYMTAB = 2,
- ELFSECT_TYPE_STRTAB = 3,
- ELFSECT_TYPE_NOBITS = 8
- };
- #define ELFSECT_FLAGS_WRITE 1
- #define ELFSECT_FLAGS_ALLOC 2
- #define ELFSECT_FLAGS_EXEC 4
- typedef struct ELFsymbol {
- #if LJ_64
- uint32_t name;
- uint8_t info;
- uint8_t other;
- uint16_t sectidx;
- uintptr_t value;
- uint64_t size;
- #else
- uint32_t name;
- uintptr_t value;
- uint32_t size;
- uint8_t info;
- uint8_t other;
- uint16_t sectidx;
- #endif
- } ELFsymbol;
- enum {
- ELFSYM_TYPE_FUNC = 2,
- ELFSYM_TYPE_FILE = 4,
- ELFSYM_BIND_LOCAL = 0 << 4,
- ELFSYM_BIND_GLOBAL = 1 << 4,
- };
- #define DW_CIE_VERSION 1
- enum {
- DW_CFA_nop = 0x0,
- DW_CFA_offset_extended = 0x5,
- DW_CFA_def_cfa = 0xc,
- DW_CFA_def_cfa_offset = 0xe,
- DW_CFA_offset_extended_sf = 0x11,
- DW_CFA_advance_loc = 0x40,
- DW_CFA_offset = 0x80
- };
- enum {
- DW_EH_PE_udata4 = 3,
- DW_EH_PE_textrel = 0x20
- };
- enum {
- DW_TAG_compile_unit = 0x11
- };
- enum {
- DW_children_no = 0,
- DW_children_yes = 1
- };
- enum {
- DW_AT_name = 0x03,
- DW_AT_stmt_list = 0x10,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12
- };
- enum {
- DW_FORM_addr = 0x01,
- DW_FORM_data4 = 0x06,
- DW_FORM_string = 0x08
- };
- enum {
- DW_LNS_extended_op = 0,
- DW_LNS_copy = 1,
- DW_LNS_advance_pc = 2,
- DW_LNS_advance_line = 3
- };
- enum {
- DW_LNE_end_sequence = 1,
- DW_LNE_set_address = 2
- };
- enum {
- #if LJ_TARGET_X86
- DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX,
- DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI,
- DW_REG_RA,
- #elif LJ_TARGET_X64
-
- DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX,
- DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP,
- DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11,
- DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15,
- DW_REG_RA,
- #elif LJ_TARGET_ARM
- DW_REG_SP = 13,
- DW_REG_RA = 14,
- #elif LJ_TARGET_PPC
- DW_REG_SP = 1,
- DW_REG_RA = 65,
- DW_REG_CR = 70,
- #elif LJ_TARGET_MIPS
- DW_REG_SP = 29,
- DW_REG_RA = 31,
- #else
- #error "Unsupported target architecture"
- #endif
- };
- enum {
- GDBJIT_SECT_NULL,
- GDBJIT_SECT_text,
- GDBJIT_SECT_eh_frame,
- GDBJIT_SECT_shstrtab,
- GDBJIT_SECT_strtab,
- GDBJIT_SECT_symtab,
- GDBJIT_SECT_debug_info,
- GDBJIT_SECT_debug_abbrev,
- GDBJIT_SECT_debug_line,
- GDBJIT_SECT__MAX
- };
- enum {
- GDBJIT_SYM_UNDEF,
- GDBJIT_SYM_FILE,
- GDBJIT_SYM_FUNC,
- GDBJIT_SYM__MAX
- };
- typedef struct GDBJITobj {
- ELFheader hdr;
- ELFsectheader sect[GDBJIT_SECT__MAX];
- ELFsymbol sym[GDBJIT_SYM__MAX];
- uint8_t space[4096];
- } GDBJITobj;
- typedef struct GDBJITentryobj {
- GDBJITentry entry;
- size_t sz;
- GDBJITobj obj;
- } GDBJITentryobj;
- static const ELFheader elfhdr_template = {
- .emagic = { 0x7f, 'E', 'L', 'F' },
- .eclass = LJ_64 ? 2 : 1,
- .eendian = LJ_ENDIAN_SELECT(1, 2),
- .eversion = 1,
- #if LJ_TARGET_LINUX
- .eosabi = 0,
- #elif defined(__FreeBSD__)
- .eosabi = 9,
- #elif defined(__NetBSD__)
- .eosabi = 2,
- #elif defined(__OpenBSD__)
- .eosabi = 12,
- #elif defined(__DragonFly__)
- .eosabi = 0,
- #elif (defined(__sun__) && defined(__svr4__))
- .eosabi = 6,
- #else
- .eosabi = 0,
- #endif
- .eabiversion = 0,
- .epad = { 0, 0, 0, 0, 0, 0, 0 },
- .type = 1,
- #if LJ_TARGET_X86
- .machine = 3,
- #elif LJ_TARGET_X64
- .machine = 62,
- #elif LJ_TARGET_ARM
- .machine = 40,
- #elif LJ_TARGET_PPC
- .machine = 20,
- #elif LJ_TARGET_MIPS
- .machine = 8,
- #else
- #error "Unsupported target architecture"
- #endif
- .version = 1,
- .entry = 0,
- .phofs = 0,
- .shofs = offsetof(GDBJITobj, sect),
- .flags = 0,
- .ehsize = sizeof(ELFheader),
- .phentsize = 0,
- .phnum = 0,
- .shentsize = sizeof(ELFsectheader),
- .shnum = GDBJIT_SECT__MAX,
- .shstridx = GDBJIT_SECT_shstrtab
- };
- typedef struct GDBJITctx {
- uint8_t *p;
- uint8_t *startp;
- GCtrace *T;
- uintptr_t mcaddr;
- MSize szmcode;
- MSize spadjp;
- MSize spadj;
- BCLine lineno;
- const char *filename;
- size_t objsize;
- GDBJITobj obj;
- } GDBJITctx;
- static uint32_t gdbjit_strz(GDBJITctx *ctx, const char *str)
- {
- uint8_t *p = ctx->p;
- uint32_t ofs = (uint32_t)(p - ctx->startp);
- do {
- *p++ = (uint8_t)*str;
- } while (*str++);
- ctx->p = p;
- return ofs;
- }
- static void gdbjit_catnum(GDBJITctx *ctx, uint32_t n)
- {
- if (n >= 10) { uint32_t m = n / 10; n = n % 10; gdbjit_catnum(ctx, m); }
- *ctx->p++ = '0' + n;
- }
- static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
- {
- uint8_t *p = ctx->p;
- for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7)
- *p++ = (uint8_t)((v & 0x7f) | 0x80);
- *p++ = (uint8_t)(v & 0x7f);
- ctx->p = p;
- }
- #define DB(x) (*p++ = (x))
- #define DI8(x) (*(int8_t *)p = (x), p++)
- #define DU16(x) (*(uint16_t *)p = (x), p += 2)
- #define DU32(x) (*(uint32_t *)p = (x), p += 4)
- #define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t))
- #define DUV(x) (p = (uint8_t *)lj_strfmt_wuleb128((char *)p, (x)))
- #define DSV(x) (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p)
- #define DSTR(str) (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p)
- #define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
- #define DSECT(name, stmt) \
- { uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
- *szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); } \
- static void LJ_FASTCALL gdbjit_secthdr(GDBJITctx *ctx)
- {
- ELFsectheader *sect;
- *ctx->p++ = '\0';
- #define SECTDEF(id, tp, al) \
- sect = &ctx->obj.sect[GDBJIT_SECT_##id]; \
- sect->name = gdbjit_strz(ctx, "." #id); \
- sect->type = ELFSECT_TYPE_##tp; \
- sect->align = (al)
- SECTDEF(text, NOBITS, 16);
- sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC;
- sect->addr = ctx->mcaddr;
- sect->ofs = 0;
- sect->size = ctx->szmcode;
- SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t));
- sect->flags = ELFSECT_FLAGS_ALLOC;
- SECTDEF(shstrtab, STRTAB, 1);
- SECTDEF(strtab, STRTAB, 1);
- SECTDEF(symtab, SYMTAB, sizeof(uintptr_t));
- sect->ofs = offsetof(GDBJITobj, sym);
- sect->size = sizeof(ctx->obj.sym);
- sect->link = GDBJIT_SECT_strtab;
- sect->entsize = sizeof(ELFsymbol);
- sect->info = GDBJIT_SYM_FUNC;
- SECTDEF(debug_info, PROGBITS, 1);
- SECTDEF(debug_abbrev, PROGBITS, 1);
- SECTDEF(debug_line, PROGBITS, 1);
- #undef SECTDEF
- }
- static void LJ_FASTCALL gdbjit_symtab(GDBJITctx *ctx)
- {
- ELFsymbol *sym;
- *ctx->p++ = '\0';
- sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
- sym->name = gdbjit_strz(ctx, "JIT mcode");
- sym->sectidx = ELFSECT_IDX_ABS;
- sym->info = ELFSYM_TYPE_FILE|ELFSYM_BIND_LOCAL;
- sym = &ctx->obj.sym[GDBJIT_SYM_FUNC];
- sym->name = gdbjit_strz(ctx, "TRACE_"); ctx->p--;
- gdbjit_catnum(ctx, ctx->T->traceno); *ctx->p++ = '\0';
- sym->sectidx = GDBJIT_SECT_text;
- sym->value = 0;
- sym->size = ctx->szmcode;
- sym->info = ELFSYM_TYPE_FUNC|ELFSYM_BIND_GLOBAL;
- }
- static void LJ_FASTCALL gdbjit_ehframe(GDBJITctx *ctx)
- {
- uint8_t *p = ctx->p;
- uint8_t *framep = p;
-
- DSECT(CIE,
- DU32(0);
- DB(DW_CIE_VERSION);
- DSTR("zR");
- DUV(1);
- DSV(-(int32_t)sizeof(uintptr_t));
- DB(DW_REG_RA);
- DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4);
- DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
- #if LJ_TARGET_PPC
- DB(DW_CFA_offset_extended_sf); DB(DW_REG_RA); DSV(-1);
- #else
- DB(DW_CFA_offset|DW_REG_RA); DUV(1);
- #endif
- DALIGNNOP(sizeof(uintptr_t));
- )
-
- DSECT(FDE,
- DU32((uint32_t)(p-framep));
- DU32(0);
- DU32(ctx->szmcode);
- DB(0);
-
- #if LJ_TARGET_X86
- DB(DW_CFA_offset|DW_REG_BP); DUV(2);
- DB(DW_CFA_offset|DW_REG_DI); DUV(3);
- DB(DW_CFA_offset|DW_REG_SI); DUV(4);
- DB(DW_CFA_offset|DW_REG_BX); DUV(5);
- #elif LJ_TARGET_X64
- DB(DW_CFA_offset|DW_REG_BP); DUV(2);
- DB(DW_CFA_offset|DW_REG_BX); DUV(3);
- DB(DW_CFA_offset|DW_REG_15); DUV(4);
- DB(DW_CFA_offset|DW_REG_14); DUV(5);
-
- DB(DW_CFA_offset|DW_REG_13); DUV(9);
- DB(DW_CFA_offset|DW_REG_12); DUV(10);
- #elif LJ_TARGET_ARM
- {
- int i;
- for (i = 11; i >= 4; i--) { DB(DW_CFA_offset|i); DUV(2+(11-i)); }
- }
- #elif LJ_TARGET_PPC
- {
- int i;
- DB(DW_CFA_offset_extended); DB(DW_REG_CR); DUV(55);
- for (i = 14; i <= 31; i++) {
- DB(DW_CFA_offset|i); DUV(37+(31-i));
- DB(DW_CFA_offset|32|i); DUV(2+2*(31-i));
- }
- }
- #elif LJ_TARGET_MIPS
- {
- int i;
- DB(DW_CFA_offset|30); DUV(2);
- for (i = 23; i >= 16; i--) { DB(DW_CFA_offset|i); DUV(26-i); }
- for (i = 30; i >= 20; i -= 2) { DB(DW_CFA_offset|32|i); DUV(42-i); }
- }
- #else
- #error "Unsupported target architecture"
- #endif
- if (ctx->spadjp != ctx->spadj) {
- DB(DW_CFA_def_cfa_offset); DUV(ctx->spadjp);
- DB(DW_CFA_advance_loc|1);
- }
- DB(DW_CFA_def_cfa_offset); DUV(ctx->spadj);
- DALIGNNOP(sizeof(uintptr_t));
- )
- ctx->p = p;
- }
- static void LJ_FASTCALL gdbjit_debuginfo(GDBJITctx *ctx)
- {
- uint8_t *p = ctx->p;
- DSECT(info,
- DU16(2);
- DU32(0);
- DB(sizeof(uintptr_t));
- DUV(1);
- DSTR(ctx->filename);
- DADDR(ctx->mcaddr);
- DADDR(ctx->mcaddr + ctx->szmcode);
- DU32(0);
- )
- ctx->p = p;
- }
- static void LJ_FASTCALL gdbjit_debugabbrev(GDBJITctx *ctx)
- {
- uint8_t *p = ctx->p;
-
- DUV(1); DUV(DW_TAG_compile_unit);
- DB(DW_children_no);
- DUV(DW_AT_name); DUV(DW_FORM_string);
- DUV(DW_AT_low_pc); DUV(DW_FORM_addr);
- DUV(DW_AT_high_pc); DUV(DW_FORM_addr);
- DUV(DW_AT_stmt_list); DUV(DW_FORM_data4);
- DB(0); DB(0);
- ctx->p = p;
- }
- #define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
- static void LJ_FASTCALL gdbjit_debugline(GDBJITctx *ctx)
- {
- uint8_t *p = ctx->p;
- DSECT(line,
- DU16(2);
- DSECT(header,
- DB(1);
- DB(1);
- DI8(0);
- DB(2);
- DB(3+1);
- DB(0); DB(1); DB(1);
-
- DB(0);
-
- DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
- DB(0);
- )
- DLNE(DW_LNE_set_address, sizeof(uintptr_t)); DADDR(ctx->mcaddr);
- if (ctx->lineno) {
- DB(DW_LNS_advance_line); DSV(ctx->lineno-1);
- }
- DB(DW_LNS_copy);
- DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
- DLNE(DW_LNE_end_sequence, 0);
- )
- ctx->p = p;
- }
- #undef DLNE
- #undef DB
- #undef DI8
- #undef DU16
- #undef DU32
- #undef DADDR
- #undef DUV
- #undef DSV
- #undef DSTR
- #undef DALIGNNOP
- #undef DSECT
- typedef void (LJ_FASTCALL *GDBJITinitf)(GDBJITctx *ctx);
- static void gdbjit_initsect(GDBJITctx *ctx, int sect, GDBJITinitf initf)
- {
- ctx->startp = ctx->p;
- ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
- initf(ctx);
- ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
- }
- #define SECTALIGN(p, a) \
- ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
- static void gdbjit_buildobj(GDBJITctx *ctx)
- {
- GDBJITobj *obj = &ctx->obj;
-
- memcpy(&obj->hdr, &elfhdr_template, sizeof(ELFheader));
- memset(&obj->sect, 0, sizeof(ELFsectheader)*GDBJIT_SECT__MAX);
- memset(&obj->sym, 0, sizeof(ELFsymbol)*GDBJIT_SYM__MAX);
-
- ctx->p = obj->space;
- gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab, gdbjit_secthdr);
- gdbjit_initsect(ctx, GDBJIT_SECT_strtab, gdbjit_symtab);
- gdbjit_initsect(ctx, GDBJIT_SECT_debug_info, gdbjit_debuginfo);
- gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev, gdbjit_debugabbrev);
- gdbjit_initsect(ctx, GDBJIT_SECT_debug_line, gdbjit_debugline);
- SECTALIGN(ctx->p, sizeof(uintptr_t));
- gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame, gdbjit_ehframe);
- ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
- lua_assert(ctx->objsize < sizeof(GDBJITobj));
- }
- #undef SECTALIGN
- static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
- {
-
- MSize sz = (MSize)(sizeof(GDBJITentryobj) - sizeof(GDBJITobj) + ctx->objsize);
- GDBJITentryobj *eo = lj_mem_newt(L, sz, GDBJITentryobj);
- memcpy(&eo->obj, &ctx->obj, ctx->objsize);
- eo->sz = sz;
- ctx->T->gdbjit_entry = (void *)eo;
-
- eo->entry.prev_entry = NULL;
- eo->entry.next_entry = __jit_debug_descriptor.first_entry;
- if (eo->entry.next_entry)
- eo->entry.next_entry->prev_entry = &eo->entry;
- eo->entry.symfile_addr = (const char *)&eo->obj;
- eo->entry.symfile_size = ctx->objsize;
- __jit_debug_descriptor.first_entry = &eo->entry;
- __jit_debug_descriptor.relevant_entry = &eo->entry;
- __jit_debug_descriptor.action_flag = GDBJIT_REGISTER;
- __jit_debug_register_code();
- }
- void lj_gdbjit_addtrace(jit_State *J, GCtrace *T)
- {
- GDBJITctx ctx;
- GCproto *pt = &gcref(T->startpt)->pt;
- TraceNo parent = T->ir[REF_BASE].op1;
- const BCIns *startpc = mref(T->startpc, const BCIns);
- ctx.T = T;
- ctx.mcaddr = (uintptr_t)T->mcode;
- ctx.szmcode = T->szmcode;
- ctx.spadjp = CFRAME_SIZE_JIT +
- (MSize)(parent ? traceref(J, parent)->spadjust : 0);
- ctx.spadj = CFRAME_SIZE_JIT + T->spadjust;
- lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc);
- ctx.lineno = lj_debug_line(pt, proto_bcpos(pt, startpc));
- ctx.filename = proto_chunknamestr(pt);
- if (*ctx.filename == '@' || *ctx.filename == '=')
- ctx.filename++;
- else
- ctx.filename = "(string)";
- gdbjit_buildobj(&ctx);
- gdbjit_newentry(J->L, &ctx);
- }
- void lj_gdbjit_deltrace(jit_State *J, GCtrace *T)
- {
- GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry;
- if (eo) {
- if (eo->entry.prev_entry)
- eo->entry.prev_entry->next_entry = eo->entry.next_entry;
- else
- __jit_debug_descriptor.first_entry = eo->entry.next_entry;
- if (eo->entry.next_entry)
- eo->entry.next_entry->prev_entry = eo->entry.prev_entry;
- __jit_debug_descriptor.relevant_entry = &eo->entry;
- __jit_debug_descriptor.action_flag = GDBJIT_UNREGISTER;
- __jit_debug_register_code();
- lj_mem_free(J2G(J), eo, eo->sz);
- }
- }
- #endif
- #endif
One Level Up
Top Level