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 <stdio.h> 12 #include <getopt.h> 13 #include <stddef.h> 14 #include <libelf.h> 15 #include <string.h> 16 #include <stdlib.h> 17 #include <unistd.h> 18 #include <inttypes.h> 19 #include <limits.h> 20 #include <fcntl.h> 21 #include <err.h> 22 #ifdef HAVE_DWARF_SUPPORT 23 #include <dwarf.h> 24 #endif 25 26 #include "perf.h" 27 #include "genelf.h" 28 #include "../util/jitdump.h" 29 #include <linux/compiler.h> 30 31 #ifndef NT_GNU_BUILD_ID 32 #define NT_GNU_BUILD_ID 3 33 #endif 34 35 #define JVMTI 36 37 #define BUILD_ID_URANDOM /* different uuid for each run */ 38 39 #ifdef HAVE_LIBCRYPTO 40 41 #define BUILD_ID_MD5 42 #undef BUILD_ID_SHA /* does not seem to work well when linked with Java */ 43 #undef BUILD_ID_URANDOM /* different uuid for each run */ 44 45 #ifdef BUILD_ID_SHA 46 #include <openssl/sha.h> 47 #endif 48 49 #ifdef BUILD_ID_MD5 50 #include <openssl/md5.h> 51 #endif 52 #endif 53 54 55 typedef struct { 56 unsigned int namesz; /* Size of entry's owner string */ 57 unsigned int descsz; /* Size of the note descriptor */ 58 unsigned int type; /* Interpretation of the descriptor */ 59 char name[0]; /* Start of the name+desc data */ 60 } Elf_Note; 61 62 struct options { 63 char *output; 64 int fd; 65 }; 66 67 static char shd_string_table[] = { 68 0, 69 '.', 't', 'e', 'x', 't', 0, /* 1 */ 70 '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */ 71 '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */ 72 '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */ 73 '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */ 74 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ 75 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ 76 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ 77 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */ 78 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */ 79 }; 80 81 static struct buildid_note { 82 Elf_Note desc; /* descsz: size of build-id, must be multiple of 4 */ 83 char name[4]; /* GNU\0 */ 84 char build_id[20]; 85 } bnote; 86 87 static Elf_Sym symtab[]={ 88 /* symbol 0 MUST be the undefined symbol */ 89 { .st_name = 0, /* index in sym_string table */ 90 .st_info = ELF_ST_TYPE(STT_NOTYPE), 91 .st_shndx = 0, /* for now */ 92 .st_value = 0x0, 93 .st_other = ELF_ST_VIS(STV_DEFAULT), 94 .st_size = 0, 95 }, 96 { .st_name = 1, /* index in sym_string table */ 97 .st_info = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC), 98 .st_shndx = 1, 99 .st_value = 0, /* for now */ 100 .st_other = ELF_ST_VIS(STV_DEFAULT), 101 .st_size = 0, /* for now */ 102 } 103 }; 104 105 #ifdef BUILD_ID_URANDOM 106 static void 107 gen_build_id(struct buildid_note *note, 108 unsigned long load_addr __maybe_unused, 109 const void *code __maybe_unused, 110 size_t csize __maybe_unused) 111 { 112 int fd; 113 size_t sz = sizeof(note->build_id); 114 ssize_t sret; 115 116 fd = open("/dev/urandom", O_RDONLY); 117 if (fd == -1) 118 err(1, "cannot access /dev/urandom for buildid"); 119 120 sret = read(fd, note->build_id, sz); 121 122 close(fd); 123 124 if (sret != (ssize_t)sz) 125 memset(note->build_id, 0, sz); 126 } 127 #endif 128 129 #ifdef BUILD_ID_SHA 130 static void 131 gen_build_id(struct buildid_note *note, 132 unsigned long load_addr __maybe_unused, 133 const void *code, 134 size_t csize) 135 { 136 if (sizeof(note->build_id) < SHA_DIGEST_LENGTH) 137 errx(1, "build_id too small for SHA1"); 138 139 SHA1(code, csize, (unsigned char *)note->build_id); 140 } 141 #endif 142 143 #ifdef BUILD_ID_MD5 144 static void 145 gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize) 146 { 147 MD5_CTX context; 148 149 if (sizeof(note->build_id) < 16) 150 errx(1, "build_id too small for MD5"); 151 152 MD5_Init(&context); 153 MD5_Update(&context, &load_addr, sizeof(load_addr)); 154 MD5_Update(&context, code, csize); 155 MD5_Final((unsigned char *)note->build_id, &context); 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 516 #ifndef JVMTI 517 518 static unsigned char x86_code[] = { 519 0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */ 520 0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */ 521 0xCD, 0x80 /* int $0x80 */ 522 }; 523 524 static struct options options; 525 526 int main(int argc, char **argv) 527 { 528 int c, fd, ret; 529 530 while ((c = getopt(argc, argv, "o:h")) != -1) { 531 switch (c) { 532 case 'o': 533 options.output = optarg; 534 break; 535 case 'h': 536 printf("Usage: genelf -o output_file [-h]\n"); 537 return 0; 538 default: 539 errx(1, "unknown option"); 540 } 541 } 542 543 fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666); 544 if (fd == -1) 545 err(1, "cannot create file %s", options.output); 546 547 ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code)); 548 close(fd); 549 550 if (ret != 0) 551 unlink(options.output); 552 553 return ret; 554 } 555 #endif 556