xref: /php-src/ext/opcache/jit/ir/ir_gdb.c (revision cc5a3945)
1 /*
2  * IR - Lightweight JIT Compilation Framework
3  * (GDB interface)
4  * Copyright (C) 2022 Zend by Perforce.
5  * Authors: Dmitry Stogov <dmitry@php.net>
6  *
7  * Based on Mike Pall's implementation of GDB interface for LuaJIT.
8  */
9 
10 #include <stddef.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 
15 #ifdef __FreeBSD__
16 # include <sys/types.h>
17 # include <sys/sysctl.h>
18 # include <sys/user.h>
19 #endif
20 
21 #include "ir.h"
22 #include "ir_private.h"
23 #include "ir_elf.h"
24 
25 /* DWARF definitions. */
26 #define DW_CIE_VERSION  1
27 
28 /* CFA (Canonical frame address) */
29 enum {
30 	DW_CFA_nop = 0x0,
31 	DW_CFA_offset_extended = 0x5,
32 	DW_CFA_def_cfa = 0xc,
33 	DW_CFA_def_cfa_offset = 0xe,
34 	DW_CFA_offset_extended_sf = 0x11,
35 	DW_CFA_advance_loc = 0x40,
36 	DW_CFA_offset = 0x80
37 };
38 
39 enum {
40 	DW_EH_PE_udata4 = 0x03,
41 	DW_EH_PE_textrel = 0x20
42 };
43 
44 enum {
45 	DW_TAG_compile_unit = 0x11
46 };
47 
48 enum {
49 	DW_children_no = 0,
50 	DW_children_yes = 1
51 };
52 
53 enum {
54 	DW_AT_name = 0x03,
55 	DW_AT_stmt_list = 0x10,
56 	DW_AT_low_pc = 0x11,
57 	DW_AT_high_pc = 0x12
58 };
59 
60 enum {
61 	DW_FORM_addr = 0x01,
62 	DW_FORM_data4 = 0x06,
63 	DW_FORM_string = 0x08
64 };
65 
66 enum {
67 	DW_LNS_extended_op = 0,
68 	DW_LNS_copy = 1,
69 	DW_LNS_advance_pc = 2,
70 	DW_LNS_advance_line = 3
71 };
72 
73 enum {
74 	DW_LNE_end_sequence = 1,
75 	DW_LNE_set_address = 2
76 };
77 
78 enum {
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,
82 	DW_REG_RA,
83 #elif defined(IR_TARGET_X64)
84 	/* Yes, the order is strange, but correct. */
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,
89 	DW_REG_RA,
90 #elif defined(IR_TARGET_AARCH64)
91 	DW_REG_SP = 31,
92 	DW_REG_RA = 30,
93 	DW_REG_X29 = 29,
94 #else
95 #error "Unsupported target architecture"
96 #endif
97 };
98 
99 enum {
100 	GDBJIT_SECT_NULL,
101 	GDBJIT_SECT_text,
102 	GDBJIT_SECT_eh_frame,
103 	GDBJIT_SECT_shstrtab,
104 	GDBJIT_SECT_strtab,
105 	GDBJIT_SECT_symtab,
106 	GDBJIT_SECT_debug_info,
107 	GDBJIT_SECT_debug_abbrev,
108 	GDBJIT_SECT_debug_line,
109 	GDBJIT_SECT__MAX
110 };
111 
112 enum {
113 	GDBJIT_SYM_UNDEF,
114 	GDBJIT_SYM_FILE,
115 	GDBJIT_SYM_FUNC,
116 	GDBJIT_SYM__MAX
117 };
118 
119 typedef struct _ir_gdbjit_obj {
120 	ir_elf_header     hdr;
121 	ir_elf_sectheader sect[GDBJIT_SECT__MAX];
122 	ir_elf_symbol     sym[GDBJIT_SYM__MAX];
123 	uint8_t           space[4096];
124 } ir_gdbjit_obj;
125 
126 static const ir_elf_header ir_elfhdr_template = {
127 	.emagic      = { 0x7f, 'E', 'L', 'F' },
128 #ifdef ELF64
129 	.eclass      = 2,
130 #else
131 	.eclass      = 1,
132 #endif
133 #ifdef WORDS_BIGENDIAN
134 	.eendian     = 2,
135 #else
136 	.eendian     = 1,
137 #endif
138 	.eversion    = 1,
139 #if defined(Linux)
140 	.eosabi      = 0,  /* TODO: Nope, it's not 3. ??? */
141 #elif defined(__FreeBSD__)
142 	.eosabi      = 9,
143 #elif defined(__OpenBSD__)
144 	.eosabi      = 12,
145 #elif defined(__NetBSD__)
146 	.eosabi      = 2,
147 #elif defined(__DragonFly__)
148 	.eosabi      = 0,
149 #elif (defined(__sun__) && defined(__svr4__))
150 	.eosabi      = 6,
151 #else
152 	.eosabi      = 0,
153 #endif
154 	.eabiversion = 0,
155 	.epad        = { 0, 0, 0, 0, 0, 0, 0 },
156 	.type        = 1,
157 #if defined(IR_TARGET_X86)
158 	.machine     = 3,
159 #elif defined(IR_TARGET_X64)
160 	.machine     = 62,
161 #elif defined(IR_TARGET_AARCH64)
162 	.machine     = 183,
163 #else
164 # error "Unsupported target architecture"
165 #endif
166 	.version     = 1,
167 	.entry       = 0,
168 	.phofs       = 0,
169 	.shofs       = offsetof(ir_gdbjit_obj, sect),
170 	.flags       = 0,
171 	.ehsize      = sizeof(ir_elf_header),
172 	.phentsize   = 0,
173 	.phnum       = 0,
174 	.shentsize   = sizeof(ir_elf_sectheader),
175 	.shnum       = GDBJIT_SECT__MAX,
176 	.shstridx    = GDBJIT_SECT_shstrtab
177 };
178 
179 /* Context for generating the ELF object for the GDB JIT API. */
180 typedef struct _ir_gdbjit_ctx {
181 	uint8_t *p;              /* Pointer to next address in obj.space. */
182 	uint8_t *startp;         /* Pointer to start address in obj.space. */
183 	uintptr_t mcaddr;        /* Machine code address. */
184 	uint32_t szmcode;        /* Size of machine code. */
185 	int32_t  lineno;         /* Starting line number. */
186 	const char *name;        /* JIT function name */
187 	const char *filename;    /* Starting file name. */
188 	size_t objsize;          /* Final size of ELF object. */
189 	ir_gdbjit_obj obj;       /* In-memory ELF object. */
190 } ir_gdbjit_ctx;
191 
192 /* Add a zero-terminated string */
ir_gdbjit_strz(ir_gdbjit_ctx * ctx,const char * str)193 static uint32_t ir_gdbjit_strz(ir_gdbjit_ctx *ctx, const char *str)
194 {
195 	uint8_t *p = ctx->p;
196 	uint32_t ofs = (uint32_t)(p - ctx->startp);
197 	do {
198 		*p++ = (uint8_t)*str;
199 	} while (*str++);
200 	ctx->p = p;
201 	return ofs;
202 }
203 
204 /* Add a ULEB128 value */
ir_gdbjit_uleb128(ir_gdbjit_ctx * ctx,uint32_t v)205 static void ir_gdbjit_uleb128(ir_gdbjit_ctx *ctx, uint32_t v)
206 {
207 	uint8_t *p = ctx->p;
208 	for (; v >= 0x80; v >>= 7)
209 		*p++ = (uint8_t)((v & 0x7f) | 0x80);
210 	*p++ = (uint8_t)v;
211 	ctx->p = p;
212 }
213 
214 /* Add a SLEB128 value */
ir_gdbjit_sleb128(ir_gdbjit_ctx * ctx,int32_t v)215 static void ir_gdbjit_sleb128(ir_gdbjit_ctx *ctx, int32_t v)
216 {
217 	uint8_t *p = ctx->p;
218 	for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7)
219 		*p++ = (uint8_t)((v & 0x7f) | 0x80);
220 	*p++ = (uint8_t)(v & 0x7f);
221 	ctx->p = p;
222 }
223 
ir_gdbjit_secthdr(ir_gdbjit_ctx * ctx)224 static void ir_gdbjit_secthdr(ir_gdbjit_ctx *ctx)
225 {
226 	ir_elf_sectheader *sect;
227 
228 	*ctx->p++ = '\0';
229 
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;               \
234 	sect->align = (al)
235 
236 	SECTDEF(text, NOBITS, 16);
237 	sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC;
238 	sect->addr = ctx->mcaddr;
239 	sect->ofs = 0;
240 	sect->size = ctx->szmcode;
241 
242 	SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t));
243 	sect->flags = ELFSECT_FLAGS_ALLOC;
244 
245 	SECTDEF(shstrtab, STRTAB, 1);
246 	SECTDEF(strtab, STRTAB, 1);
247 
248 	SECTDEF(symtab, SYMTAB, sizeof(uintptr_t));
249 	sect->ofs = offsetof(ir_gdbjit_obj, sym);
250 	sect->size = sizeof(ctx->obj.sym);
251 	sect->link = GDBJIT_SECT_strtab;
252 	sect->entsize = sizeof(ir_elf_symbol);
253 	sect->info = GDBJIT_SYM_FUNC;
254 
255 	SECTDEF(debug_info, PROGBITS, 1);
256 	SECTDEF(debug_abbrev, PROGBITS, 1);
257 	SECTDEF(debug_line, PROGBITS, 1);
258 
259 #undef SECTDEF
260 }
261 
ir_gdbjit_symtab(ir_gdbjit_ctx * ctx)262 static void ir_gdbjit_symtab(ir_gdbjit_ctx *ctx)
263 {
264 	ir_elf_symbol *sym;
265 
266 	*ctx->p++ = '\0';
267 
268 	sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
269 	sym->name = ir_gdbjit_strz(ctx, "JIT code");
270 	sym->sectidx = ELFSECT_IDX_ABS;
271 	sym->info = ELFSYM_INFO(ELFSYM_BIND_LOCAL, ELFSYM_TYPE_FILE);
272 
273 	sym = &ctx->obj.sym[GDBJIT_SYM_FUNC];
274 	sym->name = ir_gdbjit_strz(ctx, ctx->name);
275 	sym->sectidx = GDBJIT_SECT_text;
276 	sym->value = 0;
277 	sym->size = ctx->szmcode;
278 	sym->info = ELFSYM_INFO(ELFSYM_BIND_GLOBAL, ELFSYM_TYPE_FUNC);
279 }
280 
281 typedef IR_SET_ALIGNED(1, uint16_t unaligned_uint16_t);
282 typedef IR_SET_ALIGNED(1, uint32_t unaligned_uint32_t);
283 typedef IR_SET_ALIGNED(1, uintptr_t unaligned_uintptr_t);
284 
285 #define SECTALIGN(p, a) \
286 	  ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
287 
288 /* Shortcuts to generate DWARF structures. */
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); }
301 
ir_gdbjit_ehframe(ir_gdbjit_ctx * ctx,uint32_t sp_offset,uint32_t sp_adjustment)302 static void ir_gdbjit_ehframe(ir_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
303 {
304 	uint8_t *p = ctx->p;
305 	uint8_t *framep = p;
306 
307 	/* DWARF EH CIE (Common Information Entry) */
308 	DSECT(CIE,
309 		DU32(0);                                       /* CIE ID. */
310 		DB(DW_CIE_VERSION);                            /* Version */
311 		DSTR("zR");                                    /* Augmentation String. */
312 		DUV(1);                                        /* Code alignment factor. */
313 		DSV(-(int32_t)sizeof(uintptr_t));              /* Data alignment factor. */
314 		DB(DW_REG_RA);                                 /* Return address register. */
315 		DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4);   /* Augmentation data. */
316 #if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
317 		DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
318 		DB(DW_CFA_offset|DW_REG_RA); DUV(1);
319 #elif defined(IR_TARGET_AARCH64)
320 		DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(0);
321 #endif
322 		DALIGNNOP(sizeof(uintptr_t));
323 	)
324 
325 	/* DWARF EH FDE (Frame Description Entry). */
326 	DSECT(FDE,
327 		DU32((uint32_t)(p-framep)); /* Offset to CIE Pointer. */
328 		DU32(0);                    /* Machine code offset relative to .text. */
329 		DU32(ctx->szmcode);         /* Machine code length. */
330 		DB(0);                      /* Augmentation data. */
331 		DB(DW_CFA_def_cfa_offset); DUV(sp_offset);
332 #if defined(IR_TARGET_AARCH64)
333 		if (sp_offset) {
334 			if (sp_adjustment && sp_adjustment < sp_offset) {
335 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
336 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
337 			} else {
338 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_offset / sizeof(uintptr_t));
339 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_offset / sizeof(uintptr_t)) - 1);
340 			}
341 		}
342 #endif
343 		if (sp_adjustment && sp_adjustment > sp_offset) {
344 			DB(DW_CFA_advance_loc|1); DB(DW_CFA_def_cfa_offset); DUV(sp_adjustment);
345 #if defined(IR_TARGET_AARCH64)
346 			if (!sp_offset) {
347 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
348 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
349 			}
350 #endif
351 		}
352 		DALIGNNOP(sizeof(uintptr_t));
353 	)
354 
355 	ctx->p = p;
356 }
357 
ir_gdbjit_debuginfo(ir_gdbjit_ctx * ctx)358 static void ir_gdbjit_debuginfo(ir_gdbjit_ctx *ctx)
359 {
360 	uint8_t *p = ctx->p;
361 
362 	DSECT(info,
363 		DU16(2);                 /* DWARF version. */
364 		DU32(0);                 /* Abbrev offset. */
365 		DB(sizeof(uintptr_t));   /* Pointer size. */
366 
367 		DUV(1);                  /* Abbrev #1: DW_TAG_compile_unit. */
368 		DSTR(ctx->filename);    /* DW_AT_name. */
369 		DADDR(ctx->mcaddr);     /* DW_AT_low_pc. */
370 		DADDR(ctx->mcaddr + ctx->szmcode);  /* DW_AT_high_pc. */
371 		DU32(0);                /* DW_AT_stmt_list. */
372 	 );
373 
374 	ctx->p = p;
375 }
376 
ir_gdbjit_debugabbrev(ir_gdbjit_ctx * ctx)377 static void ir_gdbjit_debugabbrev(ir_gdbjit_ctx *ctx)
378 {
379 	uint8_t *p = ctx->p;
380 
381 	/* Abbrev #1: DW_TAG_compile_unit. */
382 	DUV(1);
383 	DUV(DW_TAG_compile_unit);
384 	DB(DW_children_no);
385 	DUV(DW_AT_name);
386 	DUV(DW_FORM_string);
387 	DUV(DW_AT_low_pc);
388 	DUV(DW_FORM_addr);
389 	DUV(DW_AT_high_pc);
390 	DUV(DW_FORM_addr);
391 	DUV(DW_AT_stmt_list);
392 	DUV(DW_FORM_data4);
393 	DB(0);
394 	DB(0);
395 	DB(0);
396 
397 	ctx->p = p;
398 }
399 
400 #define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
401 
ir_gdbjit_debugline(ir_gdbjit_ctx * ctx)402 static void ir_gdbjit_debugline(ir_gdbjit_ctx *ctx)
403 {
404 	uint8_t *p = ctx->p;
405 
406 	DSECT(line,
407 		DU16(2);            /* DWARF version. */
408 		DSECT(header,
409 			DB(1);            /* Minimum instruction length. */
410 			DB(1);            /* is_stmt. */
411 			DI8(0);           /* Line base for special opcodes. */
412 			DB(2);            /* Line range for special opcodes. */
413 			DB(3+1);          /* Opcode base at DW_LNS_advance_line+1. */
414 			DB(0); DB(1); DB(1);  /* Standard opcode lengths. */
415 			/* Directory table. */
416 			DB(0);
417 			/* File name table. */
418 			DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
419 			DB(0);
420 		);
421 		DLNE(DW_LNE_set_address, sizeof(uintptr_t));
422 		DADDR(ctx->mcaddr);
423 		if (ctx->lineno) (DB(DW_LNS_advance_line), DSV(ctx->lineno-1));
424 		DB(DW_LNS_copy);
425 		DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
426 		DLNE(DW_LNE_end_sequence, 0);
427 	);
428 
429 	ctx->p = p;
430 }
431 
432 
433 #undef DLNE
434 
435 /* Undef shortcuts. */
436 #undef DB
437 #undef DI8
438 #undef DU16
439 #undef DU32
440 #undef DADDR
441 #undef DUV
442 #undef DSV
443 #undef DSTR
444 #undef DALIGNNOP
445 #undef DSECT
446 
447 typedef void (*ir_gdbjit_initf) (ir_gdbjit_ctx *ctx);
448 
ir_gdbjit_initsect(ir_gdbjit_ctx * ctx,int sect)449 static void ir_gdbjit_initsect(ir_gdbjit_ctx *ctx, int sect)
450 {
451 	ctx->startp = ctx->p;
452 	ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
453 }
454 
ir_gdbjit_initsect_done(ir_gdbjit_ctx * ctx,int sect)455 static void ir_gdbjit_initsect_done(ir_gdbjit_ctx *ctx, int sect)
456 {
457 	ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
458 }
459 
ir_gdbjit_buildobj(ir_gdbjit_ctx * ctx,uint32_t sp_offset,uint32_t sp_adjustment)460 static void ir_gdbjit_buildobj(ir_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
461 {
462 	ir_gdbjit_obj *obj = &ctx->obj;
463 
464 	/* Fill in ELF header and clear structures. */
465 	memcpy(&obj->hdr, &ir_elfhdr_template, sizeof(ir_elf_header));
466 	memset(&obj->sect, 0, sizeof(ir_elf_sectheader) * GDBJIT_SECT__MAX);
467 	memset(&obj->sym, 0, sizeof(ir_elf_symbol) * GDBJIT_SYM__MAX);
468 
469 	/* Initialize sections. */
470 	ctx->p = obj->space;
471 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab); ir_gdbjit_secthdr(ctx); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_shstrtab);
472 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_strtab); ir_gdbjit_symtab(ctx); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_strtab);
473 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_debug_info); ir_gdbjit_debuginfo(ctx); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_info);
474 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev); ir_gdbjit_debugabbrev(ctx); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_abbrev);
475 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_debug_line); ir_gdbjit_debugline(ctx); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_line);
476 	SECTALIGN(ctx->p, sizeof(uintptr_t));
477 	ir_gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame); ir_gdbjit_ehframe(ctx, sp_offset, sp_adjustment); ir_gdbjit_initsect_done(ctx, GDBJIT_SECT_eh_frame);
478 	ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
479 
480 	IR_ASSERT(ctx->objsize < sizeof(ir_gdbjit_obj));
481 }
482 
483 enum {
484 	IR_GDBJIT_NOACTION,
485 	IR_GDBJIT_REGISTER,
486 	IR_GDBJIT_UNREGISTER
487 };
488 
489 typedef struct _ir_gdbjit_code_entry {
490 	struct _ir_gdbjit_code_entry *next_entry;
491 	struct _ir_gdbjit_code_entry *prev_entry;
492 	const char                   *symfile_addr;
493 	uint64_t                      symfile_size;
494 } ir_gdbjit_code_entry;
495 
496 typedef struct _ir_gdbjit_descriptor {
497 	uint32_t                      version;
498 	uint32_t                      action_flag;
499 	struct _ir_gdbjit_code_entry *relevant_entry;
500 	struct _ir_gdbjit_code_entry *first_entry;
501 } ir_gdbjit_descriptor;
502 
503 ir_gdbjit_descriptor __jit_debug_descriptor = {
504 	1, IR_GDBJIT_NOACTION, NULL, NULL
505 };
506 
507 #ifdef IR_EXTERNAL_GDB_ENTRY
508 void __jit_debug_register_code(void);
509 #else
__jit_debug_register_code(void)510 IR_NEVER_INLINE void __jit_debug_register_code(void)
511 {
512 	__asm__ __volatile__("");
513 }
514 #endif
515 
ir_gdb_register_code(const void * object,size_t size)516 static bool ir_gdb_register_code(const void *object, size_t size)
517 {
518 	ir_gdbjit_code_entry *entry;
519 
520 	entry = malloc(sizeof(ir_gdbjit_code_entry) + size);
521 	if (entry == NULL) {
522 		return 0;
523 	}
524 
525 	entry->symfile_addr = ((char*)entry) + sizeof(ir_gdbjit_code_entry);
526 	entry->symfile_size = size;
527 
528 	memcpy((char *)entry->symfile_addr, object, size);
529 
530 	entry->prev_entry = NULL;
531 	entry->next_entry = __jit_debug_descriptor.first_entry;
532 
533 	if (entry->next_entry) {
534 		entry->next_entry->prev_entry = entry;
535 	}
536 	__jit_debug_descriptor.first_entry = entry;
537 
538 	/* Notify GDB */
539 	__jit_debug_descriptor.relevant_entry = entry;
540 	__jit_debug_descriptor.action_flag = IR_GDBJIT_REGISTER;
541 	__jit_debug_register_code();
542 
543 	return 1;
544 }
545 
ir_gdb_unregister_all(void)546 void ir_gdb_unregister_all(void)
547 {
548 	ir_gdbjit_code_entry *entry;
549 
550 	__jit_debug_descriptor.action_flag = IR_GDBJIT_UNREGISTER;
551 	while ((entry = __jit_debug_descriptor.first_entry)) {
552 		__jit_debug_descriptor.first_entry = entry->next_entry;
553 		if (entry->next_entry) {
554 			entry->next_entry->prev_entry = NULL;
555 		}
556 		/* Notify GDB */
557 		__jit_debug_descriptor.relevant_entry = entry;
558 		__jit_debug_register_code();
559 
560 		free(entry);
561 	}
562 }
563 
564 #if defined(__FreeBSD__)
ir_gdb_info_proc(pid_t pid,struct kinfo_proc * proc)565 static bool ir_gdb_info_proc(pid_t pid, struct kinfo_proc *proc)
566 {
567 	size_t len, plen;
568 	len = plen = sizeof(*proc);
569 	int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
570 
571 	if (sysctl(mib, 4, proc, &len, NULL, 0) < 0 || len != plen ||
572             proc->ki_structsize != (int)plen || proc->ki_pid != pid) {
573 		return false;
574 	}
575 
576 	return true;
577 }
578 #endif
579 
ir_gdb_present(void)580 bool ir_gdb_present(void)
581 {
582 	bool ret = 0;
583 #if defined(__linux__) /* netbsd while having this procfs part, does not hold the tracer pid */
584 	int fd = open("/proc/self/status", O_RDONLY);
585 
586 	if (fd > 0) {
587 		char buf[1024];
588 		ssize_t n = read(fd, buf, sizeof(buf) - 1);
589 		char *s;
590 		pid_t pid;
591 
592 		if (n > 0) {
593 			buf[n] = 0;
594 			s = strstr(buf, "TracerPid:");
595 			if (s) {
596 				s += sizeof("TracerPid:") - 1;
597 				while (*s == ' ' || *s == '\t') {
598 					s++;
599 				}
600 				pid = atoi(s);
601 				if (pid) {
602 					char out[1024];
603 					snprintf(buf, sizeof(buf), "/proc/%d/exe", (int)pid);
604 					if (readlink(buf, out, sizeof(out) - 1) > 0) {
605 						if (strstr(out, "gdb")) {
606 							ret = 1;
607 						}
608 					}
609 				}
610 			}
611 		}
612 
613 		close(fd);
614 	}
615 #elif defined(__FreeBSD__)
616     struct kinfo_proc proc, dbg;
617 
618     if (ir_gdb_info_proc(getpid(), &proc)) {
619         if ((proc.ki_flag & P_TRACED) != 0) {
620             if (ir_gdb_info_proc(proc.ki_tracer, &dbg)) {
621             	ret = strstr(dbg.ki_comm, "gdb");
622 	    }
623         }
624     }
625 #endif
626 
627 	return ret;
628 }
629 
ir_gdb_register(const char * name,const void * start,size_t size,uint32_t sp_offset,uint32_t sp_adjustment)630 int ir_gdb_register(const char    *name,
631                     const void    *start,
632                     size_t         size,
633                     uint32_t       sp_offset,
634                     uint32_t       sp_adjustment)
635 {
636 	ir_gdbjit_ctx ctx;
637 
638 	ctx.mcaddr = (uintptr_t)start;
639 	ctx.szmcode = (uint32_t)size;
640 	ctx.name = name;
641 	ctx.filename = "unknown";
642 	ctx.lineno = 0;
643 
644 	ir_gdbjit_buildobj(&ctx, sp_offset, sp_adjustment);
645 
646 	return ir_gdb_register_code(&ctx.obj, ctx.objsize);
647 }
648 
ir_gdb_init(void)649 void ir_gdb_init(void)
650 {
651 	/* This might enable registration of all JIT-ed code, but unfortunately,
652 	 * in case of many functions, this takes enormous time. */
653 	if (ir_gdb_present()) {
654 #if 0
655 		_debug |= IR_DEBUG_GDB;
656 #endif
657 	}
658 }
659