proc_sym.c revision 269885
155682Smarkm/*- 2233294Sstas * Copyright (c) 2010 The FreeBSD Foundation 3233294Sstas * Copyright (c) 2008 John Birrell (jb@freebsd.org) 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Portions of this software were developed by Rui Paulo under sponsorship 7233294Sstas * from the FreeBSD Foundation. 8233294Sstas * 955682Smarkm * Redistribution and use in source and binary forms, with or without 10233294Sstas * modification, are permitted provided that the following conditions 11233294Sstas * are met: 1255682Smarkm * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 14233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 15233294Sstas * notice, this list of conditions and the following disclaimer in the 1655682Smarkm * documentation and/or other materials provided with the distribution. 17233294Sstas * 18233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2055682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28233294Sstas * SUCH DAMAGE. 29233294Sstas * 30233294Sstas * $FreeBSD: stable/10/lib/libproc/proc_sym.c 269885 2014-08-12 17:56:48Z dim $ 31233294Sstas */ 3255682Smarkm 3355682Smarkm#include <sys/types.h> 3455682Smarkm#include <sys/user.h> 3555682Smarkm 3655682Smarkm#include <assert.h> 3755682Smarkm#include <err.h> 3855682Smarkm#include <stdio.h> 39178825Sdfr#include <libgen.h> 4055682Smarkm#include <string.h> 4155682Smarkm#include <stdlib.h> 4255682Smarkm#include <fcntl.h> 4355682Smarkm#include <string.h> 4455682Smarkm#include <unistd.h> 4555682Smarkm#include <libutil.h> 4655682Smarkm 4755682Smarkm#include "_libproc.h" 4855682Smarkm 4955682Smarkm#ifndef NO_CXA_DEMANGLE 5055682Smarkmextern char *__cxa_demangle(const char *, char *, size_t *, int *); 5155682Smarkm#endif /* NO_CXA_DEMANGLE */ 5255682Smarkm 5355682Smarkmstatic void proc_rdl2prmap(rd_loadobj_t *, prmap_t *); 5455682Smarkm 5555682Smarkmstatic void 5655682Smarkmdemangle(const char *symbol, char *buf, size_t len) 5755682Smarkm{ 5855682Smarkm#ifndef NO_CXA_DEMANGLE 5955682Smarkm char *dembuf; 6055682Smarkm 6155682Smarkm if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) { 6255682Smarkm dembuf = __cxa_demangle(symbol, NULL, NULL, NULL); 6355682Smarkm if (!dembuf) 6455682Smarkm goto fail; 6555682Smarkm strlcpy(buf, dembuf, len); 6655682Smarkm free(dembuf); 6755682Smarkm return; 6855682Smarkm } 6955682Smarkmfail: 7055682Smarkm#endif /* NO_CXA_DEMANGLE */ 7155682Smarkm strlcpy(buf, symbol, len); 7255682Smarkm} 73233294Sstas 7455682Smarkmstatic void 7555682Smarkmproc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map) 7655682Smarkm{ 7755682Smarkm map->pr_vaddr = rdl->rdl_saddr; 7855682Smarkm map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr; 7955682Smarkm map->pr_offset = rdl->rdl_offset; 8055682Smarkm map->pr_mflags = 0; 8155682Smarkm if (rdl->rdl_prot & RD_RDL_R) 8255682Smarkm map->pr_mflags |= MA_READ; 83233294Sstas if (rdl->rdl_prot & RD_RDL_W) 8478527Sassar map->pr_mflags |= MA_WRITE; 8578527Sassar if (rdl->rdl_prot & RD_RDL_X) 8655682Smarkm map->pr_mflags |= MA_EXEC; 8755682Smarkm strlcpy(map->pr_mapname, rdl->rdl_path, 8855682Smarkm sizeof(map->pr_mapname)); 8955682Smarkm} 9055682Smarkm 9155682Smarkmchar * 9255682Smarkmproc_objname(struct proc_handle *p, uintptr_t addr, char *objname, 9355682Smarkm size_t objnamesz) 9455682Smarkm{ 9555682Smarkm size_t i; 9655682Smarkm rd_loadobj_t *rdl; 9755682Smarkm 9855682Smarkm for (i = 0; i < p->nobjs; i++) { 9955682Smarkm rdl = &p->rdobjs[i]; 10055682Smarkm if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { 10155682Smarkm strlcpy(objname, rdl->rdl_path, objnamesz); 10255682Smarkm return (objname); 10355682Smarkm } 10455682Smarkm } 10555682Smarkm return (NULL); 10655682Smarkm} 10755682Smarkm 10855682Smarkmprmap_t * 10955682Smarkmproc_obj2map(struct proc_handle *p, const char *objname) 11055682Smarkm{ 11155682Smarkm size_t i; 11255682Smarkm prmap_t *map; 11355682Smarkm rd_loadobj_t *rdl; 11455682Smarkm char path[MAXPATHLEN]; 11555682Smarkm 11655682Smarkm for (i = 0; i < p->nobjs; i++) { 11755682Smarkm rdl = &p->rdobjs[i]; 11855682Smarkm basename_r(rdl->rdl_path, path); 11955682Smarkm if (strcmp(path, objname) == 0) { 12055682Smarkm if ((map = malloc(sizeof(*map))) == NULL) 12155682Smarkm return (NULL); 12255682Smarkm proc_rdl2prmap(rdl, map); 12355682Smarkm return (map); 12455682Smarkm } 12555682Smarkm } 12655682Smarkm return (NULL); 12755682Smarkm} 12855682Smarkm 12955682Smarkmint 13055682Smarkmproc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd) 13155682Smarkm{ 13255682Smarkm size_t i; 13355682Smarkm rd_loadobj_t *rdl; 13455682Smarkm prmap_t map; 13555682Smarkm char path[MAXPATHLEN]; 13655682Smarkm char last[MAXPATHLEN]; 13755682Smarkm 13855682Smarkm if (p->nobjs == 0) 13955682Smarkm return (-1); 14055682Smarkm memset(last, 0, sizeof(last)); 14155682Smarkm for (i = 0; i < p->nobjs; i++) { 14255682Smarkm rdl = &p->rdobjs[i]; 14355682Smarkm proc_rdl2prmap(rdl, &map); 14455682Smarkm basename_r(rdl->rdl_path, path); 14555682Smarkm /* 14655682Smarkm * We shouldn't call the callback twice with the same object. 14755682Smarkm * To do that we are assuming the fact that if there are 14855682Smarkm * repeated object names (i.e. different mappings for the 14955682Smarkm * same object) they occur next to each other. 15055682Smarkm */ 15155682Smarkm if (strcmp(path, last) == 0) 152233294Sstas continue; 15355682Smarkm (*func)(cd, &map, path); 15455682Smarkm strlcpy(last, path, sizeof(last)); 15555682Smarkm } 15655682Smarkm 15755682Smarkm return (0); 15855682Smarkm} 15955682Smarkm 16055682Smarkmprmap_t * 16155682Smarkmproc_addr2map(struct proc_handle *p, uintptr_t addr) 16255682Smarkm{ 16355682Smarkm size_t i; 16455682Smarkm int cnt, lastvn = 0; 16555682Smarkm prmap_t *map; 16655682Smarkm rd_loadobj_t *rdl; 16755682Smarkm struct kinfo_vmentry *kves, *kve; 16855682Smarkm 16955682Smarkm /* 17055682Smarkm * If we don't have a cache of listed objects, we need to query 17155682Smarkm * it ourselves. 17255682Smarkm */ 17355682Smarkm if (p->nobjs == 0) { 17455682Smarkm if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL) 17555682Smarkm return (NULL); 17655682Smarkm for (i = 0; i < (size_t)cnt; i++) { 17755682Smarkm kve = kves + i; 178233294Sstas if (kve->kve_type == KVME_TYPE_VNODE) 17955682Smarkm lastvn = i; 18055682Smarkm if (addr >= kve->kve_start && addr < kve->kve_end) { 18155682Smarkm if ((map = malloc(sizeof(*map))) == NULL) { 18255682Smarkm free(kves); 18355682Smarkm return (NULL); 18455682Smarkm } 18555682Smarkm map->pr_vaddr = kve->kve_start; 18655682Smarkm map->pr_size = kve->kve_end - kve->kve_start; 18755682Smarkm map->pr_offset = kve->kve_offset; 18855682Smarkm map->pr_mflags = 0; 18955682Smarkm if (kve->kve_protection & KVME_PROT_READ) 19090926Snectar map->pr_mflags |= MA_READ; 19155682Smarkm if (kve->kve_protection & KVME_PROT_WRITE) 192178825Sdfr map->pr_mflags |= MA_WRITE; 193178825Sdfr if (kve->kve_protection & KVME_PROT_EXEC) 19455682Smarkm map->pr_mflags |= MA_EXEC; 19555682Smarkm if (kve->kve_flags & KVME_FLAG_COW) 19655682Smarkm map->pr_mflags |= MA_COW; 19790926Snectar if (kve->kve_flags & KVME_FLAG_NEEDS_COPY) 19855682Smarkm map->pr_mflags |= MA_NEEDS_COPY; 19955682Smarkm if (kve->kve_flags & KVME_FLAG_NOCOREDUMP) 20055682Smarkm map->pr_mflags |= MA_NOCOREDUMP; 20155682Smarkm strlcpy(map->pr_mapname, kves[lastvn].kve_path, 20255682Smarkm sizeof(map->pr_mapname)); 203178825Sdfr free(kves); 20455682Smarkm return (map); 205178825Sdfr } 206178825Sdfr } 20755682Smarkm free(kves); 208178825Sdfr return (NULL); 20990926Snectar } 21090926Snectar 211233294Sstas for (i = 0; i < p->nobjs; i++) { 212178825Sdfr rdl = &p->rdobjs[i]; 213178825Sdfr if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { 214178825Sdfr if ((map = malloc(sizeof(*map))) == NULL) 215178825Sdfr return (NULL); 216178825Sdfr proc_rdl2prmap(rdl, map); 217178825Sdfr return (map); 21855682Smarkm } 21955682Smarkm } 22055682Smarkm return (NULL); 22155682Smarkm} 22255682Smarkm 22355682Smarkmint 22455682Smarkmproc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name, 225178825Sdfr size_t namesz, GElf_Sym *symcopy) 22655682Smarkm{ 22755682Smarkm Elf *e; 228178825Sdfr Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; 229178825Sdfr Elf_Data *data; 23055682Smarkm GElf_Shdr shdr; 23155682Smarkm GElf_Sym sym; 23255682Smarkm GElf_Ehdr ehdr; 23355682Smarkm int fd, error = -1; 23455682Smarkm size_t i; 23555682Smarkm uint64_t rsym; 23655682Smarkm prmap_t *map; 23755682Smarkm char *s; 23855682Smarkm unsigned long symtabstridx = 0, dynsymstridx = 0; 23955682Smarkm 24055682Smarkm if ((map = proc_addr2map(p, addr)) == NULL) 24155682Smarkm return (-1); 24255682Smarkm if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) { 24355682Smarkm DPRINTF("ERROR: open %s failed", map->pr_mapname); 24455682Smarkm goto err0; 24555682Smarkm } 24655682Smarkm if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 24755682Smarkm DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 248233294Sstas goto err1; 24955682Smarkm } 25055682Smarkm if (gelf_getehdr(e, &ehdr) == NULL) { 25155682Smarkm DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 25255682Smarkm goto err2; 25355682Smarkm } 25455682Smarkm /* 25555682Smarkm * Find the index of the STRTAB and SYMTAB sections to locate 25655682Smarkm * symbol names. 257233294Sstas */ 25855682Smarkm scn = NULL; 25955682Smarkm while ((scn = elf_nextscn(e, scn)) != NULL) { 26055682Smarkm gelf_getshdr(scn, &shdr); 26155682Smarkm switch (shdr.sh_type) { 26255682Smarkm case SHT_SYMTAB: 26355682Smarkm symtabscn = scn; 26455682Smarkm symtabstridx = shdr.sh_link; 26555682Smarkm break; 266233294Sstas case SHT_DYNSYM: 26755682Smarkm dynsymscn = scn; 26855682Smarkm dynsymstridx = shdr.sh_link; 26955682Smarkm break; 270233294Sstas default: 27155682Smarkm break; 27255682Smarkm } 27355682Smarkm } 27455682Smarkm /* 27555682Smarkm * Iterate over the Dynamic Symbols table to find the symbol. 27655682Smarkm * Then look up the string name in STRTAB (.dynstr) 27755682Smarkm */ 27855682Smarkm if ((data = elf_getdata(dynsymscn, NULL)) == NULL) { 27955682Smarkm DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 28055682Smarkm goto symtab; 28155682Smarkm } 28255682Smarkm i = 0; 28355682Smarkm while (gelf_getsym(data, i++, &sym) != NULL) { 28455682Smarkm /* 28555682Smarkm * Calculate the address mapped to the virtual memory 28655682Smarkm * by rtld. 28755682Smarkm */ 28855682Smarkm if (ehdr.e_type != ET_EXEC) 28955682Smarkm rsym = map->pr_vaddr + sym.st_value; 29055682Smarkm else 291233294Sstas rsym = sym.st_value; 29255682Smarkm if (addr >= rsym && addr < rsym + sym.st_size) { 29355682Smarkm s = elf_strptr(e, dynsymstridx, sym.st_name); 29455682Smarkm if (s) { 29555682Smarkm demangle(s, name, namesz); 29655682Smarkm memcpy(symcopy, &sym, sizeof(sym)); 29755682Smarkm /* 29855682Smarkm * DTrace expects the st_value to contain 29955682Smarkm * only the address relative to the start of 300178825Sdfr * the function. 30155682Smarkm */ 30255682Smarkm symcopy->st_value = rsym; 30355682Smarkm error = 0; 30455682Smarkm goto out; 30555682Smarkm } 30655682Smarkm } 30755682Smarkm } 30855682Smarkmsymtab: 30955682Smarkm /* 31055682Smarkm * Iterate over the Symbols Table to find the symbol. 311233294Sstas * Then look up the string name in STRTAB (.dynstr) 31255682Smarkm */ 31355682Smarkm if ((data = elf_getdata(symtabscn, NULL)) == NULL) { 31455682Smarkm DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 31555682Smarkm goto err2; 31655682Smarkm } 31755682Smarkm i = 0; 31855682Smarkm while (gelf_getsym(data, i++, &sym) != NULL) { 31955682Smarkm /* 320233294Sstas * Calculate the address mapped to the virtual memory 32155682Smarkm * by rtld. 32255682Smarkm */ 32355682Smarkm if (ehdr.e_type != ET_EXEC) 32455682Smarkm rsym = map->pr_vaddr + sym.st_value; 32555682Smarkm else 32655682Smarkm rsym = sym.st_value; 32755682Smarkm if (addr >= rsym && addr < rsym + sym.st_size) { 328 s = elf_strptr(e, symtabstridx, sym.st_name); 329 if (s) { 330 demangle(s, name, namesz); 331 memcpy(symcopy, &sym, sizeof(sym)); 332 /* 333 * DTrace expects the st_value to contain 334 * only the address relative to the start of 335 * the function. 336 */ 337 symcopy->st_value = rsym; 338 error = 0; 339 goto out; 340 } 341 } 342 } 343out: 344err2: 345 elf_end(e); 346err1: 347 close(fd); 348err0: 349 free(map); 350 return (error); 351} 352 353prmap_t * 354proc_name2map(struct proc_handle *p, const char *name) 355{ 356 size_t i; 357 int cnt; 358 prmap_t *map; 359 char tmppath[MAXPATHLEN]; 360 struct kinfo_vmentry *kves, *kve; 361 rd_loadobj_t *rdl; 362 363 /* 364 * If we haven't iterated over the list of loaded objects, 365 * librtld_db isn't yet initialized and it's very likely 366 * that librtld_db called us. We need to do the heavy 367 * lifting here to find the symbol librtld_db is looking for. 368 */ 369 if (p->nobjs == 0) { 370 if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) 371 return (NULL); 372 for (i = 0; i < (size_t)cnt; i++) { 373 kve = kves + i; 374 basename_r(kve->kve_path, tmppath); 375 if (strcmp(tmppath, name) == 0) { 376 map = proc_addr2map(p, kve->kve_start); 377 free(kves); 378 return (map); 379 } 380 } 381 free(kves); 382 return (NULL); 383 } 384 if (name == NULL || strcmp(name, "a.out") == 0) { 385 map = proc_addr2map(p, p->rdobjs[0].rdl_saddr); 386 return (map); 387 } 388 for (i = 0; i < p->nobjs; i++) { 389 rdl = &p->rdobjs[i]; 390 basename_r(rdl->rdl_path, tmppath); 391 if (strcmp(tmppath, name) == 0) { 392 if ((map = malloc(sizeof(*map))) == NULL) 393 return (NULL); 394 proc_rdl2prmap(rdl, map); 395 return (map); 396 } 397 } 398 399 return (NULL); 400} 401 402int 403proc_name2sym(struct proc_handle *p, const char *object, const char *symbol, 404 GElf_Sym *symcopy) 405{ 406 Elf *e; 407 Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; 408 Elf_Data *data; 409 GElf_Shdr shdr; 410 GElf_Sym sym; 411 GElf_Ehdr ehdr; 412 int fd, error = -1; 413 size_t i; 414 prmap_t *map; 415 char *s; 416 unsigned long symtabstridx = 0, dynsymstridx = 0; 417 418 if ((map = proc_name2map(p, object)) == NULL) { 419 DPRINTFX("ERROR: couldn't find object %s", object); 420 goto err0; 421 } 422 if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) { 423 DPRINTF("ERROR: open %s failed", map->pr_mapname); 424 goto err0; 425 } 426 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 427 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 428 goto err1; 429 } 430 if (gelf_getehdr(e, &ehdr) == NULL) { 431 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 432 goto err2; 433 } 434 /* 435 * Find the index of the STRTAB and SYMTAB sections to locate 436 * symbol names. 437 */ 438 scn = NULL; 439 while ((scn = elf_nextscn(e, scn)) != NULL) { 440 gelf_getshdr(scn, &shdr); 441 switch (shdr.sh_type) { 442 case SHT_SYMTAB: 443 symtabscn = scn; 444 symtabstridx = shdr.sh_link; 445 break; 446 case SHT_DYNSYM: 447 dynsymscn = scn; 448 dynsymstridx = shdr.sh_link; 449 break; 450 default: 451 break; 452 } 453 } 454 /* 455 * Iterate over the Dynamic Symbols table to find the symbol. 456 * Then look up the string name in STRTAB (.dynstr) 457 */ 458 if ((data = elf_getdata(dynsymscn, NULL))) { 459 i = 0; 460 while (gelf_getsym(data, i++, &sym) != NULL) { 461 s = elf_strptr(e, dynsymstridx, sym.st_name); 462 if (s && strcmp(s, symbol) == 0) { 463 memcpy(symcopy, &sym, sizeof(sym)); 464 if (ehdr.e_type != ET_EXEC) 465 symcopy->st_value += map->pr_vaddr; 466 error = 0; 467 goto out; 468 } 469 } 470 } 471 /* 472 * Iterate over the Symbols Table to find the symbol. 473 * Then look up the string name in STRTAB (.dynstr) 474 */ 475 if ((data = elf_getdata(symtabscn, NULL))) { 476 i = 0; 477 while (gelf_getsym(data, i++, &sym) != NULL) { 478 s = elf_strptr(e, symtabstridx, sym.st_name); 479 if (s && strcmp(s, symbol) == 0) { 480 memcpy(symcopy, &sym, sizeof(sym)); 481 if (ehdr.e_type != ET_EXEC) 482 symcopy->st_value += map->pr_vaddr; 483 error = 0; 484 goto out; 485 } 486 } 487 } 488out: 489 DPRINTFX("found addr 0x%lx for %s", symcopy->st_value, symbol); 490err2: 491 elf_end(e); 492err1: 493 close(fd); 494err0: 495 free(map); 496 497 return (error); 498} 499 500 501int 502proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which, 503 int mask, proc_sym_f *func, void *cd) 504{ 505 Elf *e; 506 int i, fd; 507 prmap_t *map; 508 Elf_Scn *scn, *foundscn = NULL; 509 Elf_Data *data; 510 GElf_Ehdr ehdr; 511 GElf_Shdr shdr; 512 GElf_Sym sym; 513 unsigned long stridx = -1; 514 char *s; 515 int error = -1; 516 517 if ((map = proc_name2map(p, object)) == NULL) 518 return (-1); 519 if ((fd = open(map->pr_mapname, O_RDONLY)) < 0) { 520 DPRINTF("ERROR: open %s failed", map->pr_mapname); 521 goto err0; 522 } 523 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 524 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 525 goto err1; 526 } 527 if (gelf_getehdr(e, &ehdr) == NULL) { 528 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 529 goto err2; 530 } 531 /* 532 * Find the section we are looking for. 533 */ 534 scn = NULL; 535 while ((scn = elf_nextscn(e, scn)) != NULL) { 536 gelf_getshdr(scn, &shdr); 537 if (which == PR_SYMTAB && 538 shdr.sh_type == SHT_SYMTAB) { 539 foundscn = scn; 540 break; 541 } else if (which == PR_DYNSYM && 542 shdr.sh_type == SHT_DYNSYM) { 543 foundscn = scn; 544 break; 545 } 546 } 547 if (!foundscn) 548 return (-1); 549 stridx = shdr.sh_link; 550 if ((data = elf_getdata(foundscn, NULL)) == NULL) { 551 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 552 goto err2; 553 } 554 i = 0; 555 while (gelf_getsym(data, i++, &sym) != NULL) { 556 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL && 557 (mask & BIND_LOCAL) == 0) 558 continue; 559 if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL && 560 (mask & BIND_GLOBAL) == 0) 561 continue; 562 if (GELF_ST_BIND(sym.st_info) == STB_WEAK && 563 (mask & BIND_WEAK) == 0) 564 continue; 565 if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE && 566 (mask & TYPE_NOTYPE) == 0) 567 continue; 568 if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT && 569 (mask & TYPE_OBJECT) == 0) 570 continue; 571 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC && 572 (mask & TYPE_FUNC) == 0) 573 continue; 574 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && 575 (mask & TYPE_SECTION) == 0) 576 continue; 577 if (GELF_ST_TYPE(sym.st_info) == STT_FILE && 578 (mask & TYPE_FILE) == 0) 579 continue; 580 s = elf_strptr(e, stridx, sym.st_name); 581 if (ehdr.e_type != ET_EXEC) 582 sym.st_value += map->pr_vaddr; 583 (*func)(cd, &sym, s); 584 } 585 error = 0; 586err2: 587 elf_end(e); 588err1: 589 close(fd); 590err0: 591 free(map); 592 return (error); 593} 594