Home | History | Annotate | Line # | Download | only in dist
      1 /*-
      2  * Copyright (c) 2010 The FreeBSD Foundation
      3  * Copyright (c) 2008 John Birrell (jb (at) freebsd.org)
      4  * All rights reserved.
      5  *
      6  * Portions of this software were developed by Rui Paulo under sponsorship
      7  * from the FreeBSD Foundation.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 #ifdef __FBSDID
     33 __FBSDID("$FreeBSD: head/lib/libproc/proc_sym.c 279946 2015-03-13 04:26:48Z stas $");
     34 #else
     35 __RCSID("$NetBSD: proc_sym.c,v 1.6 2024/07/05 09:43:53 rin Exp $");
     36 #endif
     37 
     38 #include <sys/types.h>
     39 #ifndef NO_CTF
     40 #include <sys/ctf.h>
     41 #include <sys/ctf_api.h>
     42 #endif
     43 #if defined(__FreeBSD__)
     44 #include <sys/user.h>
     45 #endif
     46 #include <sys/sysctl.h>
     47 
     48 #include <assert.h>
     49 #include <err.h>
     50 #include <fcntl.h>
     51 #include <libgen.h>
     52 #include <stdio.h>
     53 #include <stdlib.h>
     54 #include <string.h>
     55 #include <unistd.h>
     56 #ifndef NO_CTF
     57 #include <libctf.h>
     58 #endif
     59 #include <util.h>
     60 
     61 #include "_libproc.h"
     62 
     63 #define DBG_PATH_FMT "/usr/libdata/debug/%s.debug"
     64 
     65 #ifdef NO_CTF
     66 typedef struct ctf_file ctf_file_t;
     67 #endif
     68 
     69 #ifndef NO_CXA_DEMANGLE
     70 extern char *__cxa_demangle(const char *, char *, size_t *, int *);
     71 #endif /* NO_CXA_DEMANGLE */
     72 
     73 static void	proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
     74 
     75 #ifdef __NetBSD__
     76 static char *basename_r(const char *path, char *buf)
     77 {
     78 	// We "know" this works.
     79 	if (path[0])
     80 		strlcpy(buf, strrchr(path, '/') + 1, PATH_MAX);
     81 	else
     82 		buf[0] = '\0';
     83 	return buf;
     84 }
     85 #endif
     86 
     87 static void
     88 demangle(const char *symbol, char *buf, size_t len)
     89 {
     90 #ifndef NO_CXA_DEMANGLE
     91 	char *dembuf;
     92 
     93 	if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) {
     94 		dembuf = __cxa_demangle(symbol, NULL, NULL, NULL);
     95 		if (!dembuf)
     96 			goto fail;
     97 		strlcpy(buf, dembuf, len);
     98 		free(dembuf);
     99 		return;
    100 	}
    101 fail:
    102 #endif /* NO_CXA_DEMANGLE */
    103 	strlcpy(buf, symbol, len);
    104 }
    105 
    106 static int
    107 find_dbg_obj(const char *path)
    108 {
    109 	int fd;
    110 	char dbg_path[PATH_MAX];
    111 
    112 	snprintf(dbg_path, sizeof(dbg_path), DBG_PATH_FMT, path);
    113 	fd = open(dbg_path, O_RDONLY);
    114 	if (fd >= 0)
    115 		return (fd);
    116 	else
    117 		return (open(path, O_RDONLY));
    118 }
    119 
    120 static void
    121 proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
    122 {
    123 	map->pr_vaddr = rdl->rdl_saddr;
    124 	map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
    125 	map->pr_offset = rdl->rdl_offset;
    126 	map->pr_mflags = 0;
    127 	if (rdl->rdl_prot & RD_RDL_R)
    128 		map->pr_mflags |= MA_READ;
    129 	if (rdl->rdl_prot & RD_RDL_W)
    130 		map->pr_mflags |= MA_WRITE;
    131 	if (rdl->rdl_prot & RD_RDL_X)
    132 		map->pr_mflags |= MA_EXEC;
    133 	strlcpy(map->pr_mapname, rdl->rdl_path,
    134 	    sizeof(map->pr_mapname));
    135 }
    136 
    137 char *
    138 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
    139     size_t objnamesz)
    140 {
    141 	size_t i;
    142 	rd_loadobj_t *rdl;
    143 
    144 	if (p->nobjs == 0)
    145 		if (proc_rdagent(p) == NULL)
    146 			return (NULL);
    147 
    148 	for (i = 0; i < p->nobjs; i++) {
    149 		rdl = &p->rdobjs[i];
    150 		if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
    151 			strlcpy(objname, rdl->rdl_path, objnamesz);
    152 			return (objname);
    153 		}
    154 	}
    155 	return (NULL);
    156 }
    157 
    158 prmap_t *
    159 proc_obj2map(struct proc_handle *p, const char *objname)
    160 {
    161 	size_t i;
    162 	prmap_t *map;
    163 	rd_loadobj_t *rdl;
    164 	char path[MAXPATHLEN];
    165 
    166 	rdl = NULL;
    167 	for (i = 0; i < p->nobjs; i++) {
    168 		basename_r(p->rdobjs[i].rdl_path, path);
    169 		if (strcmp(path, objname) == 0) {
    170 			rdl = &p->rdobjs[i];
    171 			break;
    172 		}
    173 	}
    174 	if (rdl == NULL) {
    175 		if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
    176 			rdl = p->rdexec;
    177 		else
    178 			return (NULL);
    179 	}
    180 
    181 	if ((map = malloc(sizeof(*map))) == NULL)
    182 		return (NULL);
    183 	proc_rdl2prmap(rdl, map);
    184 	return (map);
    185 }
    186 
    187 int
    188 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd)
    189 {
    190 	size_t i;
    191 	rd_loadobj_t *rdl;
    192 	prmap_t map;
    193 	char path[MAXPATHLEN];
    194 	char last[MAXPATHLEN];
    195 	int error;
    196 
    197 	if (p->nobjs == 0)
    198 		return (-1);
    199 
    200 	error = 0;
    201 	memset(last, 0, sizeof(last));
    202 	for (i = 0; i < p->nobjs; i++) {
    203 		rdl = &p->rdobjs[i];
    204 		proc_rdl2prmap(rdl, &map);
    205 		basename_r(rdl->rdl_path, path);
    206 		/*
    207 		 * We shouldn't call the callback twice with the same object.
    208 		 * To do that we are assuming the fact that if there are
    209 		 * repeated object names (i.e. different mappings for the
    210 		 * same object) they occur next to each other.
    211 		 */
    212 		if (strcmp(path, last) == 0)
    213 			continue;
    214 		if ((error = (*func)(cd, &map, path)) != 0)
    215 			break;
    216 		strlcpy(last, path, sizeof(last));
    217 	}
    218 	return (error);
    219 }
    220 
    221 prmap_t *
    222 proc_addr2map(struct proc_handle *p, uintptr_t addr)
    223 {
    224 	size_t i, cnt, lastvn = 0;
    225 	prmap_t *map;
    226 	rd_loadobj_t *rdl;
    227 	struct kinfo_vmentry *kves, *kve;
    228 
    229 	/*
    230 	 * If we don't have a cache of listed objects, we need to query
    231 	 * it ourselves.
    232 	 */
    233 	if (p->nobjs == 0) {
    234 		if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL)
    235 			return (NULL);
    236 		for (i = 0; i < (size_t)cnt; i++) {
    237 			kve = kves + i;
    238 			if (kve->kve_type == KVME_TYPE_VNODE)
    239 				lastvn = i;
    240 			if (addr >= kve->kve_start && addr < kve->kve_end) {
    241 				if ((map = malloc(sizeof(*map))) == NULL) {
    242 					free(kves);
    243 					return (NULL);
    244 				}
    245 				map->pr_vaddr = kve->kve_start;
    246 				map->pr_size = kve->kve_end - kve->kve_start;
    247 				map->pr_offset = kve->kve_offset;
    248 				map->pr_mflags = 0;
    249 				if (kve->kve_protection & KVME_PROT_READ)
    250 					map->pr_mflags |= MA_READ;
    251 				if (kve->kve_protection & KVME_PROT_WRITE)
    252 					map->pr_mflags |= MA_WRITE;
    253 				if (kve->kve_protection & KVME_PROT_EXEC)
    254 					map->pr_mflags |= MA_EXEC;
    255 				if (kve->kve_flags & KVME_FLAG_COW)
    256 					map->pr_mflags |= MA_COW;
    257 				if (kve->kve_flags & KVME_FLAG_NEEDS_COPY)
    258 					map->pr_mflags |= MA_NEEDS_COPY;
    259 				if (kve->kve_flags & KVME_FLAG_NOCOREDUMP)
    260 					map->pr_mflags |= MA_NOCOREDUMP;
    261 				strlcpy(map->pr_mapname, kves[lastvn].kve_path,
    262 				    sizeof(map->pr_mapname));
    263 				free(kves);
    264 				return (map);
    265 			}
    266 		}
    267 		free(kves);
    268 		return (NULL);
    269 	}
    270 
    271 	for (i = 0; i < p->nobjs; i++) {
    272 		rdl = &p->rdobjs[i];
    273 		if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
    274 			if ((map = malloc(sizeof(*map))) == NULL)
    275 				return (NULL);
    276 			proc_rdl2prmap(rdl, map);
    277 			return (map);
    278 		}
    279 	}
    280 	return (NULL);
    281 }
    282 
    283 /*
    284  * Look up the symbol at addr, returning a copy of the symbol and its name.
    285  */
    286 static int
    287 lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
    288     const char **name, GElf_Sym *symcopy)
    289 {
    290 	GElf_Sym sym;
    291 	Elf_Data *data;
    292 	const char *s;
    293 	uint64_t rsym;
    294 	int i;
    295 
    296 	if ((data = elf_getdata(scn, NULL)) == NULL) {
    297 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
    298 		return (1);
    299 	}
    300 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
    301 		rsym = off + sym.st_value;
    302 		if (addr >= rsym && addr < rsym + sym.st_size) {
    303 			s = elf_strptr(e, stridx, sym.st_name);
    304 			if (s != NULL) {
    305 				*name = s;
    306 				memcpy(symcopy, &sym, sizeof(*symcopy));
    307 				/*
    308 				 * DTrace expects the st_value to contain
    309 				 * only the address relative to the start of
    310 				 * the function.
    311 				 */
    312 				symcopy->st_value = rsym;
    313 				return (0);
    314 			}
    315 		}
    316 	}
    317 	return (1);
    318 }
    319 
    320 int
    321 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
    322     size_t namesz, GElf_Sym *symcopy)
    323 {
    324 	GElf_Ehdr ehdr;
    325 	GElf_Shdr shdr;
    326 	Elf *e;
    327 	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
    328 	prmap_t *map;
    329 	const char *s;
    330 	uintptr_t off;
    331 	u_long symtabstridx = 0, dynsymstridx = 0;
    332 	int fd, error = -1;
    333 
    334 	if ((map = proc_addr2map(p, addr)) == NULL)
    335 		return (-1);
    336 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
    337 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
    338 		goto err0;
    339 	}
    340 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
    341 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
    342 		goto err1;
    343 	}
    344 	if (gelf_getehdr(e, &ehdr) == NULL) {
    345 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
    346 		goto err2;
    347 	}
    348 
    349 	/*
    350 	 * Find the index of the STRTAB and SYMTAB sections to locate
    351 	 * symbol names.
    352 	 */
    353 	scn = NULL;
    354 	while ((scn = elf_nextscn(e, scn)) != NULL) {
    355 		gelf_getshdr(scn, &shdr);
    356 		switch (shdr.sh_type) {
    357 		case SHT_SYMTAB:
    358 			symtabscn = scn;
    359 			symtabstridx = shdr.sh_link;
    360 			break;
    361 		case SHT_DYNSYM:
    362 			dynsymscn = scn;
    363 			dynsymstridx = shdr.sh_link;
    364 			break;
    365 		}
    366 	}
    367 
    368 	off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
    369 
    370 	/*
    371 	 * First look up the symbol in the dynsymtab, and fall back to the
    372 	 * symtab if the lookup fails.
    373 	 */
    374 	if (dynsymscn) {
    375 		error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
    376 		if (error == 0)
    377 			goto out;
    378 	}
    379 
    380 	error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
    381 	if (error != 0)
    382 		goto err2;
    383 
    384 out:
    385 	demangle(s, name, namesz);
    386 err2:
    387 	elf_end(e);
    388 err1:
    389 	close(fd);
    390 err0:
    391 	free(map);
    392 	return (error);
    393 }
    394 
    395 prmap_t *
    396 proc_name2map(struct proc_handle *p, const char *name)
    397 {
    398 	size_t i, cnt;
    399 	prmap_t *map = NULL;
    400 	char tmppath[MAXPATHLEN];
    401 	struct kinfo_vmentry *kves, *kve;
    402 	rd_loadobj_t *rdl;
    403 
    404 	/*
    405 	 * If we haven't iterated over the list of loaded objects,
    406 	 * librtld_db isn't yet initialized and it's very likely
    407 	 * that librtld_db called us. We need to do the heavy
    408 	 * lifting here to find the symbol librtld_db is looking for.
    409 	 */
    410 	if (p->nobjs == 0) {
    411 		if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
    412 			return (NULL);
    413 		for (i = 0; i < (size_t)cnt; i++) {
    414 			kve = kves + i;
    415 			basename_r(kve->kve_path, tmppath);
    416 			if (strcmp(tmppath, name) == 0) {
    417 				map = proc_addr2map(p, kve->kve_start);
    418 				break;
    419 			}
    420 		}
    421 		free(kves);
    422 	} else
    423 		for (i = 0; i < p->nobjs; i++) {
    424 			rdl = &p->rdobjs[i];
    425 			basename_r(rdl->rdl_path, tmppath);
    426 			if (strcmp(tmppath, name) == 0) {
    427 				if ((map = malloc(sizeof(*map))) == NULL)
    428 					return (NULL);
    429 				proc_rdl2prmap(rdl, map);
    430 				break;
    431 			}
    432 		}
    433 
    434 	if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
    435 		map = proc_addr2map(p, p->rdexec->rdl_saddr);
    436 
    437 	return (map);
    438 }
    439 
    440 /*
    441  * Look up the symbol with the given name and return a copy of it.
    442  */
    443 static int
    444 lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
    445     GElf_Sym *symcopy, prsyminfo_t *si)
    446 {
    447 	GElf_Sym sym;
    448 	Elf_Data *data;
    449 	char *s;
    450 	int i;
    451 
    452 	if ((data = elf_getdata(scn, NULL)) == NULL) {
    453 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
    454 		return (1);
    455 	}
    456 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
    457 		s = elf_strptr(e, stridx, sym.st_name);
    458 		if (s != NULL && strcmp(s, symbol) == 0) {
    459 			memcpy(symcopy, &sym, sizeof(*symcopy));
    460 			if (si != NULL)
    461 				si->prs_id = i;
    462 			return (0);
    463 		}
    464 	}
    465 	return (1);
    466 }
    467 
    468 int
    469 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
    470     GElf_Sym *symcopy, prsyminfo_t *si)
    471 {
    472 	Elf *e;
    473 	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
    474 	GElf_Shdr shdr;
    475 	GElf_Ehdr ehdr;
    476 	prmap_t *map;
    477 	uintptr_t off;
    478 	u_long symtabstridx = 0, dynsymstridx = 0;
    479 	int fd, error = -1;
    480 
    481 	if ((map = proc_name2map(p, object)) == NULL) {
    482 		DPRINTFX("ERROR: couldn't find object %s", object);
    483 		goto err0;
    484 	}
    485 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
    486 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
    487 		goto err0;
    488 	}
    489 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
    490 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
    491 		goto err1;
    492 	}
    493 	if (gelf_getehdr(e, &ehdr) == NULL) {
    494 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
    495 		goto err2;
    496 	}
    497 	/*
    498 	 * Find the index of the STRTAB and SYMTAB sections to locate
    499 	 * symbol names.
    500 	 */
    501 	scn = NULL;
    502 	while ((scn = elf_nextscn(e, scn)) != NULL) {
    503 		gelf_getshdr(scn, &shdr);
    504 		switch (shdr.sh_type) {
    505 		case SHT_SYMTAB:
    506 			symtabscn = scn;
    507 			symtabstridx = shdr.sh_link;
    508 			break;
    509 		case SHT_DYNSYM:
    510 			dynsymscn = scn;
    511 			dynsymstridx = shdr.sh_link;
    512 			break;
    513 		}
    514 	}
    515 
    516 	/*
    517 	 * First look up the symbol in the dynsymtab, and fall back to the
    518 	 * symtab if the lookup fails.
    519 	 */
    520 	if (dynsymscn) {
    521 		error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si);
    522 		if (error == 0)
    523 			goto out;
    524 	}
    525 
    526 	error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si);
    527 	if (error == 0)
    528 		goto out;
    529 
    530 out:
    531 	off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
    532 	symcopy->st_value += off;
    533 
    534 err2:
    535 	elf_end(e);
    536 err1:
    537 	close(fd);
    538 err0:
    539 	free(map);
    540 
    541 	return (error);
    542 }
    543 
    544 ctf_file_t *
    545 proc_name2ctf(struct proc_handle *p, const char *name)
    546 {
    547 #ifndef NO_CTF
    548 	ctf_file_t *ctf;
    549 	prmap_t *map;
    550 	int error;
    551 
    552 	if ((map = proc_name2map(p, name)) == NULL)
    553 		return (NULL);
    554 
    555 	ctf = ctf_open(map->pr_mapname, &error);
    556 	free(map);
    557 	return (ctf);
    558 #else
    559 	(void)p;
    560 	(void)name;
    561 	return (NULL);
    562 #endif
    563 }
    564 
    565 int
    566 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
    567     int mask, proc_sym_f *func, void *cd)
    568 {
    569 	Elf *e;
    570 	int i, fd;
    571 	prmap_t *map;
    572 	Elf_Scn *scn, *foundscn = NULL;
    573 	Elf_Data *data;
    574 	GElf_Ehdr ehdr;
    575 	GElf_Shdr shdr;
    576 	GElf_Sym sym;
    577 	unsigned long stridx = -1;
    578 	char *s;
    579 	int error = -1;
    580 
    581 	if ((map = proc_name2map(p, object)) == NULL)
    582 		return (-1);
    583 	if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
    584 		DPRINTF("ERROR: open %s failed", map->pr_mapname);
    585 		goto err0;
    586 	}
    587 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
    588 		DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
    589 		goto err1;
    590 	}
    591 	if (gelf_getehdr(e, &ehdr) == NULL) {
    592 		DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
    593 		goto err2;
    594 	}
    595 	/*
    596 	 * Find the section we are looking for.
    597 	 */
    598 	scn = NULL;
    599 	while ((scn = elf_nextscn(e, scn)) != NULL) {
    600 		gelf_getshdr(scn, &shdr);
    601 		if (which == PR_SYMTAB &&
    602 		    shdr.sh_type == SHT_SYMTAB) {
    603 			foundscn = scn;
    604 			break;
    605 		} else if (which == PR_DYNSYM &&
    606 		    shdr.sh_type == SHT_DYNSYM) {
    607 			foundscn = scn;
    608 			break;
    609 		}
    610 	}
    611 	if (!foundscn)
    612 		return (-1);
    613 	stridx = shdr.sh_link;
    614 	if ((data = elf_getdata(foundscn, NULL)) == NULL) {
    615 		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
    616 		goto err2;
    617 	}
    618 	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
    619 		if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
    620 		    (mask & BIND_LOCAL) == 0)
    621 			continue;
    622 		if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL &&
    623 		    (mask & BIND_GLOBAL) == 0)
    624 			continue;
    625 		if (GELF_ST_BIND(sym.st_info) == STB_WEAK &&
    626 		    (mask & BIND_WEAK) == 0)
    627 			continue;
    628 		if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE &&
    629 		    (mask & TYPE_NOTYPE) == 0)
    630 			continue;
    631 		if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT &&
    632 		    (mask & TYPE_OBJECT) == 0)
    633 			continue;
    634 		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC &&
    635 		    (mask & TYPE_FUNC) == 0)
    636 			continue;
    637 		if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
    638 		    (mask & TYPE_SECTION) == 0)
    639 			continue;
    640 		if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
    641 		    (mask & TYPE_FILE) == 0)
    642 			continue;
    643 		s = elf_strptr(e, stridx, sym.st_name);
    644 		if (ehdr.e_type != ET_EXEC)
    645 			sym.st_value += map->pr_vaddr;
    646 		if ((error = (*func)(cd, &sym, s)) != 0)
    647 			goto err2;
    648 	}
    649 	error = 0;
    650 err2:
    651 	elf_end(e);
    652 err1:
    653 	close(fd);
    654 err0:
    655 	free(map);
    656 	return (error);
    657 }
    658