3 * Copyright (C) 2014, Google, Inc
6 * Stephane Eranian <eranian@gmail.com>
8 * Released under the GPL v2. (and only v2, not any later version)
11 #include <sys/types.h>
22 #ifdef HAVE_DWARF_SUPPORT
28 #include "../util/jitdump.h"
30 #ifndef NT_GNU_BUILD_ID
31 #define NT_GNU_BUILD_ID 3
36 #define BUILD_ID_URANDOM /* different uuid for each run */
41 #undef BUILD_ID_SHA /* does not seem to work well when linked with Java */
42 #undef BUILD_ID_URANDOM /* different uuid for each run */
45 #include <openssl/sha.h>
49 #include <openssl/md5.h>
55 unsigned int namesz
; /* Size of entry's owner string */
56 unsigned int descsz
; /* Size of the note descriptor */
57 unsigned int type
; /* Interpretation of the descriptor */
58 char name
[0]; /* Start of the name+desc data */
66 static char shd_string_table
[] = {
68 '.', 't', 'e', 'x', 't', 0, /* 1 */
69 '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */
70 '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */
71 '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */
72 '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */
73 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
74 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
75 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
76 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */
77 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */
80 static struct buildid_note
{
81 Elf_Note desc
; /* descsz: size of build-id, must be multiple of 4 */
82 char name
[4]; /* GNU\0 */
86 static Elf_Sym symtab
[]={
87 /* symbol 0 MUST be the undefined symbol */
88 { .st_name
= 0, /* index in sym_string table */
89 .st_info
= ELF_ST_TYPE(STT_NOTYPE
),
90 .st_shndx
= 0, /* for now */
92 .st_other
= ELF_ST_VIS(STV_DEFAULT
),
95 { .st_name
= 1, /* index in sym_string table */
96 .st_info
= ELF_ST_BIND(STB_LOCAL
) | ELF_ST_TYPE(STT_FUNC
),
98 .st_value
= 0, /* for now */
99 .st_other
= ELF_ST_VIS(STV_DEFAULT
),
100 .st_size
= 0, /* for now */
104 #ifdef BUILD_ID_URANDOM
106 gen_build_id(struct buildid_note
*note
,
107 unsigned long load_addr __maybe_unused
,
108 const void *code __maybe_unused
,
109 size_t csize __maybe_unused
)
112 size_t sz
= sizeof(note
->build_id
);
115 fd
= open("/dev/urandom", O_RDONLY
);
117 err(1, "cannot access /dev/urandom for builid");
119 sret
= read(fd
, note
->build_id
, sz
);
123 if (sret
!= (ssize_t
)sz
)
124 memset(note
->build_id
, 0, sz
);
130 gen_build_id(struct buildid_note
*note
,
131 unsigned long load_addr __maybe_unused
,
135 if (sizeof(note
->build_id
) < SHA_DIGEST_LENGTH
)
136 errx(1, "build_id too small for SHA1");
138 SHA1(code
, csize
, (unsigned char *)note
->build_id
);
144 gen_build_id(struct buildid_note
*note
, unsigned long load_addr
, const void *code
, size_t csize
)
148 if (sizeof(note
->build_id
) < 16)
149 errx(1, "build_id too small for MD5");
152 MD5_Update(&context
, &load_addr
, sizeof(load_addr
));
153 MD5_Update(&context
, code
, csize
);
154 MD5_Final((unsigned char *)note
->build_id
, &context
);
159 jit_add_eh_frame_info(Elf
*e
, void* unwinding
, uint64_t unwinding_header_size
,
160 uint64_t unwinding_size
, uint64_t base_offset
)
165 uint64_t unwinding_table_size
= unwinding_size
- unwinding_header_size
;
168 * setup eh_frame section
172 warnx("cannot create section");
176 d
= elf_newdata(scn
);
178 warnx("cannot get new data");
184 d
->d_buf
= unwinding
;
185 d
->d_type
= ELF_T_BYTE
;
186 d
->d_size
= unwinding_table_size
;
187 d
->d_version
= EV_CURRENT
;
189 shdr
= elf_getshdr(scn
);
191 warnx("cannot get section header");
196 shdr
->sh_type
= SHT_PROGBITS
;
197 shdr
->sh_addr
= base_offset
;
198 shdr
->sh_flags
= SHF_ALLOC
;
199 shdr
->sh_entsize
= 0;
202 * setup eh_frame_hdr section
206 warnx("cannot create section");
210 d
= elf_newdata(scn
);
212 warnx("cannot get new data");
218 d
->d_buf
= unwinding
+ unwinding_table_size
;
219 d
->d_type
= ELF_T_BYTE
;
220 d
->d_size
= unwinding_header_size
;
221 d
->d_version
= EV_CURRENT
;
223 shdr
= elf_getshdr(scn
);
225 warnx("cannot get section header");
230 shdr
->sh_type
= SHT_PROGBITS
;
231 shdr
->sh_addr
= base_offset
+ unwinding_table_size
;
232 shdr
->sh_flags
= SHF_ALLOC
;
233 shdr
->sh_entsize
= 0;
239 * fd: file descriptor open for writing for the output file
240 * load_addr: code load address (could be zero, just used for buildid)
241 * sym: function name (for native code - used as the symbol)
242 * code: the native code
243 * csize: the code size in bytes
246 jit_write_elf(int fd
, uint64_t load_addr
, const char *sym
,
247 const void *code
, int csize
,
248 void *debug __maybe_unused
, int nr_debug_entries __maybe_unused
,
249 void *unwinding
, uint64_t unwinding_header_size
, uint64_t unwinding_size
)
256 uint64_t eh_frame_base_offset
;
261 if (elf_version(EV_CURRENT
) == EV_NONE
) {
262 warnx("ELF initialization failed");
266 e
= elf_begin(fd
, ELF_C_WRITE
, NULL
);
268 warnx("elf_begin failed");
275 ehdr
= elf_newehdr(e
);
277 warnx("cannot get ehdr");
281 ehdr
->e_ident
[EI_DATA
] = GEN_ELF_ENDIAN
;
282 ehdr
->e_ident
[EI_CLASS
] = GEN_ELF_CLASS
;
283 ehdr
->e_machine
= GEN_ELF_ARCH
;
284 ehdr
->e_type
= ET_DYN
;
285 ehdr
->e_entry
= GEN_ELF_TEXT_OFFSET
;
286 ehdr
->e_version
= EV_CURRENT
;
287 ehdr
->e_shstrndx
= unwinding
? 4 : 2; /* shdr index for section name */
294 warnx("cannot create section");
298 d
= elf_newdata(scn
);
300 warnx("cannot get new data");
306 d
->d_buf
= (void *)code
;
307 d
->d_type
= ELF_T_BYTE
;
309 d
->d_version
= EV_CURRENT
;
311 shdr
= elf_getshdr(scn
);
313 warnx("cannot get section header");
318 shdr
->sh_type
= SHT_PROGBITS
;
319 shdr
->sh_addr
= GEN_ELF_TEXT_OFFSET
;
320 shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
321 shdr
->sh_entsize
= 0;
324 * Setup .eh_frame_hdr and .eh_frame
327 eh_frame_base_offset
= ALIGN_8(GEN_ELF_TEXT_OFFSET
+ csize
);
328 retval
= jit_add_eh_frame_info(e
, unwinding
,
329 unwinding_header_size
, unwinding_size
,
330 eh_frame_base_offset
);
336 * setup section headers string table
340 warnx("cannot create section");
344 d
= elf_newdata(scn
);
346 warnx("cannot get new data");
352 d
->d_buf
= shd_string_table
;
353 d
->d_type
= ELF_T_BYTE
;
354 d
->d_size
= sizeof(shd_string_table
);
355 d
->d_version
= EV_CURRENT
;
357 shdr
= elf_getshdr(scn
);
359 warnx("cannot get section header");
363 shdr
->sh_name
= 7; /* offset of '.shstrtab' in shd_string_table */
364 shdr
->sh_type
= SHT_STRTAB
;
366 shdr
->sh_entsize
= 0;
369 * setup symtab section
371 symtab
[1].st_size
= csize
;
372 symtab
[1].st_value
= GEN_ELF_TEXT_OFFSET
;
376 warnx("cannot create section");
380 d
= elf_newdata(scn
);
382 warnx("cannot get new data");
389 d
->d_type
= ELF_T_SYM
;
390 d
->d_size
= sizeof(symtab
);
391 d
->d_version
= EV_CURRENT
;
393 shdr
= elf_getshdr(scn
);
395 warnx("cannot get section header");
399 shdr
->sh_name
= 17; /* offset of '.symtab' in shd_string_table */
400 shdr
->sh_type
= SHT_SYMTAB
;
402 shdr
->sh_entsize
= sizeof(Elf_Sym
);
403 shdr
->sh_link
= unwinding
? 6 : 4; /* index of .strtab section */
406 * setup symbols string table
407 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry
409 symlen
= 2 + strlen(sym
);
410 strsym
= calloc(1, symlen
);
412 warnx("cannot allocate strsym");
415 strcpy(strsym
+ 1, sym
);
419 warnx("cannot create section");
423 d
= elf_newdata(scn
);
425 warnx("cannot get new data");
432 d
->d_type
= ELF_T_BYTE
;
434 d
->d_version
= EV_CURRENT
;
436 shdr
= elf_getshdr(scn
);
438 warnx("cannot get section header");
442 shdr
->sh_name
= 25; /* offset in shd_string_table */
443 shdr
->sh_type
= SHT_STRTAB
;
445 shdr
->sh_entsize
= 0;
448 * setup build-id section
452 warnx("cannot create section");
456 d
= elf_newdata(scn
);
458 warnx("cannot get new data");
463 * build-id generation
465 gen_build_id(&bnote
, load_addr
, code
, csize
);
466 bnote
.desc
.namesz
= sizeof(bnote
.name
); /* must include 0 termination */
467 bnote
.desc
.descsz
= sizeof(bnote
.build_id
);
468 bnote
.desc
.type
= NT_GNU_BUILD_ID
;
469 strcpy(bnote
.name
, "GNU");
474 d
->d_type
= ELF_T_BYTE
;
475 d
->d_size
= sizeof(bnote
);
476 d
->d_version
= EV_CURRENT
;
478 shdr
= elf_getshdr(scn
);
480 warnx("cannot get section header");
484 shdr
->sh_name
= 33; /* offset in shd_string_table */
485 shdr
->sh_type
= SHT_NOTE
;
487 shdr
->sh_flags
= SHF_ALLOC
;
488 shdr
->sh_size
= sizeof(bnote
);
489 shdr
->sh_entsize
= 0;
491 #ifdef HAVE_DWARF_SUPPORT
492 if (debug
&& nr_debug_entries
) {
493 retval
= jit_add_debug_info(e
, load_addr
, debug
, nr_debug_entries
);
499 if (elf_update(e
, ELF_C_WRITE
) < 0) {
500 warnx("elf_update 4 failed");
517 static unsigned char x86_code
[] = {
518 0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
519 0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
520 0xCD, 0x80 /* int $0x80 */
523 static struct options options
;
525 int main(int argc
, char **argv
)
529 while ((c
= getopt(argc
, argv
, "o:h")) != -1) {
532 options
.output
= optarg
;
535 printf("Usage: genelf -o output_file [-h]\n");
538 errx(1, "unknown option");
542 fd
= open(options
.output
, O_CREAT
|O_TRUNC
|O_RDWR
, 0666);
544 err(1, "cannot create file %s", options
.output
);
546 ret
= jit_write_elf(fd
, "main", x86_code
, sizeof(x86_code
));
550 unlink(options
.output
);