1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * genelf.c 4 * Copyright (C) 2014, Google, Inc 5 * 6 * Contributed by: 7 * Stephane Eranian <eranian@gmail.com> 8 */ 9 10 #include <sys/types.h> 11 #include <stddef.h> 12 #include <libelf.h> 13 #include <string.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 #include <inttypes.h> 17 #include <fcntl.h> 18 #include <err.h> 19 #ifdef HAVE_DWARF_SUPPORT 20 #include <dwarf.h> 21 #endif 22 23 #include "genelf.h" 24 #include "../util/jitdump.h" 25 #include <linux/compiler.h> 26 27 #ifndef NT_GNU_BUILD_ID 28 #define NT_GNU_BUILD_ID 3 29 #endif 30 31 #define BUILD_ID_URANDOM /* different uuid for each run */ 32 33 #ifdef HAVE_LIBCRYPTO_SUPPORT 34 35 #define BUILD_ID_MD5 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 */ 38 39 #ifdef BUILD_ID_SHA 40 #include <openssl/sha.h> 41 #endif 42 43 #ifdef BUILD_ID_MD5 44 #include <openssl/evp.h> 45 #include <openssl/md5.h> 46 #endif 47 #endif 48 49 50 typedef struct { 51 unsigned int namesz; /* Size of entry's owner string */ 52 unsigned int descsz; /* Size of the note descriptor */ 53 unsigned int type; /* Interpretation of the descriptor */ 54 char name[0]; /* Start of the name+desc data */ 55 } Elf_Note; 56 57 static char shd_string_table[] = { 58 0, 59 '.', 't', 'e', 'x', 't', 0, /* 1 */ 60 '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */ 61 '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */ 62 '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */ 63 '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */ 64 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ 65 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ 66 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ 67 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */ 68 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */ 69 }; 70 71 static struct buildid_note { 72 Elf_Note desc; /* descsz: size of build-id, must be multiple of 4 */ 73 char name[4]; /* GNU\0 */ 74 char build_id[20]; 75 } bnote; 76 77 static Elf_Sym symtab[]={ 78 /* symbol 0 MUST be the undefined symbol */ 79 { .st_name = 0, /* index in sym_string table */ 80 .st_info = ELF_ST_TYPE(STT_NOTYPE), 81 .st_shndx = 0, /* for now */ 82 .st_value = 0x0, 83 .st_other = ELF_ST_VIS(STV_DEFAULT), 84 .st_size = 0, 85 }, 86 { .st_name = 1, /* index in sym_string table */ 87 .st_info = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC), 88 .st_shndx = 1, 89 .st_value = 0, /* for now */ 90 .st_other = ELF_ST_VIS(STV_DEFAULT), 91 .st_size = 0, /* for now */ 92 } 93 }; 94 95 #ifdef BUILD_ID_URANDOM 96 static void 97 gen_build_id(struct buildid_note *note, 98 unsigned long load_addr __maybe_unused, 99 const void *code __maybe_unused, 100 size_t csize __maybe_unused) 101 { 102 int fd; 103 size_t sz = sizeof(note->build_id); 104 ssize_t sret; 105 106 fd = open("/dev/urandom", O_RDONLY); 107 if (fd == -1) 108 err(1, "cannot access /dev/urandom for buildid"); 109 110 sret = read(fd, note->build_id, sz); 111 112 close(fd); 113 114 if (sret != (ssize_t)sz) 115 memset(note->build_id, 0, sz); 116 } 117 #endif 118 119 #ifdef BUILD_ID_SHA 120 static void 121 gen_build_id(struct buildid_note *note, 122 unsigned long load_addr __maybe_unused, 123 const void *code, 124 size_t csize) 125 { 126 if (sizeof(note->build_id) < SHA_DIGEST_LENGTH) 127 errx(1, "build_id too small for SHA1"); 128 129 SHA1(code, csize, (unsigned char *)note->build_id); 130 } 131 #endif 132 133 #ifdef BUILD_ID_MD5 134 static void 135 gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize) 136 { 137 EVP_MD_CTX *mdctx; 138 139 if (sizeof(note->build_id) < 16) 140 errx(1, "build_id too small for MD5"); 141 142 mdctx = EVP_MD_CTX_new(); 143 if (!mdctx) 144 errx(2, "failed to create EVP_MD_CTX"); 145 146 EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); 147 EVP_DigestUpdate(mdctx, &load_addr, sizeof(load_addr)); 148 EVP_DigestUpdate(mdctx, code, csize); 149 EVP_DigestFinal_ex(mdctx, (unsigned char *)note->build_id, NULL); 150 EVP_MD_CTX_free(mdctx); 151 } 152 #endif 153 154 static int 155 jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size, 156 uint64_t unwinding_size, uint64_t base_offset) 157 { 158 Elf_Data *d; 159 Elf_Scn *scn; 160 Elf_Shdr *shdr; 161 uint64_t unwinding_table_size = unwinding_size - unwinding_header_size; 162 163 /* 164 * setup eh_frame section 165 */ 166 scn = elf_newscn(e); 167 if (!scn) { 168 warnx("cannot create section"); 169 return -1; 170 } 171 172 d = elf_newdata(scn); 173 if (!d) { 174 warnx("cannot get new data"); 175 return -1; 176 } 177 178 d->d_align = 8; 179 d->d_off = 0LL; 180 d->d_buf = unwinding; 181 d->d_type = ELF_T_BYTE; 182 d->d_size = unwinding_table_size; 183 d->d_version = EV_CURRENT; 184 185 shdr = elf_getshdr(scn); 186 if (!shdr) { 187 warnx("cannot get section header"); 188 return -1; 189 } 190 191 shdr->sh_name = 104; 192 shdr->sh_type = SHT_PROGBITS; 193 shdr->sh_addr = base_offset; 194 shdr->sh_flags = SHF_ALLOC; 195 shdr->sh_entsize = 0; 196 197 /* 198 * setup eh_frame_hdr section 199 */ 200 scn = elf_newscn(e); 201 if (!scn) { 202 warnx("cannot create section"); 203 return -1; 204 } 205 206 d = elf_newdata(scn); 207 if (!d) { 208 warnx("cannot get new data"); 209 return -1; 210 } 211 212 d->d_align = 4; 213 d->d_off = 0LL; 214 d->d_buf = unwinding + unwinding_table_size; 215 d->d_type = ELF_T_BYTE; 216 d->d_size = unwinding_header_size; 217 d->d_version = EV_CURRENT; 218 219 shdr = elf_getshdr(scn); 220 if (!shdr) { 221 warnx("cannot get section header"); 222 return -1; 223 } 224 225 shdr->sh_name = 90; 226 shdr->sh_type = SHT_PROGBITS; 227 shdr->sh_addr = base_offset + unwinding_table_size; 228 shdr->sh_flags = SHF_ALLOC; 229 shdr->sh_entsize = 0; 230 231 return 0; 232 } 233 234 /* 235 * fd: file descriptor open for writing for the output file 236 * load_addr: code load address (could be zero, just used for buildid) 237 * sym: function name (for native code - used as the symbol) 238 * code: the native code 239 * csize: the code size in bytes 240 */ 241 int 242 jit_write_elf(int fd, uint64_t load_addr, const char *sym, 243 const void *code, int csize, 244 void *debug __maybe_unused, int nr_debug_entries __maybe_unused, 245 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size) 246 { 247 Elf *e; 248 Elf_Data *d; 249 Elf_Scn *scn; 250 Elf_Ehdr *ehdr; 251 Elf_Phdr *phdr; 252 Elf_Shdr *shdr; 253 uint64_t eh_frame_base_offset; 254 char *strsym = NULL; 255 int symlen; 256 int retval = -1; 257 258 if (elf_version(EV_CURRENT) == EV_NONE) { 259 warnx("ELF initialization failed"); 260 return -1; 261 } 262 263 e = elf_begin(fd, ELF_C_WRITE, NULL); 264 if (!e) { 265 warnx("elf_begin failed"); 266 goto error; 267 } 268 269 /* 270 * setup ELF header 271 */ 272 ehdr = elf_newehdr(e); 273 if (!ehdr) { 274 warnx("cannot get ehdr"); 275 goto error; 276 } 277 278 ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN; 279 ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS; 280 ehdr->e_machine = GEN_ELF_ARCH; 281 ehdr->e_type = ET_DYN; 282 ehdr->e_entry = GEN_ELF_TEXT_OFFSET; 283 ehdr->e_version = EV_CURRENT; 284 ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */ 285 286 /* 287 * setup program header 288 */ 289 phdr = elf_newphdr(e, 1); 290 phdr[0].p_type = PT_LOAD; 291 phdr[0].p_offset = GEN_ELF_TEXT_OFFSET; 292 phdr[0].p_vaddr = GEN_ELF_TEXT_OFFSET; 293 phdr[0].p_paddr = GEN_ELF_TEXT_OFFSET; 294 phdr[0].p_filesz = csize; 295 phdr[0].p_memsz = csize; 296 phdr[0].p_flags = PF_X | PF_R; 297 phdr[0].p_align = 8; 298 299 /* 300 * setup text section 301 */ 302 scn = elf_newscn(e); 303 if (!scn) { 304 warnx("cannot create section"); 305 goto error; 306 } 307 308 d = elf_newdata(scn); 309 if (!d) { 310 warnx("cannot get new data"); 311 goto error; 312 } 313 314 d->d_align = 16; 315 d->d_off = 0LL; 316 d->d_buf = (void *)code; 317 d->d_type = ELF_T_BYTE; 318 d->d_size = csize; 319 d->d_version = EV_CURRENT; 320 321 shdr = elf_getshdr(scn); 322 if (!shdr) { 323 warnx("cannot get section header"); 324 goto error; 325 } 326 327 shdr->sh_name = 1; 328 shdr->sh_type = SHT_PROGBITS; 329 shdr->sh_addr = GEN_ELF_TEXT_OFFSET; 330 shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 331 shdr->sh_entsize = 0; 332 333 /* 334 * Setup .eh_frame_hdr and .eh_frame 335 */ 336 if (unwinding) { 337 eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize); 338 retval = jit_add_eh_frame_info(e, unwinding, 339 unwinding_header_size, unwinding_size, 340 eh_frame_base_offset); 341 if (retval) 342 goto error; 343 retval = -1; 344 } 345 346 /* 347 * setup section headers string table 348 */ 349 scn = elf_newscn(e); 350 if (!scn) { 351 warnx("cannot create section"); 352 goto error; 353 } 354 355 d = elf_newdata(scn); 356 if (!d) { 357 warnx("cannot get new data"); 358 goto error; 359 } 360 361 d->d_align = 1; 362 d->d_off = 0LL; 363 d->d_buf = shd_string_table; 364 d->d_type = ELF_T_BYTE; 365 d->d_size = sizeof(shd_string_table); 366 d->d_version = EV_CURRENT; 367 368 shdr = elf_getshdr(scn); 369 if (!shdr) { 370 warnx("cannot get section header"); 371 goto error; 372 } 373 374 shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */ 375 shdr->sh_type = SHT_STRTAB; 376 shdr->sh_flags = 0; 377 shdr->sh_entsize = 0; 378 379 /* 380 * setup symtab section 381 */ 382 symtab[1].st_size = csize; 383 symtab[1].st_value = GEN_ELF_TEXT_OFFSET; 384 385 scn = elf_newscn(e); 386 if (!scn) { 387 warnx("cannot create section"); 388 goto error; 389 } 390 391 d = elf_newdata(scn); 392 if (!d) { 393 warnx("cannot get new data"); 394 goto error; 395 } 396 397 d->d_align = 8; 398 d->d_off = 0LL; 399 d->d_buf = symtab; 400 d->d_type = ELF_T_SYM; 401 d->d_size = sizeof(symtab); 402 d->d_version = EV_CURRENT; 403 404 shdr = elf_getshdr(scn); 405 if (!shdr) { 406 warnx("cannot get section header"); 407 goto error; 408 } 409 410 shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */ 411 shdr->sh_type = SHT_SYMTAB; 412 shdr->sh_flags = 0; 413 shdr->sh_entsize = sizeof(Elf_Sym); 414 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ 415 416 /* 417 * setup symbols string table 418 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry 419 */ 420 symlen = 2 + strlen(sym); 421 strsym = calloc(1, symlen); 422 if (!strsym) { 423 warnx("cannot allocate strsym"); 424 goto error; 425 } 426 strcpy(strsym + 1, sym); 427 428 scn = elf_newscn(e); 429 if (!scn) { 430 warnx("cannot create section"); 431 goto error; 432 } 433 434 d = elf_newdata(scn); 435 if (!d) { 436 warnx("cannot get new data"); 437 goto error; 438 } 439 440 d->d_align = 1; 441 d->d_off = 0LL; 442 d->d_buf = strsym; 443 d->d_type = ELF_T_BYTE; 444 d->d_size = symlen; 445 d->d_version = EV_CURRENT; 446 447 shdr = elf_getshdr(scn); 448 if (!shdr) { 449 warnx("cannot get section header"); 450 goto error; 451 } 452 453 shdr->sh_name = 25; /* offset in shd_string_table */ 454 shdr->sh_type = SHT_STRTAB; 455 shdr->sh_flags = 0; 456 shdr->sh_entsize = 0; 457 458 /* 459 * setup build-id section 460 */ 461 scn = elf_newscn(e); 462 if (!scn) { 463 warnx("cannot create section"); 464 goto error; 465 } 466 467 d = elf_newdata(scn); 468 if (!d) { 469 warnx("cannot get new data"); 470 goto error; 471 } 472 473 /* 474 * build-id generation 475 */ 476 gen_build_id(&bnote, load_addr, code, csize); 477 bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ 478 bnote.desc.descsz = sizeof(bnote.build_id); 479 bnote.desc.type = NT_GNU_BUILD_ID; 480 strcpy(bnote.name, "GNU"); 481 482 d->d_align = 4; 483 d->d_off = 0LL; 484 d->d_buf = &bnote; 485 d->d_type = ELF_T_BYTE; 486 d->d_size = sizeof(bnote); 487 d->d_version = EV_CURRENT; 488 489 shdr = elf_getshdr(scn); 490 if (!shdr) { 491 warnx("cannot get section header"); 492 goto error; 493 } 494 495 shdr->sh_name = 33; /* offset in shd_string_table */ 496 shdr->sh_type = SHT_NOTE; 497 shdr->sh_addr = 0x0; 498 shdr->sh_flags = SHF_ALLOC; 499 shdr->sh_size = sizeof(bnote); 500 shdr->sh_entsize = 0; 501 502 #ifdef HAVE_DWARF_SUPPORT 503 if (debug && nr_debug_entries) { 504 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 505 if (retval) 506 goto error; 507 } else 508 #endif 509 { 510 if (elf_update(e, ELF_C_WRITE) < 0) { 511 warnx("elf_update 4 failed"); 512 goto error; 513 } 514 } 515 516 retval = 0; 517 error: 518 (void)elf_end(e); 519 520 free(strsym); 521 522 523 return retval; 524 } 525
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.