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