16# include <sys/types.h>
17# include <sys/sysctl.h>
26#define DW_CIE_VERSION 1
79#if defined(IR_TARGET_X86)
80 DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX,
81 DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI,
83#elif defined(IR_TARGET_X64)
85 DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX,
86 DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP,
87 DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11,
88 DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15,
90#elif defined(IR_TARGET_AARCH64)
95#error "Unsupported target architecture"
127 .emagic = { 0x7f,
'E',
'L',
'F' },
133#ifdef WORDS_BIGENDIAN
141#elif defined(__FreeBSD__)
143#elif defined(__OpenBSD__)
145#elif defined(__NetBSD__)
147#elif defined(__DragonFly__)
149#elif (defined(__sun__) && defined(__svr4__))
155 .epad = { 0, 0, 0, 0, 0, 0, 0 },
157#if defined(IR_TARGET_X86)
159#elif defined(IR_TARGET_X64)
161#elif defined(IR_TARGET_AARCH64)
164# error "Unsupported target architecture"
193static uint32_t ir_gdbjit_strz(
ir_gdbjit_ctx *ctx,
const char *str)
196 uint32_t ofs = (uint32_t)(
p - ctx->
startp);
198 *
p++ = (uint8_t)*str;
208 for (;
v >= 0x80;
v >>= 7)
209 *
p++ = (uint8_t)((
v & 0x7f) | 0x80);
218 for (; (uint32_t)(
v+0x40) >= 0x80;
v >>= 7)
219 *
p++ = (uint8_t)((
v & 0x7f) | 0x80);
220 *
p++ = (uint8_t)(
v & 0x7f);
230#define SECTDEF(id, tp, al) \
231 sect = &ctx->obj.sect[GDBJIT_SECT_##id]; \
232 sect->name = ir_gdbjit_strz(ctx, "." #id); \
233 sect->type = ELFSECT_TYPE_##tp; \
242 SECTDEF(eh_frame, PROGBITS,
sizeof(uintptr_t));
248 SECTDEF(symtab, SYMTAB,
sizeof(uintptr_t));
255 SECTDEF(debug_info, PROGBITS, 1);
256 SECTDEF(debug_abbrev, PROGBITS, 1);
257 SECTDEF(debug_line, PROGBITS, 1);
269 sym->
name = ir_gdbjit_strz(ctx,
"JIT code");
274 sym->
name = ir_gdbjit_strz(ctx, ctx->
name);
285#define SECTALIGN(p, a) \
286 ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
289#define DB(x) (*p++ = (x))
290#define DI8(x) (*(int8_t *)p = (x), p++)
291#define DU16(x) (*(unaligned_uint16_t *)p = (x), p += 2)
292#define DU32(x) (*(unaligned_uint32_t *)p = (x), p += 4)
293#define DADDR(x) (*(unaligned_uintptr_t *)p = (x), p += sizeof(uintptr_t))
294#define DUV(x) (ctx->p = p, ir_gdbjit_uleb128(ctx, (x)), p = ctx->p)
295#define DSV(x) (ctx->p = p, ir_gdbjit_sleb128(ctx, (x)), p = ctx->p)
296#define DSTR(str) (ctx->p = p, ir_gdbjit_strz(ctx, (str)), p = ctx->p)
297#define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
298#define DSECT(name, stmt) \
299 { unaligned_uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
300 *szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); }
302static void ir_gdbjit_ehframe(
ir_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
313 DSV(-(int32_t)
sizeof(uintptr_t));
316#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
319#elif defined(IR_TARGET_AARCH64)
327 DU32((uint32_t)(
p-framep));
332#if defined(IR_TARGET_AARCH64)
334 if (sp_adjustment && sp_adjustment < sp_offset) {
343 if (sp_adjustment && sp_adjustment > sp_offset) {
345#if defined(IR_TARGET_AARCH64)
365 DB(
sizeof(uintptr_t));
400#define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
452 ctx->
obj.
sect[sect].
ofs = (uintptr_t)((
char *)ctx->
p - (
char *)&ctx->
obj);
455static void ir_gdbjit_initsect_done(
ir_gdbjit_ctx *ctx,
int sect)
460static void ir_gdbjit_buildobj(
ir_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
478 ctx->
objsize = (size_t)((
char *)ctx->
p - (
char *)obj);
503#ifdef IR_EXTERNAL_GDB_ENTRY
513 __asm__ __volatile__(
"");
517static bool ir_gdb_register_code(
const void *
object,
size_t size)
565#if defined(__FreeBSD__)
566static bool ir_gdb_info_proc(pid_t pid,
struct kinfo_proc *proc)
569 len = plen =
sizeof(*proc);
570 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
572 if (sysctl(mib, 4, proc, &
len,
NULL, 0) < 0 ||
len != plen ||
573 proc->ki_structsize != (
int)plen || proc->ki_pid != pid) {
584#if defined(__linux__)
585 int fd = open(
"/proc/self/status", O_RDONLY);
589 ssize_t
n = read(
fd,
buf,
sizeof(
buf) - 1);
597 s +=
sizeof(
"TracerPid:") - 1;
598 while (*
s ==
' ' || *
s ==
'\t') {
616#elif defined(__FreeBSD__)
617 struct kinfo_proc proc,
dbg;
619 if (ir_gdb_info_proc(getpid(), &proc)) {
620 if ((proc.ki_flag & P_TRACED) != 0) {
621 if (ir_gdb_info_proc(proc.ki_tracer, &
dbg)) {
635 uint32_t sp_adjustment)
645 ir_gdbjit_buildobj(&ctx, sp_offset, sp_adjustment);
647 return ir_gdb_register_code(&ctx.
obj, ctx.
objsize);
656 _debug |= IR_DEBUG_GDB;
header(string $header, bool $replace=true, int $response_code=0)
strstr(string $haystack, string $needle, bool $before_needle=false)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
struct _ir_elf_header ir_elf_header
#define ELFSECT_FLAGS_EXEC
#define ELFSYM_INFO(bind, type)
#define ELFSECT_FLAGS_ALLOC
struct _ir_gdbjit_descriptor ir_gdbjit_descriptor
struct _ir_gdbjit_ctx ir_gdbjit_ctx
struct _ir_gdbjit_code_entry ir_gdbjit_code_entry
struct _ir_gdbjit_obj ir_gdbjit_obj
#define DSECT(name, stmt)
#define SECTDEF(id, tp, al)
int ir_gdb_register(const char *name, const void *start, size_t size, uint32_t sp_offset, uint32_t sp_adjustment)
IR_NEVER_INLINE void __jit_debug_register_code(void)
@ DW_CFA_offset_extended_sf
void(* ir_gdbjit_initf)(ir_gdbjit_ctx *ctx)
void ir_gdb_unregister_all(void)
@ GDBJIT_SECT_debug_abbrev
bool ir_gdb_present(void)
#define IR_SET_ALIGNED(alignment, decl)
unsigned const char * text
#define offsetof(STRUCTURE, FIELD)
struct _ir_gdbjit_code_entry * next_entry
const char * symfile_addr
struct _ir_gdbjit_code_entry * prev_entry
struct _ir_gdbjit_code_entry * relevant_entry
struct _ir_gdbjit_code_entry * first_entry
ir_elf_symbol sym[GDBJIT_SYM__MAX]
ir_elf_sectheader sect[GDBJIT_SECT__MAX]
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
ZEND_API zend_gdbjit_descriptor __jit_debug_descriptor