xref: /PHP-8.1/ext/opcache/jit/zend_jit_gdb.c (revision 6157fcc0)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend JIT                                                             |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | https://www.php.net/license/3_01.txt                                 |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Dmitry Stogov <dmitry@php.net>                              |
16    |          Xinchen Hui <laruence@php.net>                              |
17    +----------------------------------------------------------------------+
18    | Based on Mike Pall's implementation of GDB interface for LuaJIT.     |
19    | LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/        |
20    +----------------------------------------------------------------------+
21 */
22 
23 
24 #define HAVE_GDB
25 
26 #include "zend_jit_gdb.h"
27 #include "zend_elf.h"
28 #include "zend_gdb.h"
29 
30 /* DWARF definitions. */
31 #define DW_CIE_VERSION  1
32 
33 /* CFA (Canonical frame address) */
34 enum {
35 	DW_CFA_nop = 0x0,
36 	DW_CFA_offset_extended = 0x5,
37 	DW_CFA_def_cfa = 0xc,
38 	DW_CFA_def_cfa_offset = 0xe,
39 	DW_CFA_offset_extended_sf = 0x11,
40 	DW_CFA_advance_loc = 0x40,
41 	DW_CFA_offset = 0x80
42 };
43 
44 enum {
45 	DW_EH_PE_udata4 = 0x03,
46 	DW_EH_PE_textrel = 0x20
47 };
48 
49 enum {
50 	DW_TAG_compile_unit = 0x11
51 };
52 
53 enum {
54 	DW_children_no = 0,
55 	DW_children_yes = 1
56 };
57 
58 enum {
59 	DW_AT_name = 0x03,
60 	DW_AT_stmt_list = 0x10,
61 	DW_AT_low_pc = 0x11,
62 	DW_AT_high_pc = 0x12
63 };
64 
65 enum {
66 	DW_FORM_addr = 0x01,
67 	DW_FORM_data4 = 0x06,
68 	DW_FORM_string = 0x08
69 };
70 
71 enum {
72 	DW_LNS_extended_op = 0,
73 	DW_LNS_copy = 1,
74 	DW_LNS_advance_pc = 2,
75 	DW_LNS_advance_line = 3
76 };
77 
78 enum {
79 	DW_LNE_end_sequence = 1,
80 	DW_LNE_set_address = 2
81 };
82 
83 enum {
84 #if defined(__i386__)
85 	DW_REG_AX, DW_REG_CX, DW_REG_DX, DW_REG_BX,
86 	DW_REG_SP, DW_REG_BP, DW_REG_SI, DW_REG_DI,
87 	DW_REG_RA,
88 #elif defined(__x86_64__)
89 	/* Yes, the order is strange, but correct. */
90 	DW_REG_AX, DW_REG_DX, DW_REG_CX, DW_REG_BX,
91 	DW_REG_SI, DW_REG_DI, DW_REG_BP, DW_REG_SP,
92 	DW_REG_8, DW_REG_9, DW_REG_10, DW_REG_11,
93 	DW_REG_12, DW_REG_13, DW_REG_14, DW_REG_15,
94 	DW_REG_RA,
95 #elif defined(__aarch64__)
96 	DW_REG_SP = 31,
97 	DW_REG_RA = 30,
98 	DW_REG_X29 = 29,
99 #else
100 #error "Unsupported target architecture"
101 #endif
102 };
103 
104 enum {
105 	GDBJIT_SECT_NULL,
106 	GDBJIT_SECT_text,
107 	GDBJIT_SECT_eh_frame,
108 	GDBJIT_SECT_shstrtab,
109 	GDBJIT_SECT_strtab,
110 	GDBJIT_SECT_symtab,
111 	GDBJIT_SECT_debug_info,
112 	GDBJIT_SECT_debug_abbrev,
113 	GDBJIT_SECT_debug_line,
114 	GDBJIT_SECT__MAX
115 };
116 
117 enum {
118 	GDBJIT_SYM_UNDEF,
119 	GDBJIT_SYM_FILE,
120 	GDBJIT_SYM_FUNC,
121 	GDBJIT_SYM__MAX
122 };
123 
124 typedef struct _zend_gdbjit_obj {
125 	zend_elf_header     hdr;
126 	zend_elf_sectheader sect[GDBJIT_SECT__MAX];
127 	zend_elf_symbol     sym[GDBJIT_SYM__MAX];
128 	uint8_t             space[4096];
129 } zend_gdbjit_obj;
130 
131 static const zend_elf_header zend_elfhdr_template = {
132 	.emagic      = { 0x7f, 'E', 'L', 'F' },
133 #ifdef ELF64
134 	.eclass      = 2,
135 #else
136 	.eclass      = 1,
137 #endif
138 #ifdef WORDS_BIGENDIAN
139 	.eendian     = 2,
140 #else
141 	.eendian     = 1,
142 #endif
143 	.eversion    = 1,
144 #if defined(Linux)
145 	.eosabi      = 0,  /* Nope, it's not 3. ??? */
146 #elif defined(__FreeBSD__)
147 	.eosabi      = 9,
148 #elif defined(__OpenBSD__)
149 	.eosabi      = 12,
150 #elif defined(__NetBSD__)
151 	.eosabi      = 2,
152 #elif defined(__DragonFly__)
153 	.eosabi      = 0,
154 #elif (defined(__sun__) && defined(__svr4__))
155 	.eosabi      = 6,
156 #else
157 	.eosabi      = 0,
158 #endif
159 	.eabiversion = 0,
160 	.epad        = { 0, 0, 0, 0, 0, 0, 0 },
161 	.type        = 1,
162 #if defined(__i386__)
163 	.machine     = 3,
164 #elif defined(__x86_64__)
165 	.machine     = 62,
166 #elif defined(__aarch64__)
167 	.machine     = 183,
168 #else
169 # error "Unsupported target architecture"
170 #endif
171 	.version     = 1,
172 	.entry       = 0,
173 	.phofs       = 0,
174 	.shofs       = offsetof(zend_gdbjit_obj, sect),
175 	.flags       = 0,
176 	.ehsize      = sizeof(zend_elf_header),
177 	.phentsize   = 0,
178 	.phnum       = 0,
179 	.shentsize   = sizeof(zend_elf_sectheader),
180 	.shnum       = GDBJIT_SECT__MAX,
181 	.shstridx    = GDBJIT_SECT_shstrtab
182 };
183 
184 /* Context for generating the ELF object for the GDB JIT API. */
185 typedef struct _zend_gdbjit_ctx {
186 	uint8_t *p;              /* Pointer to next address in obj.space. */
187 	uint8_t *startp;         /* Pointer to start address in obj.space. */
188 	uintptr_t mcaddr;        /* Machine code address. */
189 	uint32_t szmcode;        /* Size of machine code. */
190 	int32_t  lineno;         /* Starting line number. */
191 	const char *name;        /* JIT function name */
192 	const char *filename;    /* Starting file name. */
193 	size_t objsize;          /* Final size of ELF object. */
194 	zend_gdbjit_obj obj;     /* In-memory ELF object. */
195 } zend_gdbjit_ctx;
196 
197 /* Add a zero-terminated string */
zend_gdbjit_strz(zend_gdbjit_ctx * ctx,const char * str)198 static uint32_t zend_gdbjit_strz(zend_gdbjit_ctx *ctx, const char *str)
199 {
200 	uint8_t *p = ctx->p;
201 	uint32_t ofs = (uint32_t)(p - ctx->startp);
202 	do {
203 		*p++ = (uint8_t)*str;
204 	} while (*str++);
205 	ctx->p = p;
206 	return ofs;
207 }
208 
209 /* Add a ULEB128 value */
zend_gdbjit_uleb128(zend_gdbjit_ctx * ctx,uint32_t v)210 static void zend_gdbjit_uleb128(zend_gdbjit_ctx *ctx, uint32_t v)
211 {
212 	uint8_t *p = ctx->p;
213 	for (; v >= 0x80; v >>= 7)
214 		*p++ = (uint8_t)((v & 0x7f) | 0x80);
215 	*p++ = (uint8_t)v;
216 	ctx->p = p;
217 }
218 
219 /* Add a SLEB128 value */
zend_gdbjit_sleb128(zend_gdbjit_ctx * ctx,int32_t v)220 static void zend_gdbjit_sleb128(zend_gdbjit_ctx *ctx, int32_t v)
221 {
222 	uint8_t *p = ctx->p;
223 	for (; (uint32_t)(v+0x40) >= 0x80; v >>= 7)
224 		*p++ = (uint8_t)((v & 0x7f) | 0x80);
225 	*p++ = (uint8_t)(v & 0x7f);
226 	ctx->p = p;
227 }
228 
zend_gdbjit_secthdr(zend_gdbjit_ctx * ctx)229 static void zend_gdbjit_secthdr(zend_gdbjit_ctx *ctx)
230 {
231 	zend_elf_sectheader *sect;
232 
233 	*ctx->p++ = '\0';
234 
235 #define SECTDEF(id, tp, al)                       \
236 	sect = &ctx->obj.sect[GDBJIT_SECT_##id];      \
237 	sect->name = zend_gdbjit_strz(ctx, "." #id);  \
238 	sect->type = ELFSECT_TYPE_##tp;               \
239 	sect->align = (al)
240 
241 	SECTDEF(text, NOBITS, 16);
242 	sect->flags = ELFSECT_FLAGS_ALLOC|ELFSECT_FLAGS_EXEC;
243 	sect->addr = ctx->mcaddr;
244 	sect->ofs = 0;
245 	sect->size = ctx->szmcode;
246 
247 	SECTDEF(eh_frame, PROGBITS, sizeof(uintptr_t));
248 	sect->flags = ELFSECT_FLAGS_ALLOC;
249 
250 	SECTDEF(shstrtab, STRTAB, 1);
251 	SECTDEF(strtab, STRTAB, 1);
252 
253 	SECTDEF(symtab, SYMTAB, sizeof(uintptr_t));
254 	sect->ofs = offsetof(zend_gdbjit_obj, sym);
255 	sect->size = sizeof(ctx->obj.sym);
256 	sect->link = GDBJIT_SECT_strtab;
257 	sect->entsize = sizeof(zend_elf_symbol);
258 	sect->info = GDBJIT_SYM_FUNC;
259 
260 	SECTDEF(debug_info, PROGBITS, 1);
261 	SECTDEF(debug_abbrev, PROGBITS, 1);
262 	SECTDEF(debug_line, PROGBITS, 1);
263 
264 #undef SECTDEF
265 }
266 
zend_gdbjit_symtab(zend_gdbjit_ctx * ctx)267 static void zend_gdbjit_symtab(zend_gdbjit_ctx *ctx)
268 {
269 	zend_elf_symbol *sym;
270 
271 	*ctx->p++ = '\0';
272 
273 	sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
274 	sym->name = zend_gdbjit_strz(ctx, "JIT code");
275 	sym->sectidx = ELFSECT_IDX_ABS;
276 	sym->info = ELFSYM_INFO(ELFSYM_BIND_LOCAL, ELFSYM_TYPE_FILE);
277 
278 	sym = &ctx->obj.sym[GDBJIT_SYM_FUNC];
279 	sym->name = zend_gdbjit_strz(ctx, ctx->name);
280 	sym->sectidx = GDBJIT_SECT_text;
281 	sym->value = 0;
282 	sym->size = ctx->szmcode;
283 	sym->info = ELFSYM_INFO(ELFSYM_BIND_GLOBAL, ELFSYM_TYPE_FUNC);
284 }
285 
286 typedef ZEND_SET_ALIGNED(1, uint16_t unaligned_uint16_t);
287 typedef ZEND_SET_ALIGNED(1, uint32_t unaligned_uint32_t);
288 typedef ZEND_SET_ALIGNED(1, uintptr_t unaligned_uintptr_t);
289 
290 #define SECTALIGN(p, a) \
291 	  ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
292 
293 /* Shortcuts to generate DWARF structures. */
294 #define DB(x)       (*p++ = (x))
295 #define DI8(x)      (*(int8_t *)p = (x), p++)
296 #define DU16(x)     (*(unaligned_uint16_t *)p = (x), p += 2)
297 #define DU32(x)     (*(unaligned_uint32_t *)p = (x), p += 4)
298 #define DADDR(x)    (*(unaligned_uintptr_t *)p = (x), p += sizeof(uintptr_t))
299 #define DUV(x)      (ctx->p = p, zend_gdbjit_uleb128(ctx, (x)), p = ctx->p)
300 #define DSV(x)      (ctx->p = p, zend_gdbjit_sleb128(ctx, (x)), p = ctx->p)
301 #define DSTR(str)   (ctx->p = p, zend_gdbjit_strz(ctx, (str)), p = ctx->p)
302 #define DALIGNNOP(s)    while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
303 #define DSECT(name, stmt) \
304 	{ unaligned_uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
305 		*szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); }
306 
zend_gdbjit_ehframe(zend_gdbjit_ctx * ctx,uint32_t sp_offset,uint32_t sp_adjustment)307 static void zend_gdbjit_ehframe(zend_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
308 {
309 	uint8_t *p = ctx->p;
310 	uint8_t *framep = p;
311 
312 	/* DWARF EH CIE (Common Information Entry) */
313 	DSECT(CIE,
314 		DU32(0);                                       /* CIE ID. */
315 		DB(DW_CIE_VERSION);                            /* Version */
316 		DSTR("zR");                                    /* Augmentation String. */
317 		DUV(1);                                        /* Code alignment factor. */
318 		DSV(-(int32_t)sizeof(uintptr_t));              /* Data alignment factor. */
319 		DB(DW_REG_RA);                                 /* Return address register. */
320 		DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4);   /* Augmentation data. */
321 #if defined(__x86_64__) || defined(i386)
322 		DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
323 		DB(DW_CFA_offset|DW_REG_RA); DUV(1);
324 #elif defined(__aarch64__)
325 		DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(0);
326 #endif
327 		DALIGNNOP(sizeof(uintptr_t));
328 	)
329 
330 	/* DWARF EH FDE (Frame Description Entry). */
331 	DSECT(FDE,
332 		DU32((uint32_t)(p-framep)); /* Offset to CIE Pointer. */
333 		DU32(0);                    /* Machine code offset relative to .text. */
334 		DU32(ctx->szmcode);         /* Machine code length. */
335 		DB(0);                      /* Augmentation data. */
336 		DB(DW_CFA_def_cfa_offset); DUV(sp_offset);
337 #if defined(__aarch64__)
338 		if (sp_offset) {
339 			if (sp_adjustment && sp_adjustment < sp_offset) {
340 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
341 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
342 			} else {
343 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_offset / sizeof(uintptr_t));
344 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_offset / sizeof(uintptr_t)) - 1);
345 			}
346 		}
347 #endif
348 		if (sp_adjustment && sp_adjustment > sp_offset) {
349 			DB(DW_CFA_advance_loc|1); DB(DW_CFA_def_cfa_offset); DUV(sp_adjustment);
350 #if defined(__aarch64__)
351 			if (!sp_offset) {
352 				DB(DW_CFA_offset|DW_REG_X29); DUV(sp_adjustment / sizeof(uintptr_t));
353 				DB(DW_CFA_offset|DW_REG_RA); DUV((sp_adjustment / sizeof(uintptr_t)) - 1);
354 			}
355 #endif
356 		}
357 		DALIGNNOP(sizeof(uintptr_t));
358 	)
359 
360 	ctx->p = p;
361 }
362 
zend_gdbjit_debuginfo(zend_gdbjit_ctx * ctx)363 static void zend_gdbjit_debuginfo(zend_gdbjit_ctx *ctx)
364 {
365 	uint8_t *p = ctx->p;
366 
367 	DSECT(info,
368 		DU16(2);                 /* DWARF version. */
369 		DU32(0);                 /* Abbrev offset. */
370 		DB(sizeof(uintptr_t));   /* Pointer size. */
371 
372 		DUV(1);                  /* Abbrev #1: DW_TAG_compile_unit. */
373 		DSTR(ctx->filename);    /* DW_AT_name. */
374 		DADDR(ctx->mcaddr);     /* DW_AT_low_pc. */
375 		DADDR(ctx->mcaddr + ctx->szmcode);  /* DW_AT_high_pc. */
376 		DU32(0);                /* DW_AT_stmt_list. */
377 	 );
378 
379 	ctx->p = p;
380 }
381 
zend_gdbjit_debugabbrev(zend_gdbjit_ctx * ctx)382 static void zend_gdbjit_debugabbrev(zend_gdbjit_ctx *ctx)
383 {
384 	uint8_t *p = ctx->p;
385 
386 	/* Abbrev #1: DW_TAG_compile_unit. */
387 	DUV(1);
388 	DUV(DW_TAG_compile_unit);
389 	DB(DW_children_no);
390 	DUV(DW_AT_name);
391 	DUV(DW_FORM_string);
392 	DUV(DW_AT_low_pc);
393 	DUV(DW_FORM_addr);
394 	DUV(DW_AT_high_pc);
395 	DUV(DW_FORM_addr);
396 	DUV(DW_AT_stmt_list);
397 	DUV(DW_FORM_data4);
398 	DB(0);
399 	DB(0);
400 
401 	ctx->p = p;
402 }
403 
404 #define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
405 
zend_gdbjit_debugline(zend_gdbjit_ctx * ctx)406 static void zend_gdbjit_debugline(zend_gdbjit_ctx *ctx)
407 {
408 	uint8_t *p = ctx->p;
409 
410 	DSECT(line,
411 		DU16(2);            /* DWARF version. */
412 		DSECT(header,
413 			DB(1);            /* Minimum instruction length. */
414 			DB(1);            /* is_stmt. */
415 			DI8(0);           /* Line base for special opcodes. */
416 			DB(2);            /* Line range for special opcodes. */
417 			DB(3+1);          /* Opcode base at DW_LNS_advance_line+1. */
418 			DB(0); DB(1); DB(1);  /* Standard opcode lengths. */
419 			/* Directory table. */
420 			DB(0);
421 			/* File name table. */
422 			DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
423 			DB(0);
424 		);
425 		DLNE(DW_LNE_set_address, sizeof(uintptr_t));
426 		DADDR(ctx->mcaddr);
427 		if (ctx->lineno) (DB(DW_LNS_advance_line), DSV(ctx->lineno-1));
428 		DB(DW_LNS_copy);
429 		DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
430 		DLNE(DW_LNE_end_sequence, 0);
431 	);
432 
433 	ctx->p = p;
434 }
435 
436 
437 #undef DLNE
438 
439 /* Undef shortcuts. */
440 #undef DB
441 #undef DI8
442 #undef DU16
443 #undef DU32
444 #undef DADDR
445 #undef DUV
446 #undef DSV
447 #undef DSTR
448 #undef DALIGNNOP
449 #undef DSECT
450 
451 typedef void (*zend_gdbjit_initf) (zend_gdbjit_ctx *ctx);
452 
zend_gdbjit_initsect(zend_gdbjit_ctx * ctx,int sect)453 static void zend_gdbjit_initsect(zend_gdbjit_ctx *ctx, int sect)
454 {
455 	ctx->startp = ctx->p;
456 	ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
457 }
458 
zend_gdbjit_initsect_done(zend_gdbjit_ctx * ctx,int sect)459 static void zend_gdbjit_initsect_done(zend_gdbjit_ctx *ctx, int sect)
460 {
461 	ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
462 }
463 
zend_gdbjit_buildobj(zend_gdbjit_ctx * ctx,uint32_t sp_offset,uint32_t sp_adjustment)464 static void zend_gdbjit_buildobj(zend_gdbjit_ctx *ctx, uint32_t sp_offset, uint32_t sp_adjustment)
465 {
466 	zend_gdbjit_obj *obj = &ctx->obj;
467 
468 	/* Fill in ELF header and clear structures. */
469 	memcpy(&obj->hdr, &zend_elfhdr_template, sizeof(zend_elf_header));
470 	memset(&obj->sect, 0, sizeof(zend_elf_sectheader) * GDBJIT_SECT__MAX);
471 	memset(&obj->sym, 0, sizeof(zend_elf_symbol) * GDBJIT_SYM__MAX);
472 
473 	/* Initialize sections. */
474 	ctx->p = obj->space;
475 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab); zend_gdbjit_secthdr(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_shstrtab);
476 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_strtab); zend_gdbjit_symtab(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_strtab);
477 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_info); zend_gdbjit_debuginfo(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_info);
478 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev); zend_gdbjit_debugabbrev(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_abbrev);
479 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_line); zend_gdbjit_debugline(ctx); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_debug_line);
480 	SECTALIGN(ctx->p, sizeof(uintptr_t));
481 	zend_gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame); zend_gdbjit_ehframe(ctx, sp_offset, sp_adjustment); zend_gdbjit_initsect_done(ctx, GDBJIT_SECT_eh_frame);
482 	ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
483 
484 	ZEND_ASSERT(ctx->objsize < sizeof(zend_gdbjit_obj));
485 }
486 
zend_jit_gdb_register(const char * name,const zend_op_array * op_array,const void * start,size_t size,uint32_t sp_offset,uint32_t sp_adjustment)487 int zend_jit_gdb_register(const char    *name,
488                           const zend_op_array *op_array,
489                           const void    *start,
490                           size_t         size,
491                           uint32_t       sp_offset,
492                           uint32_t       sp_adjustment)
493 {
494 	zend_gdbjit_ctx ctx;
495 
496 	ctx.mcaddr = (uintptr_t)start;
497 	ctx.szmcode = (uint32_t)size;
498 	ctx.name = name;
499 	ctx.filename = op_array ? ZSTR_VAL(op_array->filename) : "unknown";
500 	ctx.lineno = op_array ? op_array->line_start : 0;
501 
502 	zend_gdbjit_buildobj(&ctx, sp_offset, sp_adjustment);
503 
504 	return zend_gdb_register_code(&ctx.obj, ctx.objsize);
505 }
506 
zend_jit_gdb_unregister(void)507 int zend_jit_gdb_unregister(void)
508 {
509 	zend_gdb_unregister_all();
510 	return 1;
511 }
512 
zend_jit_gdb_init(void)513 void zend_jit_gdb_init(void)
514 {
515 #if 0
516 	/* This might enable registration of all JIT-ed code, but unfortunately,
517 	 * in case of many functions, this takes enormous time. */
518 	if (zend_gdb_present()) {
519 		JIT_G(debug) |= ZEND_JIT_DEBUG_GDB;
520 	}
521 #endif
522 }
523