ltrace-elf.c revision d5e85569fa3cd1705eca0bd9a4ab79cf908e5faa
1#include "config.h" 2 3#include <assert.h> 4#include <endian.h> 5#include <errno.h> 6#include <error.h> 7#include <fcntl.h> 8#include <gelf.h> 9#include <inttypes.h> 10#include <search.h> 11#include <stdint.h> 12#include <stdlib.h> 13#include <string.h> 14#include <unistd.h> 15 16#include "common.h" 17#include "proc.h" 18#include "library.h" 19#include "filter.h" 20 21#ifdef PLT_REINITALISATION_BP 22extern char *PLTs_initialized_by_here; 23#endif 24 25#ifndef DT_PPC_GOT 26# define DT_PPC_GOT (DT_LOPROC + 0) 27#endif 28 29 30#ifndef ARCH_HAVE_LTELF_DATA 31int 32arch_elf_init(struct ltelf *lte) 33{ 34 return 0; 35} 36 37void 38arch_elf_destroy(struct ltelf *lte) 39{ 40} 41#endif 42 43int 44default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, 45 const char *a_name, GElf_Rela *rela, size_t ndx, 46 struct library_symbol **ret) 47{ 48 char *name = strdup(a_name); 49 if (name == NULL) { 50 fail: 51 free(name); 52 return -1; 53 } 54 55 enum toplt pltt = PLTS_ARE_EXECUTABLE(lte) 56 ? LS_TOPLT_EXEC : LS_TOPLT_POINT; 57 GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela); 58 59 struct library_symbol *libsym = malloc(sizeof(*libsym)); 60 if (libsym == NULL) 61 goto fail; 62 63 target_address_t taddr = (target_address_t)(addr + lte->bias); 64 65 /* The logic behind this conditional translation is as 66 * follows. PLT entries do not typically need custom TOC 67 * pointer, and therefore aren't redirected via OPD. POINT 68 * PLT, on the other hand, most likely contains addresses of 69 * target functions, not PLT entries themselves, and would 70 * need the OPD redirection. */ 71 if (pltt == LS_TOPLT_POINT 72 && arch_translate_address(proc, taddr, &taddr) < 0) { 73 free(libsym); 74 goto fail; 75 } 76 77 library_symbol_init(libsym, taddr, name, 1, pltt); 78 *ret = libsym; 79 return 0; 80} 81 82#ifndef ARCH_HAVE_ADD_PLT_ENTRY 83enum plt_status 84arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, 85 const char *a_name, GElf_Rela *rela, size_t ndx, 86 struct library_symbol **ret) 87{ 88 return plt_default; 89} 90#endif 91 92Elf_Data * 93elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr) 94{ 95 Elf_Data *data = elf_getdata(scn, NULL); 96 if (data == NULL || elf_getdata(scn, data) != NULL 97 || data->d_off || data->d_size != shdr->sh_size) 98 return NULL; 99 return data; 100} 101 102static int 103elf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr, 104 int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data), 105 void *data) 106{ 107 int i; 108 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 109 Elf_Scn *scn; 110 GElf_Shdr shdr; 111 112 scn = elf_getscn(lte->elf, i); 113 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) { 114 debug(1, "Couldn't read section or header."); 115 return -1; 116 } 117 if (predicate(scn, &shdr, data)) { 118 *tgt_sec = scn; 119 *tgt_shdr = shdr; 120 return 0; 121 } 122 } 123 return -1; 124 125} 126 127static int 128inside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data) 129{ 130 GElf_Addr addr = *(GElf_Addr *)data; 131 return addr >= shdr->sh_addr 132 && addr < shdr->sh_addr + shdr->sh_size; 133} 134 135int 136elf_get_section_covering(struct ltelf *lte, GElf_Addr addr, 137 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 138{ 139 return elf_get_section_if(lte, tgt_sec, tgt_shdr, 140 &inside_p, &addr); 141} 142 143static int 144type_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data) 145{ 146 GElf_Word type = *(GElf_Word *)data; 147 return shdr->sh_type == type; 148} 149 150int 151elf_get_section_type(struct ltelf *lte, GElf_Word type, 152 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr) 153{ 154 return elf_get_section_if(lte, tgt_sec, tgt_shdr, 155 &type_p, &type); 156} 157 158static int 159need_data(Elf_Data *data, size_t offset, size_t size) 160{ 161 assert(data != NULL); 162 if (data->d_size < size || offset > data->d_size - size) { 163 debug(1, "Not enough data to read %zd-byte value" 164 " at offset %zd.", size, offset); 165 return -1; 166 } 167 return 0; 168} 169 170#define DEF_READER(NAME, SIZE) \ 171 int \ 172 NAME(Elf_Data *data, size_t offset, uint##SIZE##_t *retp) \ 173 { \ 174 if (!need_data(data, offset, SIZE / 8) < 0) \ 175 return -1; \ 176 \ 177 if (data->d_buf == NULL) /* NODATA section */ { \ 178 *retp = 0; \ 179 return 0; \ 180 } \ 181 \ 182 union { \ 183 uint##SIZE##_t dst; \ 184 char buf[0]; \ 185 } u; \ 186 memcpy(u.buf, data->d_buf + offset, sizeof(u.dst)); \ 187 *retp = u.dst; \ 188 return 0; \ 189 } 190 191DEF_READER(elf_read_u16, 16) 192DEF_READER(elf_read_u32, 32) 193DEF_READER(elf_read_u64, 64) 194 195#undef DEF_READER 196 197int 198open_elf(struct ltelf *lte, const char *filename) 199{ 200 lte->fd = open(filename, O_RDONLY); 201 if (lte->fd == -1) 202 return 1; 203 204 elf_version(EV_CURRENT); 205 206#ifdef HAVE_ELF_C_READ_MMAP 207 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL); 208#else 209 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL); 210#endif 211 212 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) 213 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename); 214 215 if (gelf_getehdr(lte->elf, <e->ehdr) == NULL) 216 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", 217 filename); 218 219 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) 220 error(EXIT_FAILURE, 0, 221 "\"%s\" is not an ELF executable nor shared library", 222 filename); 223 224 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS 225 || lte->ehdr.e_machine != LT_ELF_MACHINE) 226#ifdef LT_ELF_MACHINE2 227 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2 228 || lte->ehdr.e_machine != LT_ELF_MACHINE2) 229#endif 230#ifdef LT_ELF_MACHINE3 231 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3 232 || lte->ehdr.e_machine != LT_ELF_MACHINE3) 233#endif 234 ) 235 error(EXIT_FAILURE, 0, 236 "\"%s\" is ELF from incompatible architecture", filename); 237 238 return 0; 239} 240 241static int 242do_init_elf(struct ltelf *lte, const char *filename, GElf_Addr bias) 243{ 244 int i; 245 GElf_Addr relplt_addr = 0; 246 GElf_Addr soname_offset = 0; 247 248 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename); 249 debug(1, "Reading ELF from %s...", filename); 250 251 if (open_elf(lte, filename) < 0) 252 return -1; 253 254 /* Find out the base address. */ 255 { 256 GElf_Phdr phdr; 257 for (i = 0; gelf_getphdr (lte->elf, i, &phdr) != NULL; ++i) { 258 if (phdr.p_type == PT_LOAD) { 259 lte->base_addr = phdr.p_vaddr + bias; 260 fprintf(stderr, 261 " + vaddr=%#lx, bias=%#lx, base=%#lx\n", 262 phdr.p_vaddr, bias, lte->base_addr); 263 break; 264 } 265 } 266 } 267 268 if (lte->base_addr == 0) { 269 fprintf(stderr, "Couldn't determine base address of %s\n", 270 filename); 271 return -1; 272 } 273 274 lte->bias = bias; 275 lte->entry_addr = lte->ehdr.e_entry + lte->bias; 276 277 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 278 Elf_Scn *scn; 279 GElf_Shdr shdr; 280 const char *name; 281 282 scn = elf_getscn(lte->elf, i); 283 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 284 error(EXIT_FAILURE, 0, 285 "Couldn't get section header from \"%s\"", 286 filename); 287 288 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name); 289 if (name == NULL) 290 error(EXIT_FAILURE, 0, 291 "Couldn't get section header from \"%s\"", 292 filename); 293 294 if (shdr.sh_type == SHT_SYMTAB) { 295 Elf_Data *data; 296 297 lte->symtab = elf_getdata(scn, NULL); 298 lte->symtab_count = shdr.sh_size / shdr.sh_entsize; 299 if ((lte->symtab == NULL 300 || elf_getdata(scn, lte->symtab) != NULL) 301 && options.static_filter != NULL) 302 error(EXIT_FAILURE, 0, 303 "Couldn't get .symtab data from \"%s\"", 304 filename); 305 306 scn = elf_getscn(lte->elf, shdr.sh_link); 307 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 308 error(EXIT_FAILURE, 0, 309 "Couldn't get section header from \"%s\"", 310 filename); 311 312 data = elf_getdata(scn, NULL); 313 if (data == NULL || elf_getdata(scn, data) != NULL 314 || shdr.sh_size != data->d_size || data->d_off) 315 error(EXIT_FAILURE, 0, 316 "Couldn't get .strtab data from \"%s\"", 317 filename); 318 319 lte->strtab = data->d_buf; 320 } else if (shdr.sh_type == SHT_DYNSYM) { 321 Elf_Data *data; 322 323 lte->dynsym = elf_getdata(scn, NULL); 324 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize; 325 if (lte->dynsym == NULL 326 || elf_getdata(scn, lte->dynsym) != NULL) 327 error(EXIT_FAILURE, 0, 328 "Couldn't get .dynsym data from \"%s\"", 329 filename); 330 331 scn = elf_getscn(lte->elf, shdr.sh_link); 332 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 333 error(EXIT_FAILURE, 0, 334 "Couldn't get section header from \"%s\"", 335 filename); 336 337 data = elf_getdata(scn, NULL); 338 if (data == NULL || elf_getdata(scn, data) != NULL 339 || shdr.sh_size != data->d_size || data->d_off) 340 error(EXIT_FAILURE, 0, 341 "Couldn't get .dynstr data from \"%s\"", 342 filename); 343 344 lte->dynstr = data->d_buf; 345 } else if (shdr.sh_type == SHT_DYNAMIC) { 346 Elf_Data *data; 347 size_t j; 348 349 lte->dyn_addr = shdr.sh_addr; 350 fprintf(stderr, "dyn_addr = %#lx\n", lte->dyn_addr); 351 lte->dyn_sz = shdr.sh_size; 352 353 data = elf_getdata(scn, NULL); 354 if (data == NULL || elf_getdata(scn, data) != NULL) 355 error(EXIT_FAILURE, 0, 356 "Couldn't get .dynamic data from \"%s\"", 357 filename); 358 359 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 360 GElf_Dyn dyn; 361 362 if (gelf_getdyn(data, j, &dyn) == NULL) 363 error(EXIT_FAILURE, 0, 364 "Couldn't get .dynamic data from \"%s\"", 365 filename); 366 if (dyn.d_tag == DT_JMPREL) 367 relplt_addr = dyn.d_un.d_ptr; 368 else if (dyn.d_tag == DT_PLTRELSZ) 369 lte->relplt_size = dyn.d_un.d_val; 370 else if (dyn.d_tag == DT_SONAME) 371 soname_offset = dyn.d_un.d_val; 372 } 373 } else if (shdr.sh_type == SHT_PROGBITS 374 || shdr.sh_type == SHT_NOBITS) { 375 if (strcmp(name, ".plt") == 0) { 376 lte->plt_addr = shdr.sh_addr; 377 lte->plt_size = shdr.sh_size; 378 lte->plt_data = elf_loaddata(scn, &shdr); 379 if (lte->plt_data == NULL) 380 fprintf(stderr, 381 "Can't load .plt data\n"); 382 if (shdr.sh_flags & SHF_EXECINSTR) 383 lte->lte_flags |= LTE_PLT_EXECUTABLE; 384 } 385#ifdef ARCH_SUPPORTS_OPD 386 else if (strcmp(name, ".opd") == 0) { 387 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr; 388 lte->opd_size = shdr.sh_size; 389 lte->opd = elf_rawdata(scn, NULL); 390 } 391#endif 392 } 393 } 394 395 if (lte->dynsym == NULL || lte->dynstr == NULL) 396 error(EXIT_FAILURE, 0, 397 "Couldn't find .dynsym or .dynstr in \"%s\"", filename); 398 399 if (!relplt_addr || !lte->plt_addr) { 400 debug(1, "%s has no PLT relocations", filename); 401 lte->relplt = NULL; 402 lte->relplt_count = 0; 403 } else if (lte->relplt_size == 0) { 404 debug(1, "%s has unknown PLT size", filename); 405 lte->relplt = NULL; 406 lte->relplt_count = 0; 407 } else { 408 409 for (i = 1; i < lte->ehdr.e_shnum; ++i) { 410 Elf_Scn *scn; 411 GElf_Shdr shdr; 412 413 scn = elf_getscn(lte->elf, i); 414 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) 415 error(EXIT_FAILURE, 0, 416 "Couldn't get section header from \"%s\"", 417 filename); 418 if (shdr.sh_addr == relplt_addr 419 && shdr.sh_size == lte->relplt_size) { 420 lte->relplt = elf_getdata(scn, NULL); 421 lte->relplt_count = 422 shdr.sh_size / shdr.sh_entsize; 423 if (lte->relplt == NULL 424 || elf_getdata(scn, lte->relplt) != NULL) 425 error(EXIT_FAILURE, 0, 426 "Couldn't get .rel*.plt data from \"%s\"", 427 filename); 428 break; 429 } 430 } 431 432 if (i == lte->ehdr.e_shnum) 433 error(EXIT_FAILURE, 0, 434 "Couldn't find .rel*.plt section in \"%s\"", 435 filename); 436 437 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count); 438 } 439 440 if (soname_offset != 0) 441 lte->soname = lte->dynstr + soname_offset; 442 443 if (arch_elf_init(lte) < 0) { 444 fprintf(stderr, "Backend initialization failed.\n"); 445 return -1; 446 } 447 448 return 0; 449} 450 451/* XXX temporarily non-static */ 452void 453do_close_elf(struct ltelf *lte) { 454 debug(DEBUG_FUNCTION, "do_close_elf()"); 455 arch_elf_destroy(lte); 456 elf_end(lte->elf); 457 close(lte->fd); 458} 459 460static int 461populate_plt(struct Process *proc, const char *filename, 462 struct ltelf *lte, struct library *lib) 463{ 464 size_t i; 465 for (i = 0; i < lte->relplt_count; ++i) { 466 GElf_Rel rel; 467 GElf_Rela rela; 468 GElf_Sym sym; 469 void *ret; 470 471 if (lte->relplt->d_type == ELF_T_REL) { 472 ret = gelf_getrel(lte->relplt, i, &rel); 473 rela.r_offset = rel.r_offset; 474 rela.r_info = rel.r_info; 475 rela.r_addend = 0; 476 } else { 477 ret = gelf_getrela(lte->relplt, i, &rela); 478 } 479 480 if (ret == NULL 481 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count 482 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info), 483 &sym) == NULL) 484 error(EXIT_FAILURE, 0, 485 "Couldn't get relocation from \"%s\"", 486 filename); 487 488 char const *name = lte->dynstr + sym.st_name; 489 490 if (!filter_matches_symbol(options.plt_filter, name, lib)) 491 continue; 492 493 fprintf(stderr, "%s@%s matches\n", name, lib->soname); 494 495 struct library_symbol *libsym; 496 switch (arch_elf_add_plt_entry(proc, lte, name, 497 &rela, i, &libsym)) { 498 case plt_default: 499 if (default_elf_add_plt_entry(proc, lte, name, 500 &rela, i, &libsym) < 0) 501 case plt_fail: 502 return -1; 503 case plt_ok: 504 if (libsym != NULL) 505 library_add_symbol(lib, libsym); 506 } 507 } 508 return 0; 509} 510 511/* When -x rules result in request to trace several aliases, we only 512 * want to add such symbol once. The only way that those symbols 513 * differ in is their name, e.g. in glibc you have __GI___libc_free, 514 * __cfree, __free, __libc_free, cfree and free all defined on the 515 * same address. So instead we keep this unique symbol struct for 516 * each address, and replace name in libsym with a shorter variant if 517 * we find it. */ 518struct unique_symbol { 519 target_address_t addr; 520 struct library_symbol *libsym; 521}; 522 523static int 524unique_symbol_cmp(const void *key, const void *val) 525{ 526 const struct unique_symbol *sym_key = key; 527 const struct unique_symbol *sym_val = val; 528 return sym_key->addr != sym_val->addr; 529} 530 531static int 532populate_this_symtab(struct Process *proc, const char *filename, 533 struct ltelf *lte, struct library *lib, 534 Elf_Data *symtab, const char *strtab, size_t size) 535{ 536 /* Using sorted array would be arguably better, but this 537 * should be well enough for the number of symbols that we 538 * typically deal with. */ 539 size_t num_symbols = 0; 540 struct unique_symbol *symbols = malloc(sizeof(*symbols) * size); 541 if (symbols == NULL) { 542 error(0, errno, "couldn't insert symbols for -x"); 543 return -1; 544 } 545 546 size_t lib_len = strlen(lib->soname); 547 size_t i; 548 for (i = 0; i < size; ++i) { 549 GElf_Sym sym; 550 if (gelf_getsym(lte->symtab, i, &sym) == NULL) { 551 fail: 552 error(0, errno, "couldn't get symbol #%zd from %s: %s", 553 i, filename, elf_errmsg(-1)); 554 continue; 555 } 556 557 /* XXX support IFUNC as well. */ 558 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC 559 || sym.st_value == 0) 560 continue; 561 562 const char *name = strtab + sym.st_name; 563 if (!filter_matches_symbol(options.static_filter, name, lib)) 564 continue; 565 566 target_address_t addr 567 = (target_address_t)(sym.st_value + lte->bias); 568 target_address_t naddr; 569 if (arch_translate_address(proc, addr, &naddr) < 0) { 570 error(0, errno, "couldn't translate address of %s@%s", 571 name, lib->soname); 572 continue; 573 } 574 if (addr != naddr) 575 naddr += lte->bias; 576 577 char *full_name = malloc(strlen(name) + 1 + lib_len + 1); 578 if (full_name == NULL) 579 goto fail; 580 sprintf(full_name, "%s@%s", name, lib->soname); 581 582 /* Look whether we already have a symbol for this 583 * address. If not, add this one. */ 584 struct unique_symbol key = { naddr, NULL }; 585 struct unique_symbol *unique 586 = lsearch(&key, symbols, &num_symbols, 587 sizeof(*symbols), &unique_symbol_cmp); 588 589 if (unique->libsym == NULL) { 590 struct library_symbol *libsym = malloc(sizeof(*libsym)); 591 if (libsym == NULL) { 592 --num_symbols; 593 goto fail; 594 } 595 library_symbol_init(libsym, naddr, full_name, 596 1, LS_TOPLT_NONE); 597 unique->libsym = libsym; 598 unique->addr = naddr; 599 600 } else if (strlen(full_name) < strlen(unique->libsym->name)) { 601 library_symbol_set_name(unique->libsym, full_name, 1); 602 603 } else { 604 free(full_name); 605 } 606 } 607 608 for (i = 0; i < num_symbols; ++i) { 609 assert(symbols[i].libsym != NULL); 610 library_add_symbol(lib, symbols[i].libsym); 611 } 612 613 free(symbols); 614 615 return 0; 616} 617 618static int 619populate_symtab(struct Process *proc, const char *filename, 620 struct ltelf *lte, struct library *lib) 621{ 622 if (lte->symtab != NULL && lte->strtab != NULL) 623 return populate_this_symtab(proc, filename, lte, lib, 624 lte->symtab, lte->strtab, 625 lte->symtab_count); 626 else 627 return populate_this_symtab(proc, filename, lte, lib, 628 lte->dynsym, lte->dynstr, 629 lte->dynsym_count); 630} 631 632int 633ltelf_read_library(struct library *lib, struct Process *proc, 634 const char *filename, GElf_Addr bias) 635{ 636 struct ltelf lte = {}; 637 if (do_init_elf(<e, filename, bias) < 0) 638 return -1; 639 proc->e_machine = lte.ehdr.e_machine; 640 641 int status = 0; 642 if (lib == NULL) 643 goto fail; 644 645 /* Note that we set soname and pathname as soon as they are 646 * allocated, so in case of further errors, this get released 647 * when LIB is release, which should happen in the caller when 648 * we return error. */ 649 650 if (lib->pathname == NULL) { 651 char *pathname = strdup(filename); 652 if (pathname == NULL) 653 goto fail; 654 library_set_pathname(lib, filename, 1); 655 } 656 657 if (lte.soname != NULL) { 658 char *soname = strdup(lte.soname); 659 if (soname == NULL) 660 goto fail; 661 library_set_soname(lib, soname, 1); 662 } else { 663 const char *soname = rindex(lib->pathname, '/') + 1; 664 if (soname == NULL) 665 soname = lib->pathname; 666 library_set_soname(lib, soname, 0); 667 } 668 669 target_address_t entry = (target_address_t)lte.entry_addr; 670 if (arch_translate_address(proc, entry, &entry) < 0) 671 goto fail; 672 673 lib->base = (target_address_t)lte.base_addr; 674 lib->entry = entry; 675 lib->dyn_addr = (target_address_t)lte.dyn_addr; 676 677 if (filter_matches_library(options.plt_filter, lib) 678 && populate_plt(proc, filename, <e, lib) < 0) 679 goto fail; 680 681 if (filter_matches_library(options.static_filter, lib) 682 && populate_symtab(proc, filename, <e, lib) < 0) 683 goto fail; 684 685done: 686 do_close_elf(<e); 687 return status; 688 689fail: 690 status = -1; 691 goto done; 692} 693 694struct library * 695ltelf_read_main_binary(struct Process *proc, const char *path) 696{ 697 struct library *lib = malloc(sizeof(*lib)); 698 if (lib == NULL) 699 return NULL; 700 library_init(lib, LT_LIBTYPE_MAIN); 701 library_set_pathname(lib, path, 0); 702 703 fprintf(stderr, "ltelf_read_main_binary %d %s\n", proc->pid, path); 704 705 /* There is a race between running the process and reading its 706 * binary for internal consumption. So open the binary from 707 * the /proc filesystem. XXX Note that there is similar race 708 * for libraries, but there we don't have a nice answer like 709 * that. Presumably we could read the DSOs from the process 710 * memory image, but that's not currently done. */ 711 char *fname = pid2name(proc->pid); 712 if (ltelf_read_library(lib, proc, fname, 0) < 0) { 713 library_destroy(lib); 714 free(lib); 715 return NULL; 716 } 717 718 return lib; 719} 720