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 | http://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 #define HAVE_GDB
24
25 #ifdef HAVE_GDB
26
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 /* TODO: ARM supports? */
96 #else
97 #error "Unsupported target architecture"
98 #endif
99 };
100
101 enum {
102 GDBJIT_SECT_NULL,
103 GDBJIT_SECT_text,
104 GDBJIT_SECT_eh_frame,
105 GDBJIT_SECT_shstrtab,
106 GDBJIT_SECT_strtab,
107 GDBJIT_SECT_symtab,
108 GDBJIT_SECT_debug_info,
109 GDBJIT_SECT_debug_abbrev,
110 GDBJIT_SECT_debug_line,
111 GDBJIT_SECT__MAX
112 };
113
114 enum {
115 GDBJIT_SYM_UNDEF,
116 GDBJIT_SYM_FILE,
117 GDBJIT_SYM_FUNC,
118 GDBJIT_SYM__MAX
119 };
120
121 typedef struct _zend_gdbjit_obj {
122 zend_elf_header hdr;
123 zend_elf_sectheader sect[GDBJIT_SECT__MAX];
124 zend_elf_symbol sym[GDBJIT_SYM__MAX];
125 uint8_t space[4096];
126 } zend_gdbjit_obj;
127
128 static const zend_elf_header zend_elfhdr_template = {
129 .emagic = { 0x7f, 'E', 'L', 'F' },
130 #ifdef ELF64
131 .eclass = 2,
132 #else
133 .eclass = 1,
134 #endif
135 #ifdef WORDS_BIGENDIAN
136 .eendian = 2,
137 #else
138 .eendian = 1,
139 #endif
140 .eversion = 1,
141 #if defined(Linux)
142 .eosabi = 0, /* Nope, it's not 3. ??? */
143 #elif defined(__FreeBSD__)
144 .eosabi = 9,
145 #elif defined(__OpenBSD__)
146 .eosabi = 12,
147 #elif defined(__NetBSD__)
148 .eosabi = 2,
149 #elif defined(__DragonFly__)
150 .eosabi = 0,
151 #elif (defined(__sun__) && defined(__svr4__))
152 .eosabi = 6,
153 #else
154 .eosabi = 0,
155 #endif
156 .eabiversion = 0,
157 .epad = { 0, 0, 0, 0, 0, 0, 0 },
158 .type = 1,
159 #if defined(__i386__)
160 .machine = 3,
161 #elif defined(__x86_64__)
162 .machine = 62,
163 #else
164 # error "Unsupported target architecture"
165 #endif
166 .version = 1,
167 .entry = 0,
168 .phofs = 0,
169 .shofs = offsetof(zend_gdbjit_obj, sect),
170 .flags = 0,
171 .ehsize = sizeof(zend_elf_header),
172 .phentsize = 0,
173 .phnum = 0,
174 .shentsize = sizeof(zend_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 _zend_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 zend_gdbjit_obj obj; /* In-memory ELF object. */
190 } zend_gdbjit_ctx;
191
192 /* Add a zero-terminated string */
zend_gdbjit_strz(zend_gdbjit_ctx * ctx,const char * str)193 static uint32_t zend_gdbjit_strz(zend_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 */
zend_gdbjit_uleb128(zend_gdbjit_ctx * ctx,uint32_t v)205 static void zend_gdbjit_uleb128(zend_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 */
zend_gdbjit_sleb128(zend_gdbjit_ctx * ctx,int32_t v)215 static void zend_gdbjit_sleb128(zend_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
zend_gdbjit_secthdr(zend_gdbjit_ctx * ctx)224 static void zend_gdbjit_secthdr(zend_gdbjit_ctx *ctx)
225 {
226 zend_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 = zend_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(zend_gdbjit_obj, sym);
250 sect->size = sizeof(ctx->obj.sym);
251 sect->link = GDBJIT_SECT_strtab;
252 sect->entsize = sizeof(zend_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
zend_gdbjit_symtab(zend_gdbjit_ctx * ctx)262 static void zend_gdbjit_symtab(zend_gdbjit_ctx *ctx)
263 {
264 zend_elf_symbol *sym;
265
266 *ctx->p++ = '\0';
267
268 sym = &ctx->obj.sym[GDBJIT_SYM_FILE];
269 sym->name = zend_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 = zend_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 #define SECTALIGN(p, a) \
282 ((p) = (uint8_t *)(((uintptr_t)(p) + ((a)-1)) & ~(uintptr_t)((a)-1)))
283
284 /* Shortcuts to generate DWARF structures. */
285 #define DB(x) (*p++ = (x))
286 #define DI8(x) (*(int8_t *)p = (x), p++)
287 #define DU16(x) (*(uint16_t *)p = (x), p += 2)
288 #define DU32(x) (*(uint32_t *)p = (x), p += 4)
289 #define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t))
290 #define DUV(x) (ctx->p = p, zend_gdbjit_uleb128(ctx, (x)), p = ctx->p)
291 #define DSV(x) (ctx->p = p, zend_gdbjit_sleb128(ctx, (x)), p = ctx->p)
292 #define DSTR(str) (ctx->p = p, zend_gdbjit_strz(ctx, (str)), p = ctx->p)
293 #define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
294 #define DSECT(name, stmt) \
295 { uint32_t *szp_##name = (uint32_t *)p; p += 4; stmt \
296 *szp_##name = (uint32_t)((p-(uint8_t *)szp_##name)-4); }
297
zend_gdbjit_ehframe(zend_gdbjit_ctx * ctx)298 static void zend_gdbjit_ehframe(zend_gdbjit_ctx *ctx)
299 {
300 uint8_t *p = ctx->p;
301 uint8_t *framep = p;
302
303 /* DWARF EH CIE (Common Information Entry) */
304 DSECT(CIE,
305 DU32(0); /* CIE ID. */
306 DB(DW_CIE_VERSION); /* Version */
307 DSTR("zR"); /* Augmentation String. */
308 DUV(1); /* Code alignment factor. */
309 DSV(-(int32_t)sizeof(uintptr_t)); /* Data alignment factor. */
310 DB(DW_REG_RA); /* Return address register. */
311 DB(1); DB(DW_EH_PE_textrel|DW_EH_PE_udata4); /* Augmentation data. */
312 DB(DW_CFA_def_cfa); DUV(DW_REG_SP); DUV(sizeof(uintptr_t));
313 DB(DW_CFA_offset|DW_REG_RA); DUV(1);
314 DALIGNNOP(sizeof(uintptr_t));
315 )
316
317 /* DWARF EH FDE (Frame Description Entry). */
318 DSECT(FDE,
319 DU32((uint32_t)(p-framep)); /* Offset to CIE Pointer. */
320 DU32(0); /* Machine code offset relative to .text. */
321 DU32(ctx->szmcode); /* Machine code length. */
322 DB(0); /* Augmentation data. */
323 DB(DW_CFA_def_cfa_offset); DUV(sizeof(uintptr_t));
324 #if defined(__i386__)
325 DB(DW_CFA_advance_loc|3); /* sub $0xc,%esp */
326 DB(DW_CFA_def_cfa_offset); DUV(16); /* Aligned stack frame size. */
327 #elif defined(__x86_64__)
328 DB(DW_CFA_advance_loc|4); /* sub $0x8,%rsp */
329 DB(DW_CFA_def_cfa_offset); DUV(16); /* Aligned stack frame size. */
330 #else
331 # error "Unsupported target architecture"
332 #endif
333 DALIGNNOP(sizeof(uintptr_t));
334 )
335
336 ctx->p = p;
337 }
338
zend_gdbjit_debuginfo(zend_gdbjit_ctx * ctx)339 static void zend_gdbjit_debuginfo(zend_gdbjit_ctx *ctx)
340 {
341 uint8_t *p = ctx->p;
342
343 DSECT(info,
344 DU16(2); /* DWARF version. */
345 DU32(0); /* Abbrev offset. */
346 DB(sizeof(uintptr_t)); /* Pointer size. */
347
348 DUV(1); /* Abbrev #1: DW_TAG_compile_unit. */
349 DSTR(ctx->filename); /* DW_AT_name. */
350 DADDR(ctx->mcaddr); /* DW_AT_low_pc. */
351 DADDR(ctx->mcaddr + ctx->szmcode); /* DW_AT_high_pc. */
352 DU32(0); /* DW_AT_stmt_list. */
353 );
354
355 ctx->p = p;
356 }
357
zend_gdbjit_debugabbrev(zend_gdbjit_ctx * ctx)358 static void zend_gdbjit_debugabbrev(zend_gdbjit_ctx *ctx)
359 {
360 uint8_t *p = ctx->p;
361
362 /* Abbrev #1: DW_TAG_compile_unit. */
363 DUV(1);
364 DUV(DW_TAG_compile_unit);
365 DB(DW_children_no);
366 DUV(DW_AT_name);
367 DUV(DW_FORM_string);
368 DUV(DW_AT_low_pc);
369 DUV(DW_FORM_addr);
370 DUV(DW_AT_high_pc);
371 DUV(DW_FORM_addr);
372 DUV(DW_AT_stmt_list);
373 DUV(DW_FORM_data4);
374 DB(0);
375 DB(0);
376
377 ctx->p = p;
378 }
379
380 #define DLNE(op, s) (DB(DW_LNS_extended_op), DUV(1+(s)), DB((op)))
381
zend_gdbjit_debugline(zend_gdbjit_ctx * ctx)382 static void zend_gdbjit_debugline(zend_gdbjit_ctx *ctx)
383 {
384 uint8_t *p = ctx->p;
385
386 DSECT(line,
387 DU16(2); /* DWARF version. */
388 DSECT(header,
389 DB(1); /* Minimum instruction length. */
390 DB(1); /* is_stmt. */
391 DI8(0); /* Line base for special opcodes. */
392 DB(2); /* Line range for special opcodes. */
393 DB(3+1); /* Opcode base at DW_LNS_advance_line+1. */
394 DB(0); DB(1); DB(1); /* Standard opcode lengths. */
395 /* Directory table. */
396 DB(0);
397 /* File name table. */
398 DSTR(ctx->filename); DUV(0); DUV(0); DUV(0);
399 DB(0);
400 );
401 DLNE(DW_LNE_set_address, sizeof(uintptr_t));
402 DADDR(ctx->mcaddr);
403 if (ctx->lineno) (DB(DW_LNS_advance_line), DSV(ctx->lineno-1));
404 DB(DW_LNS_copy);
405 DB(DW_LNS_advance_pc); DUV(ctx->szmcode);
406 DLNE(DW_LNE_end_sequence, 0);
407 );
408
409 ctx->p = p;
410 }
411
412
413 #undef DLNE
414
415 /* Undef shortcuts. */
416 #undef DB
417 #undef DI8
418 #undef DU16
419 #undef DU32
420 #undef DADDR
421 #undef DUV
422 #undef DSV
423 #undef DSTR
424 #undef DALIGNNOP
425 #undef DSECT
426
427 typedef void (*zend_gdbjit_initf) (zend_gdbjit_ctx *ctx);
428
zend_gdbjit_initsect(zend_gdbjit_ctx * ctx,int sect,zend_gdbjit_initf initf)429 static void zend_gdbjit_initsect(zend_gdbjit_ctx *ctx, int sect, zend_gdbjit_initf initf)
430 {
431 ctx->startp = ctx->p;
432 ctx->obj.sect[sect].ofs = (uintptr_t)((char *)ctx->p - (char *)&ctx->obj);
433 initf(ctx);
434 ctx->obj.sect[sect].size = (uintptr_t)(ctx->p - ctx->startp);
435 }
436
zend_gdbjit_buildobj(zend_gdbjit_ctx * ctx)437 static void zend_gdbjit_buildobj(zend_gdbjit_ctx *ctx)
438 {
439 zend_gdbjit_obj *obj = &ctx->obj;
440
441 /* Fill in ELF header and clear structures. */
442 memcpy(&obj->hdr, &zend_elfhdr_template, sizeof(zend_elf_header));
443 memset(&obj->sect, 0, sizeof(zend_elf_sectheader) * GDBJIT_SECT__MAX);
444 memset(&obj->sym, 0, sizeof(zend_elf_symbol) * GDBJIT_SYM__MAX);
445
446 /* Initialize sections. */
447 ctx->p = obj->space;
448 zend_gdbjit_initsect(ctx, GDBJIT_SECT_shstrtab, zend_gdbjit_secthdr);
449 zend_gdbjit_initsect(ctx, GDBJIT_SECT_strtab, zend_gdbjit_symtab);
450 zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_info, zend_gdbjit_debuginfo);
451 zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_abbrev, zend_gdbjit_debugabbrev);
452 zend_gdbjit_initsect(ctx, GDBJIT_SECT_debug_line, zend_gdbjit_debugline);
453 SECTALIGN(ctx->p, sizeof(uintptr_t));
454 zend_gdbjit_initsect(ctx, GDBJIT_SECT_eh_frame, zend_gdbjit_ehframe);
455 ctx->objsize = (size_t)((char *)ctx->p - (char *)obj);
456
457 ZEND_ASSERT(ctx->objsize < sizeof(zend_gdbjit_obj));
458 }
459
zend_jit_gdb_register(const char * name,const zend_op_array * op_array,const void * start,size_t size)460 static int zend_jit_gdb_register(const char *name,
461 const zend_op_array *op_array,
462 const void *start,
463 size_t size)
464 {
465 zend_gdbjit_ctx ctx;
466
467 ctx.mcaddr = (uintptr_t)start;
468 ctx.szmcode = (uint32_t)size;
469 ctx.name = name;
470 ctx.filename = op_array ? ZSTR_VAL(op_array->filename) : "unknown";
471 ctx.lineno = op_array ? op_array->line_start : 0;
472
473 zend_gdbjit_buildobj(&ctx);
474
475 return zend_gdb_register_code(&ctx.obj, ctx.objsize);
476 }
477
zend_jit_gdb_unregister(void)478 static int zend_jit_gdb_unregister(void)
479 {
480 zend_gdb_unregister_all();
481 return 1;
482 }
483
zend_jit_gdb_init(void)484 static void zend_jit_gdb_init(void)
485 {
486 #if 0
487 /* This might enable registration of all JIT-ed code, but unfortunately,
488 * in case of many functions, this takes enormous time. */
489 if (zend_gdb_present()) {
490 JIT_G(debug) |= ZEND_JIT_DEBUG_GDB;
491 }
492 #endif
493 }
494
495 #endif
496