ltrace-elf.c revision a7db59c355cef464073496221ad27519a48466f9
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 <inttypes.h> 9#include <stdint.h> 10#include <stdlib.h> 11#include <string.h> 12#include <unistd.h> 13#include <assert.h> 14 15#include "common.h" 16#include "proc.h" 17 18void do_close_elf(struct ltelf *lte); 19void add_library_symbol(GElf_Addr addr, const char *name, 20 struct library_symbol **library_symbolspp, 21 enum toplt type_of_plt, int is_weak); 22int in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym); 23static GElf_Addr opd2addr(struct ltelf *ltc, GElf_Addr addr); 24 25struct library_symbol *library_symbols = NULL; 26struct ltelf main_lte; 27 28#ifdef PLT_REINITALISATION_BP 29extern char *PLTs_initialized_by_here; 30#endif 31 32#ifndef DT_PPC_GOT 33# define DT_PPC_GOT (DT_LOPROC + 0) 34#endif 35 36#define PPC_PLT_STUB_SIZE 16 37 38static Elf_Data *loaddata(Elf_Scn *scn, GElf_Shdr *shdr) 39{ 40 Elf_Data *data = elf_getdata(scn, NULL); 41 if (data == NULL || elf_getdata(scn, data) != NULL 42 || data->d_off || data->d_size != shdr->sh_size) 43 return NULL; 44 return data; 45} 46 47static int inside(GElf_Addr addr, GElf_Shdr *shdr) 48{ 49 return addr >= shdr->sh_addr 50 && addr < shdr->sh_addr + shdr->sh_size; 51} 52 53static int maybe_pick_section(GElf_Addr addr, 54 Elf_Scn *in_sec, GElf_Shdr *in_shdr, 55 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 56{ 57 if (inside (addr, in_shdr)) { 58 *tgt_sec = in_sec; 59 *tgt_shdr = *in_shdr; 60 return 1; 61 } 62 return 0; 63} 64 65static int get_section_covering(struct ltelf *lte, GElf_Addr addr, 66 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 67{ 68 int i; 69 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 70 Elf_Scn *scn; 71 GElf_Shdr shdr; 72 73 scn = elf_getscn(lte->elf, i); 74 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) { 75 debug(1, "Couldn't read section or header."); 76 return 0; 77 } 78 79 if (maybe_pick_section(addr, scn, &shdr, tgt_sec, tgt_shdr)) 80 return 1; 81 } 82 83 return 0; 84} 85 86static GElf_Addr read32be(Elf_Data *data, size_t offset) 87{ 88 if (data->d_size < offset + 4) { 89 debug(1, "Not enough data to read 32bit value at offset %zd.", 90 offset); 91 return 0; 92 } 93 94 unsigned char const *buf = data->d_buf + offset; 95 return ((Elf32_Word)buf[0] << 24) 96 | ((Elf32_Word)buf[1] << 16) 97 | ((Elf32_Word)buf[2] << 8) 98 | ((Elf32_Word)buf[3]); 99} 100 101static GElf_Addr get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, 102 Elf_Data *plt_data) 103{ 104 Elf_Scn *ppcgot_sec = NULL; 105 GElf_Shdr ppcgot_shdr; 106 if (ppcgot != 0 107 && !get_section_covering(lte, ppcgot, &ppcgot_sec, &ppcgot_shdr)) 108 // xxx should be the log out 109 fprintf(stderr, 110 "DT_PPC_GOT=%#" PRIx64 ", but no such section found.\n", 111 ppcgot); 112 113 if (ppcgot_sec != NULL) { 114 Elf_Data *data = loaddata(ppcgot_sec, &ppcgot_shdr); 115 if (data == NULL 116 || data->d_size < 8 ) 117 debug(1, "Couldn't read GOT data."); 118 else { 119 // where PPCGOT begins in .got 120 size_t offset = ppcgot - ppcgot_shdr.sh_addr; 121 GElf_Addr glink_vma = read32be(data, offset + 4); 122 if (glink_vma != 0) { 123 debug(1, "PPC GOT glink_vma address: %#" PRIx64, 124 glink_vma); 125 return glink_vma; 126 } 127 } 128 } 129 130 if (plt_data != NULL) { 131 GElf_Addr glink_vma = read32be(plt_data, 0); 132 debug(1, ".plt glink_vma address: %#" PRIx64, glink_vma); 133 return glink_vma; 134 } 135 136 return 0; 137} 138 139int 140open_elf(struct ltelf *lte, const char *filename) 141{ 142 lte->fd = open(filename, O_RDONLY); 143 if (lte->fd == -1) 144 return 1; 145 146 elf_version(EV_CURRENT); 147 148#ifdef HAVE_ELF_C_READ_MMAP 149 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL); 150#else 151 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL); 152#endif 153 154 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) 155 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename); 156 157 if (gelf_getehdr(lte->elf, <e->ehdr) == NULL) 158 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", 159 filename); 160 161 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) 162 error(EXIT_FAILURE, 0, 163 "\"%s\" is not an ELF executable nor shared library", 164 filename); 165 166 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS 167 || lte->ehdr.e_machine != LT_ELF_MACHINE) 168#ifdef LT_ELF_MACHINE2 169 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2 170 || lte->ehdr.e_machine != LT_ELF_MACHINE2) 171#endif 172#ifdef LT_ELF_MACHINE3 173 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3 174 || lte->ehdr.e_machine != LT_ELF_MACHINE3) 175#endif 176 ) 177 error(EXIT_FAILURE, 0, 178 "\"%s\" is ELF from incompatible architecture", filename); 179 180 return 0; 181} 182 183int 184do_init_elf(struct ltelf *lte, const char *filename) { 185 int i; 186 GElf_Addr relplt_addr = 0; 187 size_t relplt_size = 0; 188 189 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); 190 debug(1, "Reading ELF from %s...", filename); 191 192 if (open_elf(lte, filename) < 0) 193 return -1; 194 195 Elf_Data *plt_data = NULL; 196 GElf_Addr ppcgot = 0; 197 198 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 199 Elf_Scn *scn; 200 GElf_Shdr shdr; 201 const char *name; 202 203 scn = elf_getscn(lte->elf, i); 204 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 205 error(EXIT_FAILURE, 0, 206 "Couldn't get section header from \"%s\"", 207 filename); 208 209 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name); 210 if (name == NULL) 211 error(EXIT_FAILURE, 0, 212 "Couldn't get section header from \"%s\"", 213 filename); 214 215 if (shdr.sh_type == SHT_SYMTAB) { 216 Elf_Data *data; 217 218 lte->symtab = elf_getdata(scn, NULL); 219 lte->symtab_count = shdr.sh_size / shdr.sh_entsize; 220 if ((lte->symtab == NULL 221 || elf_getdata(scn, lte->symtab) != NULL) 222 && opt_x != NULL) 223 error(EXIT_FAILURE, 0, 224 "Couldn't get .symtab data from \"%s\"", 225 filename); 226 227 scn = elf_getscn(lte->elf, shdr.sh_link); 228 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 229 error(EXIT_FAILURE, 0, 230 "Couldn't get section header from \"%s\"", 231 filename); 232 233 data = elf_getdata(scn, NULL); 234 if (data == NULL || elf_getdata(scn, data) != NULL 235 || shdr.sh_size != data->d_size || data->d_off) 236 error(EXIT_FAILURE, 0, 237 "Couldn't get .strtab data from \"%s\"", 238 filename); 239 240 lte->strtab = data->d_buf; 241 } else if (shdr.sh_type == SHT_DYNSYM) { 242 Elf_Data *data; 243 244 lte->dynsym = elf_getdata(scn, NULL); 245 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize; 246 if (lte->dynsym == NULL 247 || elf_getdata(scn, lte->dynsym) != NULL) 248 error(EXIT_FAILURE, 0, 249 "Couldn't get .dynsym data from \"%s\"", 250 filename); 251 252 scn = elf_getscn(lte->elf, shdr.sh_link); 253 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 254 error(EXIT_FAILURE, 0, 255 "Couldn't get section header from \"%s\"", 256 filename); 257 258 data = elf_getdata(scn, NULL); 259 if (data == NULL || elf_getdata(scn, data) != NULL 260 || shdr.sh_size != data->d_size || data->d_off) 261 error(EXIT_FAILURE, 0, 262 "Couldn't get .dynstr data from \"%s\"", 263 filename); 264 265 lte->dynstr = data->d_buf; 266 } else if (shdr.sh_type == SHT_DYNAMIC) { 267 Elf_Data *data; 268 size_t j; 269 270 lte->dyn_addr = shdr.sh_addr; 271 lte->dyn_sz = shdr.sh_size; 272 273 data = elf_getdata(scn, NULL); 274 if (data == NULL || elf_getdata(scn, data) != NULL) 275 error(EXIT_FAILURE, 0, 276 "Couldn't get .dynamic data from \"%s\"", 277 filename); 278 279 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 280 GElf_Dyn dyn; 281 282 if (gelf_getdyn(data, j, &dyn) == NULL) 283 error(EXIT_FAILURE, 0, 284 "Couldn't get .dynamic data from \"%s\"", 285 filename); 286#ifdef __mips__ 287/** 288 MIPS ABI Supplement: 289 290 DT_PLTGOT This member holds the address of the .got section. 291 292 DT_MIPS_SYMTABNO This member holds the number of entries in the 293 .dynsym section. 294 295 DT_MIPS_LOCAL_GOTNO This member holds the number of local global 296 offset table entries. 297 298 DT_MIPS_GOTSYM This member holds the index of the first dyamic 299 symbol table entry that corresponds to an entry in the gobal offset 300 table. 301 302 */ 303 if(dyn.d_tag==DT_PLTGOT){ 304 lte->pltgot_addr=dyn.d_un.d_ptr; 305 } 306 if(dyn.d_tag==DT_MIPS_LOCAL_GOTNO){ 307 lte->mips_local_gotno=dyn.d_un.d_val; 308 } 309 if(dyn.d_tag==DT_MIPS_GOTSYM){ 310 lte->mips_gotsym=dyn.d_un.d_val; 311 } 312#endif // __mips__ 313 if (dyn.d_tag == DT_JMPREL) 314 relplt_addr = dyn.d_un.d_ptr; 315 else if (dyn.d_tag == DT_PLTRELSZ) 316 relplt_size = dyn.d_un.d_val; 317 else if (dyn.d_tag == DT_PPC_GOT) { 318 ppcgot = dyn.d_un.d_val; 319 debug(1, "ppcgot %#" PRIx64, ppcgot); 320 } 321 } 322 } else if (shdr.sh_type == SHT_HASH) { 323 Elf_Data *data; 324 size_t j; 325 326 lte->hash_type = SHT_HASH; 327 328 data = elf_getdata(scn, NULL); 329 if (data == NULL || elf_getdata(scn, data) != NULL 330 || data->d_off || data->d_size != shdr.sh_size) 331 error(EXIT_FAILURE, 0, 332 "Couldn't get .hash data from \"%s\"", 333 filename); 334 335 if (shdr.sh_entsize == 4) { 336 /* Standard conforming ELF. */ 337 if (data->d_type != ELF_T_WORD) 338 error(EXIT_FAILURE, 0, 339 "Couldn't get .hash data from \"%s\"", 340 filename); 341 lte->hash = (Elf32_Word *) data->d_buf; 342 } else if (shdr.sh_entsize == 8) { 343 /* Alpha or s390x. */ 344 Elf32_Word *dst, *src; 345 size_t hash_count = data->d_size / 8; 346 347 lte->hash = (Elf32_Word *) 348 malloc(hash_count * sizeof(Elf32_Word)); 349 if (lte->hash == NULL) 350 error(EXIT_FAILURE, 0, 351 "Couldn't convert .hash section from \"%s\"", 352 filename); 353 lte->lte_flags |= LTE_HASH_MALLOCED; 354 dst = lte->hash; 355 src = (Elf32_Word *) data->d_buf; 356 if ((data->d_type == ELF_T_WORD 357 && __BYTE_ORDER == __BIG_ENDIAN) 358 || (data->d_type == ELF_T_XWORD 359 && lte->ehdr.e_ident[EI_DATA] == 360 ELFDATA2MSB)) 361 ++src; 362 for (j = 0; j < hash_count; ++j, src += 2) 363 *dst++ = *src; 364 } else 365 error(EXIT_FAILURE, 0, 366 "Unknown .hash sh_entsize in \"%s\"", 367 filename); 368 } else if (shdr.sh_type == SHT_GNU_HASH 369 && lte->hash == NULL) { 370 Elf_Data *data; 371 372 lte->hash_type = SHT_GNU_HASH; 373 374 if (shdr.sh_entsize != 0 375 && shdr.sh_entsize != 4) { 376 error(EXIT_FAILURE, 0, 377 ".gnu.hash sh_entsize in \"%s\" " 378 "should be 4, but is %#" PRIx64, 379 filename, shdr.sh_entsize); 380 } 381 382 data = loaddata(scn, &shdr); 383 if (data == NULL) 384 error(EXIT_FAILURE, 0, 385 "Couldn't get .gnu.hash data from \"%s\"", 386 filename); 387 388 lte->hash = (Elf32_Word *) data->d_buf; 389 } else if (shdr.sh_type == SHT_PROGBITS 390 || shdr.sh_type == SHT_NOBITS) { 391 if (strcmp(name, ".plt") == 0) { 392 lte->plt_addr = shdr.sh_addr; 393 lte->plt_size = shdr.sh_size; 394 if (shdr.sh_flags & SHF_EXECINSTR) { 395 lte->lte_flags |= LTE_PLT_EXECUTABLE; 396 } 397 if (lte->ehdr.e_machine == EM_PPC) { 398 plt_data = loaddata(scn, &shdr); 399 if (plt_data == NULL) 400 fprintf(stderr, 401 "Can't load .plt data\n"); 402 } 403 } 404#ifdef ARCH_SUPPORTS_OPD 405 else if (strcmp(name, ".opd") == 0) { 406 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr; 407 lte->opd_size = shdr.sh_size; 408 lte->opd = elf_rawdata(scn, NULL); 409 } 410#endif 411 } 412 } 413 414 if (lte->dynsym == NULL || lte->dynstr == NULL) 415 error(EXIT_FAILURE, 0, 416 "Couldn't find .dynsym or .dynstr in \"%s\"", filename); 417 418 if (!relplt_addr || !lte->plt_addr) { 419 debug(1, "%s has no PLT relocations", filename); 420 lte->relplt = NULL; 421 lte->relplt_count = 0; 422 } else if (relplt_size == 0) { 423 debug(1, "%s has unknown PLT size", filename); 424 lte->relplt = NULL; 425 lte->relplt_count = 0; 426 } else { 427 if (lte->ehdr.e_machine == EM_PPC) { 428 GElf_Addr glink_vma 429 = get_glink_vma(lte, ppcgot, plt_data); 430 431 assert (relplt_size % 12 == 0); 432 size_t count = relplt_size / 12; // size of RELA entry 433 lte->plt_stub_vma = glink_vma 434 - (GElf_Addr)count * PPC_PLT_STUB_SIZE; 435 debug(1, "stub_vma is %#" PRIx64, lte->plt_stub_vma); 436 } 437 438 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 439 Elf_Scn *scn; 440 GElf_Shdr shdr; 441 442 scn = elf_getscn(lte->elf, i); 443 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 444 error(EXIT_FAILURE, 0, 445 "Couldn't get section header from \"%s\"", 446 filename); 447 if (shdr.sh_addr == relplt_addr 448 && shdr.sh_size == relplt_size) { 449 lte->relplt = elf_getdata(scn, NULL); 450 lte->relplt_count = 451 shdr.sh_size / shdr.sh_entsize; 452 if (lte->relplt == NULL 453 || elf_getdata(scn, lte->relplt) != NULL) 454 error(EXIT_FAILURE, 0, 455 "Couldn't get .rel*.plt data from \"%s\"", 456 filename); 457 break; 458 } 459 } 460 461 if (i == lte->ehdr.e_shnum) 462 error(EXIT_FAILURE, 0, 463 "Couldn't find .rel*.plt section in \"%s\"", 464 filename); 465 466 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); 467 } 468 return 0; 469} 470 471void 472do_close_elf(struct ltelf *lte) { 473 debug(DEBUG_FUNCTION, "do_close_elf()"); 474 if (lte->lte_flags & LTE_HASH_MALLOCED) 475 free((char *)lte->hash); 476 elf_end(lte->elf); 477 close(lte->fd); 478} 479 480void 481library_symbol_init(struct library_symbol *libsym, 482 GElf_Addr addr, const char *name, 483 enum toplt type_of_plt, int is_weak) 484{ 485 libsym->needs_init = 0; 486 libsym->is_weak = is_weak; 487 libsym->plt_type = type_of_plt; 488 libsym->name = name; 489 libsym->enter_addr = (void *)(uintptr_t)addr; 490 libsym->next = NULL; 491} 492 493static struct library_symbol * 494create_library_symbol(const char *name, GElf_Addr addr, 495 enum toplt type_of_plt, int is_weak) 496{ 497 size_t namel = strlen(name) + 1; 498 struct library_symbol * libsym = calloc(sizeof(*libsym) + namel, 1); 499 if (libsym == NULL) { 500 perror("create_library_symbol"); 501 return NULL; 502 } 503 memcpy(libsym + 1, name, namel); 504 library_symbol_init(libsym, addr, 505 (char *)(libsym + 1), type_of_plt, is_weak); 506 507 return libsym; 508} 509 510void 511add_library_symbol(GElf_Addr addr, const char *name, 512 struct library_symbol **library_symbolspp, 513 enum toplt type_of_plt, int is_weak) 514{ 515 debug(DEBUG_FUNCTION, "add_library_symbol()"); 516 517 struct library_symbol *s = create_library_symbol(name, addr, 518 type_of_plt, is_weak); 519 if (s == NULL) 520 error(EXIT_FAILURE, errno, "add_library_symbol failed"); 521 522 s->needs_init = 1; 523 s->next = *library_symbolspp; 524 *library_symbolspp = s; 525 526 debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name); 527} 528 529struct library_symbol * 530clone_library_symbol(struct library_symbol *libsym) 531{ 532 GElf_Addr addr = (uintptr_t)libsym->enter_addr; 533 struct library_symbol *copy 534 = create_library_symbol(libsym->name, addr, 535 libsym->plt_type, libsym->is_weak); 536 if (copy != NULL) 537 copy->needs_init = libsym->needs_init; 538 539 return copy; 540} 541 542void 543destroy_library_symbol(struct library_symbol * sym) 544{ 545 free(sym); 546} 547 548void 549destroy_library_symbol_chain(struct library_symbol * sym) 550{ 551 while (sym != NULL) { 552 struct library_symbol * next = sym->next; 553 destroy_library_symbol(sym); 554 sym = next; 555 } 556} 557 558/* stolen from elfutils-0.123 */ 559static unsigned long 560private_elf_gnu_hash(const char *name) { 561 unsigned long h = 5381; 562 const unsigned char *string = (const unsigned char *)name; 563 unsigned char c; 564 for (c = *string; c; c = *++string) 565 h = h * 33 + c; 566 return h & 0xffffffff; 567} 568 569static int 570symbol_matches(struct ltelf *lte, size_t lte_i, GElf_Sym *sym, 571 size_t symidx, const char *name) 572{ 573 GElf_Sym tmp_sym; 574 GElf_Sym *tmp; 575 576 tmp = (sym) ? (sym) : (&tmp_sym); 577 578 if (gelf_getsym(lte[lte_i].dynsym, symidx, tmp) == NULL) 579 error(EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym"); 580 else { 581 tmp->st_value += lte[lte_i].base_addr; 582 debug(2, "symbol found: %s, %zd, %#" PRIx64, 583 name, lte_i, tmp->st_value); 584 } 585 return tmp->st_value != 0 586 && tmp->st_shndx != SHN_UNDEF 587 && strcmp(name, lte[lte_i].dynstr + tmp->st_name) == 0; 588} 589 590int 591in_load_libraries(const char *name, struct ltelf *lte, size_t count, GElf_Sym *sym) { 592 size_t i; 593 unsigned long hash; 594 unsigned long gnu_hash; 595 596 if (!count) 597 return 1; 598 599#ifdef ELF_HASH_TAKES_CHARP 600 hash = elf_hash(name); 601#else 602 hash = elf_hash((const unsigned char *)name); 603#endif 604 gnu_hash = private_elf_gnu_hash(name); 605 606 for (i = 0; i < count; ++i) { 607 if (lte[i].hash == NULL) 608 continue; 609 610 if (lte[i].hash_type == SHT_GNU_HASH) { 611 Elf32_Word * hashbase = lte[i].hash; 612 Elf32_Word nbuckets = *hashbase++; 613 Elf32_Word symbias = *hashbase++; 614 Elf32_Word bitmask_nwords = *hashbase++; 615 Elf32_Word * buckets; 616 Elf32_Word * chain_zero; 617 Elf32_Word bucket; 618 619 // +1 for skipped `shift' 620 hashbase += lte[i].ehdr.e_ident[EI_CLASS] * bitmask_nwords + 1; 621 buckets = hashbase; 622 hashbase += nbuckets; 623 chain_zero = hashbase - symbias; 624 bucket = buckets[gnu_hash % nbuckets]; 625 626 if (bucket != 0) { 627 const Elf32_Word *hasharr = &chain_zero[bucket]; 628 do 629 if ((*hasharr & ~1u) == (gnu_hash & ~1u)) { 630 int symidx = hasharr - chain_zero; 631 if (symbol_matches(lte, i, 632 sym, symidx, 633 name)) 634 return 1; 635 } 636 while ((*hasharr++ & 1u) == 0); 637 } 638 } else { 639 Elf32_Word nbuckets, symndx; 640 Elf32_Word *buckets, *chain; 641 nbuckets = lte[i].hash[0]; 642 buckets = <e[i].hash[2]; 643 chain = <e[i].hash[2 + nbuckets]; 644 645 for (symndx = buckets[hash % nbuckets]; 646 symndx != STN_UNDEF; symndx = chain[symndx]) 647 if (symbol_matches(lte, i, sym, symndx, name)) 648 return 1; 649 } 650 } 651 return 0; 652} 653 654static GElf_Addr 655opd2addr(struct ltelf *lte, GElf_Addr addr) { 656#ifdef ARCH_SUPPORTS_OPD 657 unsigned long base, offset; 658 659 if (!lte->opd) 660 return addr; 661 662 base = (unsigned long)lte->opd->d_buf; 663 offset = (unsigned long)addr - (unsigned long)lte->opd_addr; 664 if (offset > lte->opd_size) 665 error(EXIT_FAILURE, 0, "static plt not in .opd"); 666 667 return *(GElf_Addr*)(base + offset); 668#else //!ARCH_SUPPORTS_OPD 669 return addr; 670#endif 671} 672 673struct library_symbol * 674read_elf(Process *proc, GElf_Addr *entryp) 675{ 676 struct ltelf lte[MAX_LIBRARIES + 1]; 677 size_t i; 678 struct opt_x_t *xptr; 679 struct opt_x_t *opt_x_loc = opt_x; 680 struct library_symbol **lib_tail = NULL; 681 int exit_out = 0; 682 int count = 0; 683 684 debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename); 685 686 memset(lte, 0, sizeof(lte)); 687 library_symbols = NULL; 688 library_num = 0; 689 proc->libdl_hooked = 0; 690 691 if (do_init_elf(lte, proc->filename)) 692 return NULL; 693 694 memcpy(&main_lte, lte, sizeof(struct ltelf)); 695 696 if (opt_p && opt_p->pid > 0) { 697 linkmap_init(proc, lte); 698 proc->libdl_hooked = 1; 699 } 700 701 proc->e_machine = lte->ehdr.e_machine; 702 703 for (i = 0; i < library_num; ++i) { 704 if (do_init_elf(<e[i + 1], library[i])) 705 error(EXIT_FAILURE, errno, "Can't open \"%s\"", 706 library[i]); 707 } 708 709 if (!options.no_plt) { 710#ifdef __mips__ 711 // MIPS doesn't use the PLT and the GOT entries get changed 712 // on startup. 713 for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){ 714 GElf_Sym sym; 715 const char *name; 716 GElf_Addr addr = arch_plt_sym_val(lte, i, 0); 717 if (gelf_getsym(lte->dynsym, i, &sym) == NULL){ 718 error(EXIT_FAILURE, 0, 719 "Couldn't get relocation from \"%s\"", 720 proc->filename); 721 } 722 name=lte->dynstr+sym.st_name; 723 if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){ 724 debug(2,"sym %s not a function",name); 725 continue; 726 } 727 add_library_symbol(addr, name, &library_symbols, 0, 728 ELF64_ST_BIND(sym.st_info) != 0); 729 if (!lib_tail) 730 lib_tail = &(library_symbols->next); 731 } 732#else 733 for (i = 0; i < lte->relplt_count; ++i) { 734 GElf_Rel rel; 735 GElf_Rela rela; 736 GElf_Sym sym; 737 GElf_Addr addr; 738 void *ret; 739 const char *name; 740 741 if (lte->relplt->d_type == ELF_T_REL) { 742 ret = gelf_getrel(lte->relplt, i, &rel); 743 rela.r_offset = rel.r_offset; 744 rela.r_info = rel.r_info; 745 rela.r_addend = 0; 746 } else 747 ret = gelf_getrela(lte->relplt, i, &rela); 748 749 if (ret == NULL 750 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count 751 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info), 752 &sym) == NULL) 753 error(EXIT_FAILURE, 0, 754 "Couldn't get relocation from \"%s\"", 755 proc->filename); 756 757 name = lte->dynstr + sym.st_name; 758 count = library_num ? library_num+1 : 0; 759 760 if (in_load_libraries(name, lte, count, NULL)) { 761 enum toplt pltt; 762 if (sym.st_value == 0 && lte->plt_stub_vma != 0) { 763 pltt = LS_TOPLT_EXEC; 764 addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i; 765 } 766 else { 767 pltt = PLTS_ARE_EXECUTABLE(lte) 768 ? LS_TOPLT_EXEC : LS_TOPLT_POINT; 769 addr = arch_plt_sym_val(lte, i, &rela); 770 } 771 772 add_library_symbol(addr, name, &library_symbols, pltt, 773 ELF64_ST_BIND(sym.st_info) == STB_WEAK); 774 if (!lib_tail) 775 lib_tail = &(library_symbols->next); 776 } 777 } 778#endif // !__mips__ 779 } else { 780 lib_tail = &library_symbols; 781 } 782 783 for (i = 0; i < lte->symtab_count; ++i) { 784 GElf_Sym sym; 785 GElf_Addr addr; 786 const char *name; 787 788 if (gelf_getsym(lte->symtab, i, &sym) == NULL) 789 error(EXIT_FAILURE, 0, 790 "Couldn't get symbol from \"%s\"", 791 proc->filename); 792 793 name = lte->strtab + sym.st_name; 794 addr = sym.st_value; 795 if (!addr) 796 continue; 797 798 for (xptr = opt_x_loc; xptr; xptr = xptr->next) 799 if (xptr->name && strcmp(xptr->name, name) == 0) { 800 /* FIXME: Should be able to use &library_symbols as above. But 801 when you do, none of the real library symbols cause breaks. */ 802 add_library_symbol(opd2addr(lte, addr), 803 name, lib_tail, LS_TOPLT_NONE, 0); 804 xptr->found = 1; 805 break; 806 } 807 } 808 809 unsigned found_count = 0; 810 811 for (xptr = opt_x_loc; xptr; xptr = xptr->next) { 812 if (xptr->found) 813 continue; 814 815 GElf_Sym sym; 816 GElf_Addr addr; 817 if (in_load_libraries(xptr->name, lte, library_num+1, &sym)) { 818 debug(2, "found symbol %s @ %#" PRIx64 ", adding it.", 819 xptr->name, sym.st_value); 820 addr = sym.st_value; 821 if (ELF32_ST_TYPE (sym.st_info) == STT_FUNC) { 822 add_library_symbol(addr, xptr->name, lib_tail, LS_TOPLT_NONE, 0); 823 xptr->found = 1; 824 found_count++; 825 } 826 } 827 if (found_count == opt_x_cnt){ 828 debug(2, "done, found everything: %d\n", found_count); 829 break; 830 } 831 } 832 833 if (lte->ehdr.e_entry != 0) { 834 *entryp = opd2addr(lte, lte->ehdr.e_entry); 835 } else { 836 } 837 838 for (xptr = opt_x_loc; xptr; xptr = xptr->next) 839 if ( ! xptr->found) { 840 char *badthing = "WARNING"; 841#ifdef PLT_REINITALISATION_BP 842 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) { 843 if (lte->ehdr.e_entry) { 844 fprintf (stderr, "WARNING: Using e_ent" 845 "ry from elf header (%p) for " 846 "address of \"%s\"\n", (void*) 847 (long) lte->ehdr.e_entry, 848 PLTs_initialized_by_here); 849 continue; 850 } 851 badthing = "ERROR"; 852 exit_out = 1; 853 } 854#endif 855 fprintf (stderr, 856 "%s: Couldn't find symbol \"%s\" in file \"%s\" assuming it will be loaded by libdl!" 857 "\n", badthing, xptr->name, proc->filename); 858 } 859 if (exit_out) { 860 exit (1); 861 } 862 863 for (i = 0; i < library_num + 1; ++i) 864 do_close_elf(<e[i]); 865 866 return library_symbols; 867} 868