Coverage Report

Created: 2026-10-28 06:20

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