ltrace-elf.c revision 747c73d5b7d66d312a1b1a293e67f9ddf2f17d93
1# include "config.h" 2 3#include <endian.h> 4#include <errno.h> 5#include <error.h> 6#include <fcntl.h> 7#include <gelf.h> 8#include <stdint.h> 9#include <stdlib.h> 10#include <string.h> 11#include <unistd.h> 12 13#include "common.h" 14 15static void do_init_elf(struct ltelf *lte, const char *filename); 16static void do_close_elf(struct ltelf *lte); 17static void add_library_symbol(GElf_Addr addr, const char *name, 18 struct library_symbol **library_symbolspp, 19 enum toplt type_of_plt, int is_weak); 20static int in_load_libraries(const char *name, struct ltelf *lte); 21static GElf_Addr opd2addr(struct ltelf *ltc, GElf_Addr addr); 22 23#ifdef PLT_REINITALISATION_BP 24extern char *PLTs_initialized_by_here; 25#endif 26 27static void 28do_init_elf(struct ltelf *lte, const char *filename) { 29 int i; 30 GElf_Addr relplt_addr = 0; 31 size_t relplt_size = 0; 32 33 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); 34 debug(1, "Reading ELF from %s...", filename); 35 36 memset(lte, 0, sizeof(*lte)); 37 lte->fd = open(filename, O_RDONLY); 38 if (lte->fd == -1) 39 error(EXIT_FAILURE, errno, "Can't open \"%s\"", filename); 40 41#ifdef HAVE_ELF_C_READ_MMAP 42 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL); 43#else 44 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL); 45#endif 46 47 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) 48 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename); 49 50 if (gelf_getehdr(lte->elf, <e->ehdr) == NULL) 51 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", 52 filename); 53 54 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) 55 error(EXIT_FAILURE, 0, 56 "\"%s\" is not an ELF executable nor shared library", 57 filename); 58 59 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS 60 || lte->ehdr.e_machine != LT_ELF_MACHINE) 61#ifdef LT_ELF_MACHINE2 62 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2 63 || lte->ehdr.e_machine != LT_ELF_MACHINE2) 64#endif 65#ifdef LT_ELF_MACHINE3 66 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3 67 || lte->ehdr.e_machine != LT_ELF_MACHINE3) 68#endif 69 ) 70 error(EXIT_FAILURE, 0, 71 "\"%s\" is ELF from incompatible architecture", filename); 72 73 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 74 Elf_Scn *scn; 75 GElf_Shdr shdr; 76 const char *name; 77 78 scn = elf_getscn(lte->elf, i); 79 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 80 error(EXIT_FAILURE, 0, 81 "Couldn't get section header from \"%s\"", 82 filename); 83 84 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name); 85 if (name == NULL) 86 error(EXIT_FAILURE, 0, 87 "Couldn't get section header from \"%s\"", 88 filename); 89 90 if (shdr.sh_type == SHT_SYMTAB) { 91 Elf_Data *data; 92 93 lte->symtab = elf_getdata(scn, NULL); 94 lte->symtab_count = shdr.sh_size / shdr.sh_entsize; 95 if ((lte->symtab == NULL 96 || elf_getdata(scn, lte->symtab) != NULL) 97 && opt_x != NULL) 98 error(EXIT_FAILURE, 0, 99 "Couldn't get .symtab data from \"%s\"", 100 filename); 101 102 scn = elf_getscn(lte->elf, shdr.sh_link); 103 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 104 error(EXIT_FAILURE, 0, 105 "Couldn't get section header from \"%s\"", 106 filename); 107 108 data = elf_getdata(scn, NULL); 109 if (data == NULL || elf_getdata(scn, data) != NULL 110 || shdr.sh_size != data->d_size || data->d_off) 111 error(EXIT_FAILURE, 0, 112 "Couldn't get .strtab data from \"%s\"", 113 filename); 114 115 lte->strtab = data->d_buf; 116 } else if (shdr.sh_type == SHT_DYNSYM) { 117 Elf_Data *data; 118 119 lte->dynsym = elf_getdata(scn, NULL); 120 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize; 121 if (lte->dynsym == NULL 122 || elf_getdata(scn, lte->dynsym) != NULL) 123 error(EXIT_FAILURE, 0, 124 "Couldn't get .dynsym data from \"%s\"", 125 filename); 126 127 scn = elf_getscn(lte->elf, shdr.sh_link); 128 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 129 error(EXIT_FAILURE, 0, 130 "Couldn't get section header from \"%s\"", 131 filename); 132 133 data = elf_getdata(scn, NULL); 134 if (data == NULL || elf_getdata(scn, data) != NULL 135 || shdr.sh_size != data->d_size || data->d_off) 136 error(EXIT_FAILURE, 0, 137 "Couldn't get .dynstr data from \"%s\"", 138 filename); 139 140 lte->dynstr = data->d_buf; 141 } else if (shdr.sh_type == SHT_DYNAMIC) { 142 Elf_Data *data; 143 size_t j; 144 145 data = elf_getdata(scn, NULL); 146 if (data == NULL || elf_getdata(scn, data) != NULL) 147 error(EXIT_FAILURE, 0, 148 "Couldn't get .dynamic data from \"%s\"", 149 filename); 150 151 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 152 GElf_Dyn dyn; 153 154 if (gelf_getdyn(data, j, &dyn) == NULL) 155 error(EXIT_FAILURE, 0, 156 "Couldn't get .dynamic data from \"%s\"", 157 filename); 158#ifdef __mips__ 159/** 160 MIPS ABI Supplement: 161 162 DT_PLTGOT This member holds the address of the .got section. 163 164 DT_MIPS_SYMTABNO This member holds the number of entries in the 165 .dynsym section. 166 167 DT_MIPS_LOCAL_GOTNO This member holds the number of local global 168 offset table entries. 169 170 DT_MIPS_GOTSYM This member holds the index of the first dyamic 171 symbol table entry that corresponds to an entry in the gobal offset 172 table. 173 174 */ 175 if(dyn.d_tag==DT_PLTGOT){ 176 lte->pltgot_addr=dyn.d_un.d_ptr; 177 } 178 if(dyn.d_tag==DT_MIPS_LOCAL_GOTNO){ 179 lte->mips_local_gotno=dyn.d_un.d_val; 180 } 181 if(dyn.d_tag==DT_MIPS_GOTSYM){ 182 lte->mips_gotsym=dyn.d_un.d_val; 183 } 184#endif // __mips__ 185 if (dyn.d_tag == DT_JMPREL) 186 relplt_addr = dyn.d_un.d_ptr; 187 else if (dyn.d_tag == DT_PLTRELSZ) 188 relplt_size = dyn.d_un.d_val; 189 } 190 } else if (shdr.sh_type == SHT_HASH) { 191 Elf_Data *data; 192 size_t j; 193 194 lte->hash_type = SHT_HASH; 195 196 data = elf_getdata(scn, NULL); 197 if (data == NULL || elf_getdata(scn, data) != NULL 198 || data->d_off || data->d_size != shdr.sh_size) 199 error(EXIT_FAILURE, 0, 200 "Couldn't get .hash data from \"%s\"", 201 filename); 202 203 if (shdr.sh_entsize == 4) { 204 /* Standard conforming ELF. */ 205 if (data->d_type != ELF_T_WORD) 206 error(EXIT_FAILURE, 0, 207 "Couldn't get .hash data from \"%s\"", 208 filename); 209 lte->hash = (Elf32_Word *) data->d_buf; 210 } else if (shdr.sh_entsize == 8) { 211 /* Alpha or s390x. */ 212 Elf32_Word *dst, *src; 213 size_t hash_count = data->d_size / 8; 214 215 lte->hash = (Elf32_Word *) 216 malloc(hash_count * sizeof(Elf32_Word)); 217 if (lte->hash == NULL) 218 error(EXIT_FAILURE, 0, 219 "Couldn't convert .hash section from \"%s\"", 220 filename); 221 lte->lte_flags |= LTE_HASH_MALLOCED; 222 dst = lte->hash; 223 src = (Elf32_Word *) data->d_buf; 224 if ((data->d_type == ELF_T_WORD 225 && __BYTE_ORDER == __BIG_ENDIAN) 226 || (data->d_type == ELF_T_XWORD 227 && lte->ehdr.e_ident[EI_DATA] == 228 ELFDATA2MSB)) 229 ++src; 230 for (j = 0; j < hash_count; ++j, src += 2) 231 *dst++ = *src; 232 } else 233 error(EXIT_FAILURE, 0, 234 "Unknown .hash sh_entsize in \"%s\"", 235 filename); 236 } else if (shdr.sh_type == SHT_GNU_HASH 237 && lte->hash == NULL) { 238 Elf_Data *data; 239 240 lte->hash_type = SHT_GNU_HASH; 241 242 if (shdr.sh_entsize != 0 243 && shdr.sh_entsize != 4) { 244 error(EXIT_FAILURE, 0, 245 ".gnu.hash sh_entsize in \"%s\" should be 4, but is %llu", 246 filename, shdr.sh_entsize); 247 } 248 249 data = elf_getdata(scn, NULL); 250 if (data == NULL || elf_getdata(scn, data) != NULL 251 || data->d_off || data->d_size != shdr.sh_size) 252 error(EXIT_FAILURE, 0, 253 "Couldn't get .gnu.hash data from \"%s\"", 254 filename); 255 256 lte->hash = (Elf32_Word *) data->d_buf; 257 } else if (shdr.sh_type == SHT_PROGBITS 258 || shdr.sh_type == SHT_NOBITS) { 259 if (strcmp(name, ".plt") == 0) { 260 lte->plt_addr = shdr.sh_addr; 261 lte->plt_size = shdr.sh_size; 262 if (shdr.sh_flags & SHF_EXECINSTR) { 263 lte->lte_flags |= LTE_PLT_EXECUTABLE; 264 } 265 } 266#ifdef ARCH_SUPPORTS_OPD 267 else if (strcmp(name, ".opd") == 0) { 268 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr; 269 lte->opd_size = shdr.sh_size; 270 lte->opd = elf_rawdata(scn, NULL); 271 } 272#endif 273 } 274 } 275 276 if (lte->dynsym == NULL || lte->dynstr == NULL) 277 error(EXIT_FAILURE, 0, 278 "Couldn't find .dynsym or .dynstr in \"%s\"", filename); 279 280 if (!relplt_addr || !lte->plt_addr) { 281 debug(1, "%s has no PLT relocations", filename); 282 lte->relplt = NULL; 283 lte->relplt_count = 0; 284 } else { 285 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 286 Elf_Scn *scn; 287 GElf_Shdr shdr; 288 289 scn = elf_getscn(lte->elf, i); 290 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 291 error(EXIT_FAILURE, 0, 292 "Couldn't get section header from \"%s\"", 293 filename); 294 if (shdr.sh_addr == relplt_addr 295 && shdr.sh_size == relplt_size) { 296 lte->relplt = elf_getdata(scn, NULL); 297 lte->relplt_count = 298 shdr.sh_size / shdr.sh_entsize; 299 if (lte->relplt == NULL 300 || elf_getdata(scn, lte->relplt) != NULL) 301 error(EXIT_FAILURE, 0, 302 "Couldn't get .rel*.plt data from \"%s\"", 303 filename); 304 break; 305 } 306 } 307 308 if (i == lte->ehdr.e_shnum) 309 error(EXIT_FAILURE, 0, 310 "Couldn't find .rel*.plt section in \"%s\"", 311 filename); 312 313 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); 314 } 315} 316 317static void 318do_close_elf(struct ltelf *lte) { 319 debug(DEBUG_FUNCTION, "do_close_elf()"); 320 if (lte->lte_flags & LTE_HASH_MALLOCED) 321 free((char *)lte->hash); 322 elf_end(lte->elf); 323 close(lte->fd); 324} 325 326static void 327add_library_symbol(GElf_Addr addr, const char *name, 328 struct library_symbol **library_symbolspp, 329 enum toplt type_of_plt, int is_weak) { 330 struct library_symbol *s; 331 332 debug(DEBUG_FUNCTION, "add_library_symbol()"); 333 334 s = malloc(sizeof(struct library_symbol) + strlen(name) + 1); 335 if (s == NULL) 336 error(EXIT_FAILURE, errno, "add_library_symbol failed"); 337 338 s->needs_init = 1; 339 s->is_weak = is_weak; 340 s->plt_type = type_of_plt; 341 s->next = *library_symbolspp; 342 s->enter_addr = (void *)(uintptr_t) addr; 343 s->name = (char *)(s + 1); 344 strcpy(s->name, name); 345 *library_symbolspp = s; 346 347 debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name); 348} 349 350/* stolen from elfutils-0.123 */ 351static unsigned long 352private_elf_gnu_hash(const char *name) { 353 unsigned long h = 5381; 354 const unsigned char *string = (const unsigned char *)name; 355 unsigned char c; 356 for (c = *string; c; c = *++string) 357 h = h * 33 + c; 358 return h & 0xffffffff; 359} 360 361static int 362in_load_libraries(const char *name, struct ltelf *lte) { 363 size_t i; 364 unsigned long hash; 365 unsigned long gnu_hash; 366 367 if (!library_num) 368 return 1; 369 370 hash = elf_hash((const unsigned char *)name); 371 gnu_hash = private_elf_gnu_hash(name); 372 for (i = 1; i <= library_num; ++i) { 373 if (lte[i].hash == NULL) 374 continue; 375 376 if (lte[i].hash_type == SHT_GNU_HASH) { 377 Elf32_Word * hashbase = lte[i].hash; 378 Elf32_Word nbuckets = *hashbase++; 379 Elf32_Word symbias = *hashbase++; 380 Elf32_Word bitmask_nwords = *hashbase++; 381 Elf32_Word * buckets; 382 Elf32_Word * chain_zero; 383 Elf32_Word bucket; 384 385 // +1 for skipped `shift' 386 hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1; 387 buckets = hashbase; 388 hashbase += nbuckets; 389 chain_zero = hashbase - symbias; 390 bucket = buckets[gnu_hash % nbuckets]; 391 392 if (bucket != 0) { 393 const Elf32_Word *hasharr = &chain_zero[bucket]; 394 do 395 if ((*hasharr & ~1u) == (gnu_hash & ~1u)) { 396 int symidx = hasharr - chain_zero; 397 GElf_Sym sym; 398 399 if (gelf_getsym(lte[i].dynsym, symidx, &sym) == NULL) 400 error(EXIT_FAILURE, 0, 401 "Couldn't get symbol from .dynsym"); 402 403 if (sym.st_value != 0 404 && sym.st_shndx != SHN_UNDEF 405 && strcmp(name, lte[i].dynstr + sym.st_name) == 0) 406 return 1; 407 } 408 while ((*hasharr++ & 1u) == 0); 409 } 410 } else { 411 Elf32_Word nbuckets, symndx; 412 Elf32_Word *buckets, *chain; 413 nbuckets = lte[i].hash[0]; 414 buckets = <e[i].hash[2]; 415 chain = <e[i].hash[2 + nbuckets]; 416 417 for (symndx = buckets[hash % nbuckets]; 418 symndx != STN_UNDEF; symndx = chain[symndx]) { 419 GElf_Sym sym; 420 421 if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL) 422 error(EXIT_FAILURE, 0, 423 "Couldn't get symbol from .dynsym"); 424 425 if (sym.st_value != 0 426 && sym.st_shndx != SHN_UNDEF 427 && strcmp(name, lte[i].dynstr + sym.st_name) == 0) 428 return 1; 429 } 430 } 431 } 432 return 0; 433} 434 435static GElf_Addr 436opd2addr(struct ltelf *lte, GElf_Addr addr) { 437#ifdef ARCH_SUPPORTS_OPD 438 unsigned long base, offset; 439 440 if (!lte->opd) 441 return addr; 442 443 base = (unsigned long)lte->opd->d_buf; 444 offset = (unsigned long)addr - (unsigned long)lte->opd_addr; 445 if (offset > lte->opd_size) 446 error(EXIT_FAILURE, 0, "static plt not in .opd"); 447 448 return *(GElf_Addr*)(base + offset); 449#else //!ARCH_SUPPORTS_OPD 450 return addr; 451#endif 452} 453 454struct library_symbol * 455read_elf(Process *proc) { 456 struct library_symbol *library_symbols = NULL; 457 struct ltelf lte[MAX_LIBRARIES + 1]; 458 size_t i; 459 struct opt_x_t *xptr; 460 struct library_symbol **lib_tail = NULL; 461 int exit_out = 0; 462 463 debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename); 464 465 elf_version(EV_CURRENT); 466 467 do_init_elf(lte, proc->filename); 468 proc->e_machine = lte->ehdr.e_machine; 469 for (i = 0; i < library_num; ++i) 470 do_init_elf(<e[i + 1], library[i]); 471 472 if (!options.no_plt) { 473#ifdef __mips__ 474 // MIPS doesn't use the PLT and the GOT entries get changed 475 // on startup. 476 proc->need_to_reinitialize_breakpoints = 1; 477 for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){ 478 GElf_Sym sym; 479 const char *name; 480 GElf_Addr addr = arch_plt_sym_val(lte, i, 0); 481 if (gelf_getsym(lte->dynsym, i, &sym) == NULL){ 482 error(EXIT_FAILURE, 0, 483 "Couldn't get relocation from \"%s\"", 484 proc->filename); 485 } 486 name=lte->dynstr+sym.st_name; 487 if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){ 488 debug(2,"sym %s not a function",name); 489 continue; 490 } 491 add_library_symbol(addr, name, &library_symbols, 0, 492 ELF64_ST_BIND(sym.st_info) != 0); 493 if (!lib_tail) 494 lib_tail = &(library_symbols->next); 495 } 496#else 497 for (i = 0; i < lte->relplt_count; ++i) { 498 GElf_Rel rel; 499 GElf_Rela rela; 500 GElf_Sym sym; 501 GElf_Addr addr; 502 void *ret; 503 const char *name; 504 505 if (lte->relplt->d_type == ELF_T_REL) { 506 ret = gelf_getrel(lte->relplt, i, &rel); 507 rela.r_offset = rel.r_offset; 508 rela.r_info = rel.r_info; 509 rela.r_addend = 0; 510 } else 511 ret = gelf_getrela(lte->relplt, i, &rela); 512 513 if (ret == NULL 514 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count 515 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info), 516 &sym) == NULL) 517 error(EXIT_FAILURE, 0, 518 "Couldn't get relocation from \"%s\"", 519 proc->filename); 520 521#ifdef PLT_REINITALISATION_BP 522 if (!sym.st_value && PLTs_initialized_by_here) 523 proc->need_to_reinitialize_breakpoints = 1; 524#endif 525 526 name = lte->dynstr + sym.st_name; 527 if (in_load_libraries(name, lte)) { 528 addr = arch_plt_sym_val(lte, i, &rela); 529 add_library_symbol(addr, name, &library_symbols, 530 (PLTS_ARE_EXECUTABLE(lte) 531 ? LS_TOPLT_EXEC : LS_TOPLT_POINT), 532 ELF64_ST_BIND(sym.st_info) == STB_WEAK); 533 if (!lib_tail) 534 lib_tail = &(library_symbols->next); 535 } 536 } 537#endif // !__mips__ 538#ifdef PLT_REINITALISATION_BP 539 struct opt_x_t *main_cheat; 540 541 if (proc->need_to_reinitialize_breakpoints) { 542 /* Add "PLTs_initialized_by_here" to opt_x list, if not 543 already there. */ 544 main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t)); 545 if (main_cheat == NULL) 546 error(EXIT_FAILURE, 0, "Couldn't allocate memory"); 547 main_cheat->next = opt_x; 548 main_cheat->found = 0; 549 main_cheat->name = PLTs_initialized_by_here; 550 551 for (xptr = opt_x; xptr; xptr = xptr->next) 552 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0 553 && main_cheat) { 554 free(main_cheat); 555 main_cheat = NULL; 556 break; 557 } 558 if (main_cheat) 559 opt_x = main_cheat; 560 } 561#endif 562 } else { 563 lib_tail = &library_symbols; 564 } 565 566 for (i = 0; i < lte->symtab_count; ++i) { 567 GElf_Sym sym; 568 GElf_Addr addr; 569 const char *name; 570 571 if (gelf_getsym(lte->symtab, i, &sym) == NULL) 572 error(EXIT_FAILURE, 0, 573 "Couldn't get symbol from \"%s\"", 574 proc->filename); 575 576 name = lte->strtab + sym.st_name; 577 addr = sym.st_value; 578 if (!addr) 579 continue; 580 581 for (xptr = opt_x; xptr; xptr = xptr->next) 582 if (xptr->name && strcmp(xptr->name, name) == 0) { 583 /* FIXME: Should be able to use &library_symbols as above. But 584 when you do, none of the real library symbols cause breaks. */ 585 add_library_symbol(opd2addr(lte, addr), 586 name, lib_tail, LS_TOPLT_NONE, 0); 587 xptr->found = 1; 588 break; 589 } 590 } 591 for (xptr = opt_x; xptr; xptr = xptr->next) 592 if ( ! xptr->found) { 593 char *badthing = "WARNING"; 594#ifdef PLT_REINITALISATION_BP 595 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) { 596 if (lte->ehdr.e_entry) { 597 add_library_symbol ( 598 opd2addr (lte, lte->ehdr.e_entry), 599 PLTs_initialized_by_here, 600 lib_tail, 1, 0); 601 fprintf (stderr, "WARNING: Using e_ent" 602 "ry from elf header (%p) for " 603 "address of \"%s\"\n", (void*) 604 (long) lte->ehdr.e_entry, 605 PLTs_initialized_by_here); 606 continue; 607 } 608 badthing = "ERROR"; 609 exit_out = 1; 610 } 611#endif 612 fprintf (stderr, 613 "%s: Couldn't find symbol \"%s\" in file \"%s" 614 "\"\n", badthing, xptr->name, proc->filename); 615 } 616 if (exit_out) { 617 exit (1); 618 } 619 620 for (i = 0; i < library_num + 1; ++i) 621 do_close_elf(<e[i]); 622 623 return library_symbols; 624} 625