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