1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2014, Google, Inc
7 * Stephane Eranian <eranian@gmail.com>
10 #include <sys/types.h>
19 #ifdef HAVE_DWARF_SUPPORT
24 #include "../util/jitdump.h"
25 #include <linux/compiler.h>
27 #ifndef NT_GNU_BUILD_ID
28 #define NT_GNU_BUILD_ID 3
31 #define BUILD_ID_URANDOM /* different uuid for each run */
36 #undef BUILD_ID_SHA /* does not seem to work well when linked with Java */
37 #undef BUILD_ID_URANDOM /* different uuid for each run */
40 #include <openssl/sha.h>
44 #include <openssl/md5.h>
50 unsigned int namesz
; /* Size of entry's owner string */
51 unsigned int descsz
; /* Size of the note descriptor */
52 unsigned int type
; /* Interpretation of the descriptor */
53 char name
[0]; /* Start of the name+desc data */
61 static char shd_string_table
[] = {
63 '.', 't', 'e', 'x', 't', 0, /* 1 */
64 '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */
65 '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */
66 '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */
67 '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */
68 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
69 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
70 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
71 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */
72 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */
75 static struct buildid_note
{
76 Elf_Note desc
; /* descsz: size of build-id, must be multiple of 4 */
77 char name
[4]; /* GNU\0 */
81 static Elf_Sym symtab
[]={
82 /* symbol 0 MUST be the undefined symbol */
83 { .st_name
= 0, /* index in sym_string table */
84 .st_info
= ELF_ST_TYPE(STT_NOTYPE
),
85 .st_shndx
= 0, /* for now */
87 .st_other
= ELF_ST_VIS(STV_DEFAULT
),
90 { .st_name
= 1, /* index in sym_string table */
91 .st_info
= ELF_ST_BIND(STB_LOCAL
) | ELF_ST_TYPE(STT_FUNC
),
93 .st_value
= 0, /* for now */
94 .st_other
= ELF_ST_VIS(STV_DEFAULT
),
95 .st_size
= 0, /* for now */
99 #ifdef BUILD_ID_URANDOM
101 gen_build_id(struct buildid_note
*note
,
102 unsigned long load_addr __maybe_unused
,
103 const void *code __maybe_unused
,
104 size_t csize __maybe_unused
)
107 size_t sz
= sizeof(note
->build_id
);
110 fd
= open("/dev/urandom", O_RDONLY
);
112 err(1, "cannot access /dev/urandom for buildid");
114 sret
= read(fd
, note
->build_id
, sz
);
118 if (sret
!= (ssize_t
)sz
)
119 memset(note
->build_id
, 0, sz
);
125 gen_build_id(struct buildid_note
*note
,
126 unsigned long load_addr __maybe_unused
,
130 if (sizeof(note
->build_id
) < SHA_DIGEST_LENGTH
)
131 errx(1, "build_id too small for SHA1");
133 SHA1(code
, csize
, (unsigned char *)note
->build_id
);
139 gen_build_id(struct buildid_note
*note
, unsigned long load_addr
, const void *code
, size_t csize
)
143 if (sizeof(note
->build_id
) < 16)
144 errx(1, "build_id too small for MD5");
147 MD5_Update(&context
, &load_addr
, sizeof(load_addr
));
148 MD5_Update(&context
, code
, csize
);
149 MD5_Final((unsigned char *)note
->build_id
, &context
);
154 jit_add_eh_frame_info(Elf
*e
, void* unwinding
, uint64_t unwinding_header_size
,
155 uint64_t unwinding_size
, uint64_t base_offset
)
160 uint64_t unwinding_table_size
= unwinding_size
- unwinding_header_size
;
163 * setup eh_frame section
167 warnx("cannot create section");
171 d
= elf_newdata(scn
);
173 warnx("cannot get new data");
179 d
->d_buf
= unwinding
;
180 d
->d_type
= ELF_T_BYTE
;
181 d
->d_size
= unwinding_table_size
;
182 d
->d_version
= EV_CURRENT
;
184 shdr
= elf_getshdr(scn
);
186 warnx("cannot get section header");
191 shdr
->sh_type
= SHT_PROGBITS
;
192 shdr
->sh_addr
= base_offset
;
193 shdr
->sh_flags
= SHF_ALLOC
;
194 shdr
->sh_entsize
= 0;
197 * setup eh_frame_hdr section
201 warnx("cannot create section");
205 d
= elf_newdata(scn
);
207 warnx("cannot get new data");
213 d
->d_buf
= unwinding
+ unwinding_table_size
;
214 d
->d_type
= ELF_T_BYTE
;
215 d
->d_size
= unwinding_header_size
;
216 d
->d_version
= EV_CURRENT
;
218 shdr
= elf_getshdr(scn
);
220 warnx("cannot get section header");
225 shdr
->sh_type
= SHT_PROGBITS
;
226 shdr
->sh_addr
= base_offset
+ unwinding_table_size
;
227 shdr
->sh_flags
= SHF_ALLOC
;
228 shdr
->sh_entsize
= 0;
234 * fd: file descriptor open for writing for the output file
235 * load_addr: code load address (could be zero, just used for buildid)
236 * sym: function name (for native code - used as the symbol)
237 * code: the native code
238 * csize: the code size in bytes
241 jit_write_elf(int fd
, uint64_t load_addr
, const char *sym
,
242 const void *code
, int csize
,
243 void *debug __maybe_unused
, int nr_debug_entries __maybe_unused
,
244 void *unwinding
, uint64_t unwinding_header_size
, uint64_t unwinding_size
)
251 uint64_t eh_frame_base_offset
;
256 if (elf_version(EV_CURRENT
) == EV_NONE
) {
257 warnx("ELF initialization failed");
261 e
= elf_begin(fd
, ELF_C_WRITE
, NULL
);
263 warnx("elf_begin failed");
270 ehdr
= elf_newehdr(e
);
272 warnx("cannot get ehdr");
276 ehdr
->e_ident
[EI_DATA
] = GEN_ELF_ENDIAN
;
277 ehdr
->e_ident
[EI_CLASS
] = GEN_ELF_CLASS
;
278 ehdr
->e_machine
= GEN_ELF_ARCH
;
279 ehdr
->e_type
= ET_DYN
;
280 ehdr
->e_entry
= GEN_ELF_TEXT_OFFSET
;
281 ehdr
->e_version
= EV_CURRENT
;
282 ehdr
->e_shstrndx
= unwinding
? 4 : 2; /* shdr index for section name */
289 warnx("cannot create section");
293 d
= elf_newdata(scn
);
295 warnx("cannot get new data");
301 d
->d_buf
= (void *)code
;
302 d
->d_type
= ELF_T_BYTE
;
304 d
->d_version
= EV_CURRENT
;
306 shdr
= elf_getshdr(scn
);
308 warnx("cannot get section header");
313 shdr
->sh_type
= SHT_PROGBITS
;
314 shdr
->sh_addr
= GEN_ELF_TEXT_OFFSET
;
315 shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
316 shdr
->sh_entsize
= 0;
319 * Setup .eh_frame_hdr and .eh_frame
322 eh_frame_base_offset
= ALIGN_8(GEN_ELF_TEXT_OFFSET
+ csize
);
323 retval
= jit_add_eh_frame_info(e
, unwinding
,
324 unwinding_header_size
, unwinding_size
,
325 eh_frame_base_offset
);
331 * setup section headers string table
335 warnx("cannot create section");
339 d
= elf_newdata(scn
);
341 warnx("cannot get new data");
347 d
->d_buf
= shd_string_table
;
348 d
->d_type
= ELF_T_BYTE
;
349 d
->d_size
= sizeof(shd_string_table
);
350 d
->d_version
= EV_CURRENT
;
352 shdr
= elf_getshdr(scn
);
354 warnx("cannot get section header");
358 shdr
->sh_name
= 7; /* offset of '.shstrtab' in shd_string_table */
359 shdr
->sh_type
= SHT_STRTAB
;
361 shdr
->sh_entsize
= 0;
364 * setup symtab section
366 symtab
[1].st_size
= csize
;
367 symtab
[1].st_value
= GEN_ELF_TEXT_OFFSET
;
371 warnx("cannot create section");
375 d
= elf_newdata(scn
);
377 warnx("cannot get new data");
384 d
->d_type
= ELF_T_SYM
;
385 d
->d_size
= sizeof(symtab
);
386 d
->d_version
= EV_CURRENT
;
388 shdr
= elf_getshdr(scn
);
390 warnx("cannot get section header");
394 shdr
->sh_name
= 17; /* offset of '.symtab' in shd_string_table */
395 shdr
->sh_type
= SHT_SYMTAB
;
397 shdr
->sh_entsize
= sizeof(Elf_Sym
);
398 shdr
->sh_link
= unwinding
? 6 : 4; /* index of .strtab section */
401 * setup symbols string table
402 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry
404 symlen
= 2 + strlen(sym
);
405 strsym
= calloc(1, symlen
);
407 warnx("cannot allocate strsym");
410 strcpy(strsym
+ 1, sym
);
414 warnx("cannot create section");
418 d
= elf_newdata(scn
);
420 warnx("cannot get new data");
427 d
->d_type
= ELF_T_BYTE
;
429 d
->d_version
= EV_CURRENT
;
431 shdr
= elf_getshdr(scn
);
433 warnx("cannot get section header");
437 shdr
->sh_name
= 25; /* offset in shd_string_table */
438 shdr
->sh_type
= SHT_STRTAB
;
440 shdr
->sh_entsize
= 0;
443 * setup build-id section
447 warnx("cannot create section");
451 d
= elf_newdata(scn
);
453 warnx("cannot get new data");
458 * build-id generation
460 gen_build_id(&bnote
, load_addr
, code
, csize
);
461 bnote
.desc
.namesz
= sizeof(bnote
.name
); /* must include 0 termination */
462 bnote
.desc
.descsz
= sizeof(bnote
.build_id
);
463 bnote
.desc
.type
= NT_GNU_BUILD_ID
;
464 strcpy(bnote
.name
, "GNU");
469 d
->d_type
= ELF_T_BYTE
;
470 d
->d_size
= sizeof(bnote
);
471 d
->d_version
= EV_CURRENT
;
473 shdr
= elf_getshdr(scn
);
475 warnx("cannot get section header");
479 shdr
->sh_name
= 33; /* offset in shd_string_table */
480 shdr
->sh_type
= SHT_NOTE
;
482 shdr
->sh_flags
= SHF_ALLOC
;
483 shdr
->sh_size
= sizeof(bnote
);
484 shdr
->sh_entsize
= 0;
486 #ifdef HAVE_DWARF_SUPPORT
487 if (debug
&& nr_debug_entries
) {
488 retval
= jit_add_debug_info(e
, load_addr
, debug
, nr_debug_entries
);
494 if (elf_update(e
, ELF_C_WRITE
) < 0) {
495 warnx("elf_update 4 failed");