1 /* 2 * genelf.c 3 * Copyright (C) 2014, Google, Inc 4 * 5 * Contributed by: 6 * Stephane Eranian <eranian@gmail.com> 7 * 8 * Released under the GPL v2. (and only v2, not any later version) 9 */ 10 11 #include <sys/types.h> 12 #include <stdio.h> 13 #include <getopt.h> 14 #include <stddef.h> 15 #include <libelf.h> 16 #include <string.h> 17 #include <stdlib.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 30 #ifndef NT_GNU_BUILD_ID 31 #define NT_GNU_BUILD_ID 3 32 #endif 33 34 #define JVMTI 35 36 #define BUILD_ID_URANDOM /* different uuid for each run */ 37 38 #ifdef HAVE_LIBCRYPTO 39 40 #define BUILD_ID_MD5 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 */ 43 44 #ifdef BUILD_ID_SHA 45 #include <openssl/sha.h> 46 #endif 47 48 #ifdef BUILD_ID_MD5 49 #include <openssl/md5.h> 50 #endif 51 #endif 52 53 54 typedef struct { 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 */ 59 } Elf_Note; 60 61 struct options { 62 char *output; 63 int fd; 64 }; 65 66 static char shd_string_table[] = { 67 0, 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 */ 78 }; 79 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 */ 83 char build_id[20]; 84 } bnote; 85 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 */ 91 .st_value = 0x0, 92 .st_other = ELF_ST_VIS(STV_DEFAULT), 93 .st_size = 0, 94 }, 95 { .st_name = 1, /* index in sym_string table */ 96 .st_info = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC), 97 .st_shndx = 1, 98 .st_value = 0, /* for now */ 99 .st_other = ELF_ST_VIS(STV_DEFAULT), 100 .st_size = 0, /* for now */ 101 } 102 }; 103 104 #ifdef BUILD_ID_URANDOM 105 static void 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) 110 { 111 int fd; 112 size_t sz = sizeof(note->build_id); 113 ssize_t sret; 114 115 fd = open("/dev/urandom", O_RDONLY); 116 if (fd == -1) 117 err(1, "cannot access /dev/urandom for buildid"); 118 119 sret = read(fd, note->build_id, sz); 120 121 close(fd); 122 123 if (sret != (ssize_t)sz) 124 memset(note->build_id, 0, sz); 125 } 126 #endif 127 128 #ifdef BUILD_ID_SHA 129 static void 130 gen_build_id(struct buildid_note *note, 131 unsigned long load_addr __maybe_unused, 132 const void *code, 133 size_t csize) 134 { 135 if (sizeof(note->build_id) < SHA_DIGEST_LENGTH) 136 errx(1, "build_id too small for SHA1"); 137 138 SHA1(code, csize, (unsigned char *)note->build_id); 139 } 140 #endif 141 142 #ifdef BUILD_ID_MD5 143 static void 144 gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize) 145 { 146 MD5_CTX context; 147 148 if (sizeof(note->build_id) < 16) 149 errx(1, "build_id too small for MD5"); 150 151 MD5_Init(&context); 152 MD5_Update(&context, &load_addr, sizeof(load_addr)); 153 MD5_Update(&context, code, csize); 154 MD5_Final((unsigned char *)note->build_id, &context); 155 } 156 #endif 157 158 static int 159 jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size, 160 uint64_t unwinding_size, uint64_t base_offset) 161 { 162 Elf_Data *d; 163 Elf_Scn *scn; 164 Elf_Shdr *shdr; 165 uint64_t unwinding_table_size = unwinding_size - unwinding_header_size; 166 167 /* 168 * setup eh_frame section 169 */ 170 scn = elf_newscn(e); 171 if (!scn) { 172 warnx("cannot create section"); 173 return -1; 174 } 175 176 d = elf_newdata(scn); 177 if (!d) { 178 warnx("cannot get new data"); 179 return -1; 180 } 181 182 d->d_align = 8; 183 d->d_off = 0LL; 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; 188 189 shdr = elf_getshdr(scn); 190 if (!shdr) { 191 warnx("cannot get section header"); 192 return -1; 193 } 194 195 shdr->sh_name = 104; 196 shdr->sh_type = SHT_PROGBITS; 197 shdr->sh_addr = base_offset; 198 shdr->sh_flags = SHF_ALLOC; 199 shdr->sh_entsize = 0; 200 201 /* 202 * setup eh_frame_hdr section 203 */ 204 scn = elf_newscn(e); 205 if (!scn) { 206 warnx("cannot create section"); 207 return -1; 208 } 209 210 d = elf_newdata(scn); 211 if (!d) { 212 warnx("cannot get new data"); 213 return -1; 214 } 215 216 d->d_align = 4; 217 d->d_off = 0LL; 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; 222 223 shdr = elf_getshdr(scn); 224 if (!shdr) { 225 warnx("cannot get section header"); 226 return -1; 227 } 228 229 shdr->sh_name = 90; 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; 234 235 return 0; 236 } 237 238 /* 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 244 */ 245 int 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) 250 { 251 Elf *e; 252 Elf_Data *d; 253 Elf_Scn *scn; 254 Elf_Ehdr *ehdr; 255 Elf_Shdr *shdr; 256 uint64_t eh_frame_base_offset; 257 char *strsym = NULL; 258 int symlen; 259 int retval = -1; 260 261 if (elf_version(EV_CURRENT) == EV_NONE) { 262 warnx("ELF initialization failed"); 263 return -1; 264 } 265 266 e = elf_begin(fd, ELF_C_WRITE, NULL); 267 if (!e) { 268 warnx("elf_begin failed"); 269 goto error; 270 } 271 272 /* 273 * setup ELF header 274 */ 275 ehdr = elf_newehdr(e); 276 if (!ehdr) { 277 warnx("cannot get ehdr"); 278 goto error; 279 } 280 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 */ 288 289 /* 290 * setup text section 291 */ 292 scn = elf_newscn(e); 293 if (!scn) { 294 warnx("cannot create section"); 295 goto error; 296 } 297 298 d = elf_newdata(scn); 299 if (!d) { 300 warnx("cannot get new data"); 301 goto error; 302 } 303 304 d->d_align = 16; 305 d->d_off = 0LL; 306 d->d_buf = (void *)code; 307 d->d_type = ELF_T_BYTE; 308 d->d_size = csize; 309 d->d_version = EV_CURRENT; 310 311 shdr = elf_getshdr(scn); 312 if (!shdr) { 313 warnx("cannot get section header"); 314 goto error; 315 } 316 317 shdr->sh_name = 1; 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; 322 323 /* 324 * Setup .eh_frame_hdr and .eh_frame 325 */ 326 if (unwinding) { 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); 331 if (retval) 332 goto error; 333 } 334 335 /* 336 * setup section headers string table 337 */ 338 scn = elf_newscn(e); 339 if (!scn) { 340 warnx("cannot create section"); 341 goto error; 342 } 343 344 d = elf_newdata(scn); 345 if (!d) { 346 warnx("cannot get new data"); 347 goto error; 348 } 349 350 d->d_align = 1; 351 d->d_off = 0LL; 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; 356 357 shdr = elf_getshdr(scn); 358 if (!shdr) { 359 warnx("cannot get section header"); 360 goto error; 361 } 362 363 shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */ 364 shdr->sh_type = SHT_STRTAB; 365 shdr->sh_flags = 0; 366 shdr->sh_entsize = 0; 367 368 /* 369 * setup symtab section 370 */ 371 symtab[1].st_size = csize; 372 symtab[1].st_value = GEN_ELF_TEXT_OFFSET; 373 374 scn = elf_newscn(e); 375 if (!scn) { 376 warnx("cannot create section"); 377 goto error; 378 } 379 380 d = elf_newdata(scn); 381 if (!d) { 382 warnx("cannot get new data"); 383 goto error; 384 } 385 386 d->d_align = 8; 387 d->d_off = 0LL; 388 d->d_buf = symtab; 389 d->d_type = ELF_T_SYM; 390 d->d_size = sizeof(symtab); 391 d->d_version = EV_CURRENT; 392 393 shdr = elf_getshdr(scn); 394 if (!shdr) { 395 warnx("cannot get section header"); 396 goto error; 397 } 398 399 shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */ 400 shdr->sh_type = SHT_SYMTAB; 401 shdr->sh_flags = 0; 402 shdr->sh_entsize = sizeof(Elf_Sym); 403 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ 404 405 /* 406 * setup symbols string table 407 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry 408 */ 409 symlen = 2 + strlen(sym); 410 strsym = calloc(1, symlen); 411 if (!strsym) { 412 warnx("cannot allocate strsym"); 413 goto error; 414 } 415 strcpy(strsym + 1, sym); 416 417 scn = elf_newscn(e); 418 if (!scn) { 419 warnx("cannot create section"); 420 goto error; 421 } 422 423 d = elf_newdata(scn); 424 if (!d) { 425 warnx("cannot get new data"); 426 goto error; 427 } 428 429 d->d_align = 1; 430 d->d_off = 0LL; 431 d->d_buf = strsym; 432 d->d_type = ELF_T_BYTE; 433 d->d_size = symlen; 434 d->d_version = EV_CURRENT; 435 436 shdr = elf_getshdr(scn); 437 if (!shdr) { 438 warnx("cannot get section header"); 439 goto error; 440 } 441 442 shdr->sh_name = 25; /* offset in shd_string_table */ 443 shdr->sh_type = SHT_STRTAB; 444 shdr->sh_flags = 0; 445 shdr->sh_entsize = 0; 446 447 /* 448 * setup build-id section 449 */ 450 scn = elf_newscn(e); 451 if (!scn) { 452 warnx("cannot create section"); 453 goto error; 454 } 455 456 d = elf_newdata(scn); 457 if (!d) { 458 warnx("cannot get new data"); 459 goto error; 460 } 461 462 /* 463 * build-id generation 464 */ 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"); 470 471 d->d_align = 4; 472 d->d_off = 0LL; 473 d->d_buf = &bnote; 474 d->d_type = ELF_T_BYTE; 475 d->d_size = sizeof(bnote); 476 d->d_version = EV_CURRENT; 477 478 shdr = elf_getshdr(scn); 479 if (!shdr) { 480 warnx("cannot get section header"); 481 goto error; 482 } 483 484 shdr->sh_name = 33; /* offset in shd_string_table */ 485 shdr->sh_type = SHT_NOTE; 486 shdr->sh_addr = 0x0; 487 shdr->sh_flags = SHF_ALLOC; 488 shdr->sh_size = sizeof(bnote); 489 shdr->sh_entsize = 0; 490 491 #ifdef HAVE_DWARF_SUPPORT 492 if (debug && nr_debug_entries) { 493 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 494 if (retval) 495 goto error; 496 } else 497 #endif 498 { 499 if (elf_update(e, ELF_C_WRITE) < 0) { 500 warnx("elf_update 4 failed"); 501 goto error; 502 } 503 } 504 505 retval = 0; 506 error: 507 (void)elf_end(e); 508 509 free(strsym); 510 511 512 return retval; 513 } 514 515 #ifndef JVMTI 516 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 */ 521 }; 522 523 static struct options options; 524 525 int main(int argc, char **argv) 526 { 527 int c, fd, ret; 528 529 while ((c = getopt(argc, argv, "o:h")) != -1) { 530 switch (c) { 531 case 'o': 532 options.output = optarg; 533 break; 534 case 'h': 535 printf("Usage: genelf -o output_file [-h]\n"); 536 return 0; 537 default: 538 errx(1, "unknown option"); 539 } 540 } 541 542 fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666); 543 if (fd == -1) 544 err(1, "cannot create file %s", options.output); 545 546 ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code)); 547 close(fd); 548 549 if (ret != 0) 550 unlink(options.output); 551 552 return ret; 553 } 554 #endif 555