xref: /openbsd-src/sys/ddb/db_elf.c (revision 949c1c4ec8cc03255798b09f6078e1d0aed70a6a)
1*949c1c4eSmiod /*	$OpenBSD: db_elf.c,v 1.34 2024/11/07 16:02:29 miod Exp $	*/
256c88695Sniklas /*	$NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $	*/
356c88695Sniklas 
456c88695Sniklas /*-
556c88695Sniklas  * Copyright (c) 1997 The NetBSD Foundation, Inc.
656c88695Sniklas  * All rights reserved.
756c88695Sniklas  *
856c88695Sniklas  * This code is derived from software contributed to The NetBSD Foundation
956c88695Sniklas  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
1056c88695Sniklas  * NASA Ames Research Center.
1156c88695Sniklas  *
1256c88695Sniklas  * Redistribution and use in source and binary forms, with or without
1356c88695Sniklas  * modification, are permitted provided that the following conditions
1456c88695Sniklas  * are met:
1556c88695Sniklas  * 1. Redistributions of source code must retain the above copyright
1656c88695Sniklas  *    notice, this list of conditions and the following disclaimer.
1756c88695Sniklas  * 2. Redistributions in binary form must reproduce the above copyright
1856c88695Sniklas  *    notice, this list of conditions and the following disclaimer in the
1956c88695Sniklas  *    documentation and/or other materials provided with the distribution.
2056c88695Sniklas  *
2156c88695Sniklas  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2256c88695Sniklas  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2356c88695Sniklas  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2456c88695Sniklas  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2556c88695Sniklas  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2656c88695Sniklas  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2756c88695Sniklas  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2856c88695Sniklas  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2956c88695Sniklas  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3056c88695Sniklas  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3156c88695Sniklas  * POSSIBILITY OF SUCH DAMAGE.
3256c88695Sniklas  */
3356c88695Sniklas 
3456c88695Sniklas #include <sys/param.h>
35b27348b2Sderaadt #include <sys/stdint.h>
3656c88695Sniklas #include <sys/systm.h>
3756c88695Sniklas #include <sys/exec.h>
3856c88695Sniklas 
3956c88695Sniklas #include <machine/db_machdep.h>
4056c88695Sniklas 
41fd68ecf3Sjasper #include <ddb/db_elf.h>
4256c88695Sniklas #include <ddb/db_sym.h>
4356c88695Sniklas #include <ddb/db_output.h>
4456c88695Sniklas 
4556c88695Sniklas #include <sys/exec_elf.h>
4656c88695Sniklas 
476933210dSmpi db_symtab_t db_symtab;
486933210dSmpi 
49*949c1c4eSmiod Elf_Sym		*db_elf_sym_lookup(const char *);
5056c88695Sniklas 
5156c88695Sniklas /*
5256c88695Sniklas  * Find the symbol table and strings; tell ddb about them.
536ecb06d0Sjsg  *
546ecb06d0Sjsg  * symsize:	size of symbol table
556ecb06d0Sjsg  * symtab:	pointer to start of symbol table
566ecb06d0Sjsg  * esymtab:	pointer to end of string table, for checking - rounded up to
5784f3acfdSjsg  *		    integer boundary
5856c88695Sniklas  */
5951015a3eSmpi int
606ecb06d0Sjsg db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name)
6156c88695Sniklas {
6256c88695Sniklas 	Elf_Ehdr *elf;
6356c88695Sniklas 	Elf_Shdr *shp;
6456c88695Sniklas 	Elf_Sym *symp, *symtab_start, *symtab_end;
6556c88695Sniklas 	char *shstrtab, *strtab_start, *strtab_end;
6656c88695Sniklas 	int i;
678566ff3fSart 	char *errstr = "";
6856c88695Sniklas 
6956c88695Sniklas 	if (ALIGNED_POINTER(symtab, long) == 0) {
70a77f7862Skettenis 		db_printf("[ %s symbol table has bad start address %p ]\n",
7156c88695Sniklas 		    name, symtab);
7251015a3eSmpi 		return (0);
7356c88695Sniklas 	}
7456c88695Sniklas 
7556c88695Sniklas 	symtab_start = symtab_end = NULL;
7656c88695Sniklas 	strtab_start = strtab_end = NULL;
7756c88695Sniklas 
7856c88695Sniklas 	/*
7956c88695Sniklas 	 * The format of the symbols loaded by the boot program is:
8056c88695Sniklas 	 *
8156c88695Sniklas 	 *	Elf exec header
8256c88695Sniklas 	 *	first section header
8356c88695Sniklas 	 *	. . .
8456c88695Sniklas 	 *	. . .
8556c88695Sniklas 	 *	last section header
864d814044Smatthew 	 *	first symbol, string, or line table section
8756c88695Sniklas 	 *	. . .
8856c88695Sniklas 	 *	. . .
894d814044Smatthew 	 *	last symbol, string, or line table section
9056c88695Sniklas 	 */
9156c88695Sniklas 
9256c88695Sniklas 	/*
9356c88695Sniklas 	 * Validate the Elf header.
9456c88695Sniklas 	 */
9556c88695Sniklas 	elf = (Elf_Ehdr *)symtab;
9656c88695Sniklas 	if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
978566ff3fSart 	    elf->e_ident[EI_CLASS] != ELFCLASS) {
988566ff3fSart 		errstr = "bad magic";
9956c88695Sniklas 		goto badheader;
1008566ff3fSart 	}
10156c88695Sniklas 
1028566ff3fSart 	if (elf->e_machine != ELF_TARG_MACH) {
1038566ff3fSart 		errstr = "bad e_machine";
10456c88695Sniklas 		goto badheader;
1058566ff3fSart 	}
10656c88695Sniklas 
10756c88695Sniklas 	/*
10856c88695Sniklas 	 * Find the section header string table (.shstrtab), and look up
10956c88695Sniklas 	 * the symbol table (.symtab) and string table (.strtab) via their
11056c88695Sniklas 	 * names in shstrtab, rather than by table type.
11156c88695Sniklas 	 * This works in the presence of multiple string tables, such as
11256c88695Sniklas 	 * stabs data found when booting bsd.gdb.
11356c88695Sniklas 	 */
11456c88695Sniklas 	shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
11556c88695Sniklas 	shstrtab = (char *)symtab + shp[elf->e_shstrndx].sh_offset;
11656c88695Sniklas 	for (i = 0; i < elf->e_shnum; i++) {
117e6686108Sart 		if (shp[i].sh_type == SHT_SYMTAB) {
118e6686108Sart 			int j;
119e6686108Sart 
120e6686108Sart 			if (shp[i].sh_offset == 0)
121e6686108Sart 				continue;
122e6686108Sart 			symtab_start = (Elf_Sym *)((char *)symtab +
123e6686108Sart 			    shp[i].sh_offset);
124e6686108Sart 			symtab_end = (Elf_Sym *)((char *)symtab +
125e6686108Sart 			    shp[i].sh_offset + shp[i].sh_size);
126e6686108Sart 			j = shp[i].sh_link;
127e6686108Sart 			if (shp[j].sh_offset == 0)
128e6686108Sart 				continue;
129e6686108Sart 			strtab_start = (char *)symtab + shp[j].sh_offset;
130e6686108Sart 			strtab_end = (char *)symtab + shp[j].sh_offset +
131e6686108Sart 			    shp[j].sh_size;
132e6686108Sart 			break;
133e6686108Sart 		}
134e6686108Sart 
135e6686108Sart 		/*
136e6686108Sart 		 * This is the old way of doing things.
137e6686108Sart 		 * XXX - verify that it's not needed.
138e6686108Sart 		 */
13956c88695Sniklas 		if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) {
14056c88695Sniklas 			strtab_start = (char *)symtab + shp[i].sh_offset;
14156c88695Sniklas 			strtab_end = (char *)symtab + shp[i].sh_offset +
14256c88695Sniklas 			    shp[i].sh_size;
14356c88695Sniklas 		} else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) {
14456c88695Sniklas 			symtab_start = (Elf_Sym *)((char *)symtab +
14556c88695Sniklas 			    shp[i].sh_offset);
14656c88695Sniklas 			symtab_end = (Elf_Sym *)((char *)symtab +
14756c88695Sniklas 			    shp[i].sh_offset + shp[i].sh_size);
14856c88695Sniklas 		}
14956c88695Sniklas 	}
15056c88695Sniklas 
15156c88695Sniklas 	/*
15256c88695Sniklas 	 * Now, sanity check the symbols against the string table.
15356c88695Sniklas 	 */
15456c88695Sniklas 	if (symtab_start == NULL || strtab_start == NULL ||
1558529ee83Sgkoehler 	    ALIGNED_POINTER(symtab_start, long) == 0) {
1568566ff3fSart 		errstr = "symtab unaligned";
15756c88695Sniklas 		goto badheader;
1588566ff3fSart 	}
15956c88695Sniklas 	for (symp = symtab_start; symp < symtab_end; symp++)
1608566ff3fSart 		if (symp->st_name + strtab_start > strtab_end) {
1618566ff3fSart 			errstr = "symtab corrupted";
16256c88695Sniklas 			goto badheader;
1638566ff3fSart 		}
16456c88695Sniklas 
16556c88695Sniklas 	/*
16656c88695Sniklas 	 * Link the symbol table into the debugger.
16756c88695Sniklas 	 */
1686933210dSmpi 	db_symtab.start = (char *)symtab_start;
1696933210dSmpi 	db_symtab.end = (char *)symtab_end;
1706933210dSmpi 	db_symtab.name = name;
1716933210dSmpi 	db_symtab.private = (char *)symtab;
17256c88695Sniklas 
1736933210dSmpi 	db_printf("[ using %lu bytes of %s ELF symbol table ]\n",
1746933210dSmpi 	    (u_long)roundup(((char *)esymtab - (char *)symtab), sizeof(u_long)),
1756933210dSmpi 	    name);
1766933210dSmpi 
17751015a3eSmpi 	return (1);
17856c88695Sniklas 
17956c88695Sniklas  badheader:
180a77f7862Skettenis 	db_printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr);
18151015a3eSmpi 	return (0);
18256c88695Sniklas }
18356c88695Sniklas 
18456c88695Sniklas /*
18556c88695Sniklas  * Internal helper function - return a pointer to the string table
18656c88695Sniklas  * for the current symbol table.
18756c88695Sniklas  */
188*949c1c4eSmiod const char *
1896ecb06d0Sjsg db_elf_find_strtab(db_symtab_t *stab)
19056c88695Sniklas {
19156c88695Sniklas 	Elf_Ehdr *elf = STAB_TO_EHDR(stab);
19256c88695Sniklas 	Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
193*949c1c4eSmiod 	const char *shstrtab;
19456c88695Sniklas 	int i;
19556c88695Sniklas 
196*949c1c4eSmiod 	shstrtab = (const char *)elf + shp[elf->e_shstrndx].sh_offset;
19756c88695Sniklas 	for (i = 0; i < elf->e_shnum; i++) {
198e6686108Sart 		if (shp[i].sh_type == SHT_SYMTAB)
199*949c1c4eSmiod 			return ((const char *)elf +
200*949c1c4eSmiod 			    shp[shp[i].sh_link].sh_offset);
20156c88695Sniklas 		if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0)
202*949c1c4eSmiod 			return ((const char *)elf + shp[i].sh_offset);
20356c88695Sniklas 	}
20456c88695Sniklas 
20556c88695Sniklas 	return (NULL);
20656c88695Sniklas }
20756c88695Sniklas 
20856c88695Sniklas /*
2094916abc8Smpi  * Internal helper function - return a pointer to the section
2104916abc8Smpi  * named ``sname''.
2114d814044Smatthew  */
2124916abc8Smpi const char *
2134916abc8Smpi db_elf_find_section(db_symtab_t *stab, size_t *size, const char *sname)
2144d814044Smatthew {
2154d814044Smatthew 	Elf_Ehdr *elf = STAB_TO_EHDR(stab);
2164d814044Smatthew 	Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
2174d814044Smatthew 	char *shstrtab;
2184d814044Smatthew 	int i;
2194d814044Smatthew 
2204d814044Smatthew 	shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset;
2214d814044Smatthew 	for (i = 0; i < elf->e_shnum; i++) {
2224d814044Smatthew 		if ((shp[i].sh_flags & SHF_ALLOC) != 0 &&
2234916abc8Smpi 		    strcmp(sname, shstrtab+shp[i].sh_name) == 0) {
2244d814044Smatthew 			*size = shp[i].sh_size;
2254d814044Smatthew 			return ((char *)elf + shp[i].sh_offset);
2264d814044Smatthew 		}
2274d814044Smatthew 	}
2284d814044Smatthew 
2294d814044Smatthew 	return (NULL);
2304d814044Smatthew }
2314d814044Smatthew 
2324d814044Smatthew /*
23356c88695Sniklas  * Lookup the symbol with the given name.
23456c88695Sniklas  */
23548cf49eeSmpi Elf_Sym *
236*949c1c4eSmiod db_elf_sym_lookup(const char *symstr)
23756c88695Sniklas {
2386933210dSmpi 	db_symtab_t *stab = &db_symtab;
23956c88695Sniklas 	Elf_Sym *symp, *symtab_start, *symtab_end;
240*949c1c4eSmiod 	const char *strtab;
24156c88695Sniklas 
2426933210dSmpi 	if (stab->private == NULL)
243268d6ae6Smpi 		return (NULL);
2446933210dSmpi 
24556c88695Sniklas 	symtab_start = STAB_TO_SYMSTART(stab);
24656c88695Sniklas 	symtab_end = STAB_TO_SYMEND(stab);
24756c88695Sniklas 
24856c88695Sniklas 	strtab = db_elf_find_strtab(stab);
24956c88695Sniklas 	if (strtab == NULL)
250268d6ae6Smpi 		return (NULL);
25156c88695Sniklas 
25256c88695Sniklas 	for (symp = symtab_start; symp < symtab_end; symp++) {
25356c88695Sniklas 		if (symp->st_name != 0 &&
25456c88695Sniklas 		    db_eqname(strtab + symp->st_name, symstr, 0))
25548cf49eeSmpi 			return (symp);
25656c88695Sniklas 	}
25756c88695Sniklas 
258268d6ae6Smpi 	return (NULL);
25956c88695Sniklas }
26056c88695Sniklas 
26156c88695Sniklas /*
26256c88695Sniklas  * Search for the symbol with the given address (matching within the
26356c88695Sniklas  * provided threshold).
26456c88695Sniklas  */
26562781896Smpi Elf_Sym *
26608f058f8Smpi db_elf_sym_search(vaddr_t off, db_strategy_t strategy, db_expr_t *diffp)
26756c88695Sniklas {
2686933210dSmpi 	db_symtab_t *stab = &db_symtab;
26956c88695Sniklas 	Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
27056c88695Sniklas 	db_expr_t diff = *diffp;
27156c88695Sniklas 
2726933210dSmpi 	if (stab->private == NULL)
273268d6ae6Smpi 		return (NULL);
2746933210dSmpi 
2756933210dSmpi 	symtab_start = STAB_TO_SYMSTART(stab);
2766933210dSmpi 	symtab_end = STAB_TO_SYMEND(stab);
27756c88695Sniklas 
27856c88695Sniklas 	rsymp = NULL;
27956c88695Sniklas 
28056c88695Sniklas 	for (symp = symtab_start; symp < symtab_end; symp++) {
28156c88695Sniklas 		if (symp->st_name == 0)
28256c88695Sniklas 			continue;
28356c88695Sniklas #if 0
2849593dc34Smglocker 		/* This prevents me from seeing anything in locore.s -- eeh */
28556c88695Sniklas 		if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
28656c88695Sniklas 		    ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
28756c88695Sniklas 			continue;
28856c88695Sniklas #endif
28956c88695Sniklas 
29056c88695Sniklas 		if (off >= symp->st_value) {
29156c88695Sniklas 			if ((off - symp->st_value) < diff) {
29256c88695Sniklas 				diff = off - symp->st_value;
29356c88695Sniklas 				rsymp = symp;
29456c88695Sniklas 				if (diff == 0) {
29556c88695Sniklas 					if (strategy == DB_STGY_PROC &&
296ce2f92c3Sguenther 					    ELF_ST_TYPE(symp->st_info)
29756c88695Sniklas 					      == STT_FUNC &&
298ce2f92c3Sguenther 					    ELF_ST_BIND(symp->st_info)
29956c88695Sniklas 					      != STB_LOCAL)
30056c88695Sniklas 						break;
30156c88695Sniklas 					if (strategy == DB_STGY_ANY &&
302ce2f92c3Sguenther 					    ELF_ST_BIND(symp->st_info)
30356c88695Sniklas 					      != STB_LOCAL)
30456c88695Sniklas 						break;
30556c88695Sniklas 				}
30656c88695Sniklas 			} else if ((off - symp->st_value) == diff) {
30756c88695Sniklas 				if (rsymp == NULL)
30856c88695Sniklas 					rsymp = symp;
309ce2f92c3Sguenther 				else if (ELF_ST_BIND(rsymp->st_info)
31056c88695Sniklas 				      == STB_LOCAL &&
311ce2f92c3Sguenther 				    ELF_ST_BIND(symp->st_info)
31256c88695Sniklas 				      != STB_LOCAL) {
31356c88695Sniklas 					/* pick the external symbol */
31456c88695Sniklas 					rsymp = symp;
31556c88695Sniklas 				}
31656c88695Sniklas 			}
31756c88695Sniklas 		}
31856c88695Sniklas 	}
31956c88695Sniklas 
32056c88695Sniklas 	if (rsymp == NULL)
32156c88695Sniklas 		*diffp = off;
32256c88695Sniklas 	else
32356c88695Sniklas 		*diffp = diff;
32456c88695Sniklas 
32562781896Smpi 	return (rsymp);
32656c88695Sniklas }
32756c88695Sniklas 
32856c88695Sniklas /*
32956c88695Sniklas  * Return the name and value for a symbol.
33056c88695Sniklas  */
33156c88695Sniklas void
332*949c1c4eSmiod db_symbol_values(Elf_Sym *sym, const char **namep, db_expr_t *valuep)
33356c88695Sniklas {
3346933210dSmpi 	db_symtab_t *stab = &db_symtab;
33556c88695Sniklas 	Elf_Sym *symp = (Elf_Sym *)sym;
336*949c1c4eSmiod 	const char *strtab;
33756c88695Sniklas 
338702da755Smpi 	if (sym == NULL) {
339702da755Smpi 		*namep = NULL;
340702da755Smpi 		return;
341702da755Smpi 	}
342702da755Smpi 
3436933210dSmpi 	if (stab->private == NULL)
3446933210dSmpi 		return;
3456933210dSmpi 
34656c88695Sniklas 	if (namep) {
3476933210dSmpi 		strtab = db_elf_find_strtab(stab);
34856c88695Sniklas 		if (strtab == NULL)
34956c88695Sniklas 			*namep = NULL;
35056c88695Sniklas 		else
35156c88695Sniklas 			*namep = strtab + symp->st_name;
35256c88695Sniklas 	}
35356c88695Sniklas 
35456c88695Sniklas 	if (valuep)
35556c88695Sniklas 		*valuep = symp->st_value;
35656c88695Sniklas }
35756c88695Sniklas 
35856c88695Sniklas /*
35956c88695Sniklas  * Return the file and line number of the current program counter
36056c88695Sniklas  * if we can find the appropriate debugging symbol.
36156c88695Sniklas  */
36251015a3eSmpi int
363*949c1c4eSmiod db_elf_line_at_pc(Elf_Sym *cursym, const char **filename,
3646ecb06d0Sjsg     int *linenum, db_expr_t off)
36556c88695Sniklas {
3666933210dSmpi 	db_symtab_t *stab = &db_symtab;
367f45abf1bSmpi 	static char path[PATH_MAX];
368f45abf1bSmpi 	const char *linetab, *dirname, *basename;
3694d814044Smatthew 	size_t linetab_size;
37056c88695Sniklas 
3716933210dSmpi 	if (stab->private == NULL)
37251015a3eSmpi 		return (0);
3736933210dSmpi 
3744916abc8Smpi 	linetab = db_elf_find_section(stab, &linetab_size, ".debug_line");
3754d814044Smatthew 	if (linetab == NULL)
37651015a3eSmpi 		return (0);
3774d814044Smatthew 
3784d814044Smatthew 	if (!db_dwarf_line_at_pc(linetab, linetab_size, off,
3794d814044Smatthew 	    &dirname, &basename, linenum))
38051015a3eSmpi 		return (0);
3814d814044Smatthew 
3824d814044Smatthew 	if (dirname == NULL)
3834d814044Smatthew 		strlcpy(path, basename, sizeof(path));
3844d814044Smatthew 	else
3854d814044Smatthew 		snprintf(path, sizeof(path), "%s/%s", dirname, basename);
3864d814044Smatthew 	*filename = path;
38751015a3eSmpi 	return (1);
38856c88695Sniklas }
38956c88695Sniklas 
39056c88695Sniklas void
3916933210dSmpi db_elf_sym_forall(db_forall_func_t db_forall_func, void *arg)
39256c88695Sniklas {
3936933210dSmpi 	db_symtab_t *stab = &db_symtab;
394*949c1c4eSmiod 	const char *strtab;
39556c88695Sniklas 	static char suffix[2];
39656c88695Sniklas 	Elf_Sym *symp, *symtab_start, *symtab_end;
39756c88695Sniklas 
3986933210dSmpi 	if (stab->private == NULL)
3996933210dSmpi 		return;
4006933210dSmpi 
40156c88695Sniklas 	symtab_start = STAB_TO_SYMSTART(stab);
40256c88695Sniklas 	symtab_end = STAB_TO_SYMEND(stab);
40356c88695Sniklas 
40456c88695Sniklas 	strtab = db_elf_find_strtab(stab);
40556c88695Sniklas 	if (strtab == NULL)
40656c88695Sniklas 		return;
40756c88695Sniklas 
40856c88695Sniklas 	for (symp = symtab_start; symp < symtab_end; symp++)
40956c88695Sniklas 		if (symp->st_name != 0) {
41056c88695Sniklas 			suffix[1] = '\0';
411ce2f92c3Sguenther 			switch (ELF_ST_TYPE(symp->st_info)) {
41256c88695Sniklas 			case STT_OBJECT:
41356c88695Sniklas 				suffix[0] = '+';
41456c88695Sniklas 				break;
41556c88695Sniklas 			case STT_FUNC:
41656c88695Sniklas 				suffix[0] = '*';
41756c88695Sniklas 				break;
41856c88695Sniklas 			case STT_SECTION:
41956c88695Sniklas 				suffix[0] = '&';
42056c88695Sniklas 				break;
42156c88695Sniklas 			case STT_FILE:
42256c88695Sniklas 				suffix[0] = '/';
42356c88695Sniklas 				break;
42456c88695Sniklas 			default:
42556c88695Sniklas 				suffix[0] = '\0';
42656c88695Sniklas 			}
42762781896Smpi 			(*db_forall_func)(symp,
428*949c1c4eSmiod 			    strtab + symp->st_name, suffix, arg);
42956c88695Sniklas 		}
43056c88695Sniklas }
43148cf49eeSmpi 
432ad205586Smpi Elf_Sym *
433*949c1c4eSmiod db_symbol_by_name(const char *name, db_expr_t *valuep)
43448cf49eeSmpi {
43548cf49eeSmpi 	Elf_Sym		*sym;
43648cf49eeSmpi 
43748cf49eeSmpi 	sym = db_elf_sym_lookup(name);
43848cf49eeSmpi 	if (sym == NULL)
439ad205586Smpi 		return (NULL);
44062781896Smpi 	db_symbol_values(sym, &name, valuep);
441ad205586Smpi 	return (sym);
44248cf49eeSmpi }
443