: movsd xmm7,QWORD PTR [edx+0x20]
[...]
0xf7fd9ff8
: jmp 0xf7fd2014
End of assembler dump.
(gdb) tbreak TRACE_2
Function "TRACE_2" not defined.
Temporary breakpoint 2 (TRACE_2) pending.
(gdb) cont
Continuing.
Temporary breakpoint 2, TRACE_2 () at x.lua:1
1 for outer=1,100 do
(gdb) info frame
Stack level 0, frame at 0xffffd7c0:
eip = 0xf7fd9f60 in TRACE_2 (x.lua:1); saved eip 0x8053690
called by frame at 0xffffd7e0
source language unknown.
Arglist at 0xffffd78c, args:
Locals at 0xffffd78c, Previous frame's sp is 0xffffd7c0
Saved registers:
ebx at 0xffffd7ac, ebp at 0xffffd7b8, esi at 0xffffd7b0, edi at 0xffffd7b4,
eip at 0xffffd7bc
(gdb)
** ------------------------------------------------------------------------
*/
/* -- GDB JIT API --------------------------------------------------------- */
/* GDB JIT actions. */
enum {
GDBJIT_NOACTION = 0,
GDBJIT_REGISTER,
GDBJIT_UNREGISTER
};
/* GDB JIT entry. */
typedef struct GDBJITentry {
struct GDBJITentry *next_entry;
struct GDBJITentry *prev_entry;
const char *symfile_addr;
uint64_t symfile_size;
} GDBJITentry;
/* GDB JIT descriptor. */
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
};
/* GDB sets a breakpoint at this function. */
void LJ_NOINLINE __jit_debug_register_code()
{
__asm__ __volatile__("");
};
/* -- In-memory ELF object definitions ------------------------------------ */
/* ELF definitions. */
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, }; /* DWARF definitions. */ #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 /* Yes, the order is strange, but correct. */ 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 }; /* Minimal list of sections for the in-memory ELF object. */ 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 }; /* In-memory ELF object. */ typedef struct GDBJITobj { ELFheader hdr; /* ELF header. */ ELFsectheader sect[GDBJIT_SECT__MAX]; /* ELF sections. */ ELFsymbol sym[GDBJIT_SYM__MAX]; /* ELF symbol table. */ uint8_t space[4096]; /* Space for various section data. */ } GDBJITobj; /* Combined structure for GDB JIT entry and ELF object. */ typedef struct GDBJITentryobj { GDBJITentry entry; size_t sz; GDBJITobj obj; } GDBJITentryobj; /* Template for in-memory ELF header. */ 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, /* Nope, it's not 3. */ #elif defined(__FreeBSD__) .eosabi = 9, #elif defined(__NetBSD__) .eosabi = 2, #elif defined(__OpenBSD__) .eosabi = 12, #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 }; /* -- In-memory ELF object generation ------------------------------------- */ /* Context for generating the ELF object for the GDB JIT API. */ typedef struct GDBJITctx { uint8_t *p; /* Pointer to next address in obj.space. */ uint8_t *startp; /* Pointer to start address in obj.space. */ GCtrace *T; /* Generate symbols for this trace. */ uintptr_t mcaddr; /* Machine code address. */ MSize szmcode; /* Size of machine code. */ MSize spadjp; /* Stack adjustment for parent trace or interpreter. */ MSize spadj; /* Stack adjustment for trace itself. */ BCLine lineno; /* Starting line number. */ const char *filename; /* Starting file name. */ size_t objsize; /* Final size of ELF object. */ GDBJITobj obj; /* In-memory ELF object. */ } GDBJITctx; /* Add a zero-terminated string. */ 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;
}
/* Append a decimal number. */
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;
}
/* Add a ULEB128 value. */
static void gdbjit_uleb128(GDBJITctx *ctx, uint32_t v)
{
uint8_t *p = ctx->p;
for (; v>= 0x80; v>>= 7)
*p++ = (uint8_t)((v & 0x7f) | 0x80);
*p++ = (uint8_t)v;
ctx->p = p;
}
/* Add a SLEB128 value. */
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;
}
/* Shortcuts to generate DWARF structures. */
#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) (ctx->p = p, gdbjit_uleb128(ctx, (x)), p = ctx->p)
#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); } \
/* Initialize ELF section headers. */
static void LJ_FASTCALL gdbjit_secthdr(GDBJITctx *ctx)
{
ELFsectheader *sect;
*ctx->p++ = '0円'; /* Empty string at start of string table. */
#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
}
/* Initialize symbol table. */
static void LJ_FASTCALL gdbjit_symtab(GDBJITctx *ctx)
{
ELFsymbol *sym;
*ctx->p++ = '0円'; /* Empty string at start of string table. */
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;
}
/* Initialize .eh_frame section. */
static void LJ_FASTCALL gdbjit_ehframe(GDBJITctx *ctx)
{
uint8_t *p = ctx->p;
uint8_t *framep = p;
/* Emit DWARF EH CIE. */
DSECT(CIE,
DU32(0); /* Offset to CIE itself. */
DB(DW_CIE_VERSION);
DSTR("zR"); /* Augmentation. */
DUV(1); /* Code alignment factor. */
DSV(-(int32_t)sizeof(uintptr_t)); /* Data alignment factor. */
DB(DW_REG_RA); /* Return address register. */
DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4); /* Augmentation data. */
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));
)
/* Emit DWARF EH FDE. */
DSECT(FDE,
DU32((uint32_t)(p-framep)); /* Offset to CIE. */
DU32(0); /* Machine code offset relative to .text. */
DU32(ctx->szmcode); /* Machine code length. */
DB(0); /* Augmentation data. */
/* Registers saved in CFRAME. */
#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);
/* Extra registers saved for JIT-compiled code. */
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) { /* Parent/interpreter stack frame size. */
DB(DW_CFA_def_cfa_offset); DUV(ctx->spadjp);
DB(DW_CFA_advance_loc|1); /* Only an approximation. */
}
DB(DW_CFA_def_cfa_offset); DUV(ctx->spadj); /* Trace stack frame size. */
DALIGNNOP(sizeof(uintptr_t));
)
ctx->p = p;
}
/* Initialize .debug_info section. */
static void LJ_FASTCALL gdbjit_debuginfo(GDBJITctx *ctx)
{
uint8_t *p = ctx->p;
DSECT(info,
DU16(2); /* DWARF version. */
DU32(0); /* Abbrev offset. */
DB(sizeof(uintptr_t)); /* Pointer size. */
DUV(1); /* Abbrev #1: DW_TAG_compile_unit. */
DSTR(ctx->filename); /* DW_AT_name. */
DADDR(ctx->mcaddr); /* DW_AT_low_pc. */
DADDR(ctx->mcaddr + ctx->szmcode); /* DW_AT_high_pc. */
DU32(0); /* DW_AT_stmt_list. */
)
ctx->p = p;
}
/* Initialize .debug_abbrev section. */
static void LJ_FASTCALL gdbjit_debugabbrev(GDBJITctx *ctx)
{
uint8_t *p = ctx->p;
/* Abbrev #1: DW_TAG_compile_unit. */
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)))
/* Initialize .debug_line section. */
static void LJ_FASTCALL gdbjit_debugline(GDBJITctx *ctx)
{
uint8_t *p = ctx->p;
DSECT(line,
DU16(2); /* DWARF version. */
DSECT(header,
DB(1); /* Minimum instruction length. */
DB(1); /* is_stmt. */
DI8(0); /* Line base for special opcodes. */
DB(2); /* Line range for special opcodes. */
DB(3+1); /* Opcode base at DW_LNS_advance_line+1. */
DB(0); DB(1); DB(1); /* Standard opcode lengths. */
/* Directory table. */
DB(0);
/* File name table. */
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 shortcuts. */
#undef DB
#undef DI8
#undef DU16
#undef DU32
#undef DADDR
#undef DUV
#undef DSV
#undef DSTR
#undef DALIGNNOP
#undef DSECT
/* Type of a section initializer callback. */
typedef void (LJ_FASTCALL *GDBJITinitf)(GDBJITctx *ctx);
/* Call section initializer and set the section offset and size. */
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)))
/* Build in-memory ELF object. */
static void gdbjit_buildobj(GDBJITctx *ctx)
{
GDBJITobj *obj = &ctx->obj;
/* Fill in ELF header and clear structures. */
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);
/* Initialize sections. */
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 /* -- Interface to GDB JIT API -------------------------------------------- */ /* Add new entry to GDB JIT symbol chain. */ static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx) { /* Allocate memory for GDB JIT entry and ELF object. */ MSize sz = (MSize)(sizeof(GDBJITentryobj) - sizeof(GDBJITobj) + ctx->objsize);
GDBJITentryobj *eo = lj_mem_newt(L, sz, GDBJITentryobj);
memcpy(&eo->obj, &ctx->obj, ctx->objsize); /* Copy ELF object. */
eo->sz = sz;
ctx->T->gdbjit_entry = (void *)eo;
/* Link new entry to chain and register it. */
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();
}
/* Add debug info for newly compiled trace and notify GDB. */
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);
}
/* Delete debug info for trace and notify GDB. */
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