xref: /netbsd-src/sys/ddb/db_elf.c (revision d3c8c77eb598c40d2768a89050112267c7a9b8dc)
1*d3c8c77eSchristos /*	$NetBSD: db_elf.c,v 1.29 2017/11/06 04:08:02 christos Exp $	*/
25accaea9Sthorpej 
35accaea9Sthorpej /*-
4cd6b1c8fSad  * Copyright (c) 1997, 2009 The NetBSD Foundation, Inc.
55accaea9Sthorpej  * All rights reserved.
65accaea9Sthorpej  *
75accaea9Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
85accaea9Sthorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9cd6b1c8fSad  * NASA Ames Research Center, and by Andrew Doran.
105accaea9Sthorpej  *
115accaea9Sthorpej  * Redistribution and use in source and binary forms, with or without
125accaea9Sthorpej  * modification, are permitted provided that the following conditions
135accaea9Sthorpej  * are met:
145accaea9Sthorpej  * 1. Redistributions of source code must retain the above copyright
155accaea9Sthorpej  *    notice, this list of conditions and the following disclaimer.
165accaea9Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
175accaea9Sthorpej  *    notice, this list of conditions and the following disclaimer in the
185accaea9Sthorpej  *    documentation and/or other materials provided with the distribution.
195accaea9Sthorpej  *
205accaea9Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
215accaea9Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
225accaea9Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
235accaea9Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
245accaea9Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
255accaea9Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
265accaea9Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
275accaea9Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285accaea9Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295accaea9Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
305accaea9Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
315accaea9Sthorpej  */
325accaea9Sthorpej 
331ac69d9cSlukem #include <sys/cdefs.h>
34*d3c8c77eSchristos __KERNEL_RCSID(0, "$NetBSD: db_elf.c,v 1.29 2017/11/06 04:08:02 christos Exp $");
351ac69d9cSlukem 
365accaea9Sthorpej #include <sys/param.h>
375accaea9Sthorpej #include <sys/systm.h>
385accaea9Sthorpej #include <sys/proc.h>
395accaea9Sthorpej 
40ad97afb1Schristos #include <machine/db_machdep.h>
41cd6b1c8fSad #include <machine/pmap.h>
42cd6b1c8fSad #include <machine/vmparam.h>
435accaea9Sthorpej 
445accaea9Sthorpej #ifdef DB_ELF_SYMBOLS
455accaea9Sthorpej 
46ad97afb1Schristos #include <ddb/ddb.h>
475accaea9Sthorpej #include <sys/exec_elf.h>
485accaea9Sthorpej 
494eaa4d66Ssimonb static char	*db_elf_find_strtab(db_symtab_t *);
505accaea9Sthorpej 
515accaea9Sthorpej #define	STAB_TO_SYMSTART(stab)	((Elf_Sym *)((stab)->start))
525accaea9Sthorpej #define	STAB_TO_SYMEND(stab)	((Elf_Sym *)((stab)->end))
535accaea9Sthorpej #define	STAB_TO_EHDR(stab)	((Elf_Ehdr *)((stab)->private))
545accaea9Sthorpej #define	STAB_TO_SHDR(stab, e)	((Elf_Shdr *)((stab)->private + (e)->e_shoff))
555accaea9Sthorpej 
56712239e3Sthorpej static bool db_elf_sym_init(int, void *, void *, const char *);
57cd6b1c8fSad static db_sym_t	db_elf_lookup(db_symtab_t *, const char *);
584eaa4d66Ssimonb static db_sym_t	db_elf_search_symbol(db_symtab_t *, db_addr_t, db_strategy_t,
594eaa4d66Ssimonb 		    db_expr_t *);
60cd6b1c8fSad static void	db_elf_symbol_values(db_symtab_t *, db_sym_t, const char **,
614eaa4d66Ssimonb 		    db_expr_t *);
62712239e3Sthorpej static bool db_elf_line_at_pc(db_symtab_t *, db_sym_t, char **, int *,
634eaa4d66Ssimonb 		    db_expr_t);
64712239e3Sthorpej static bool db_elf_sym_numargs(db_symtab_t *, db_sym_t, int *, char **);
654eaa4d66Ssimonb static void	db_elf_forall(db_symtab_t *, db_forall_func_t db_forall_func,
664eaa4d66Ssimonb 		    void *);
67c8949352Sthorpej 
689aa0a018Sjdolecek const db_symformat_t db_symformat_elf = {
69c8949352Sthorpej 	"ELF",
70c8949352Sthorpej 	db_elf_sym_init,
71c8949352Sthorpej 	db_elf_lookup,
72c8949352Sthorpej 	db_elf_search_symbol,
73c8949352Sthorpej 	db_elf_symbol_values,
74c8949352Sthorpej 	db_elf_line_at_pc,
75c8949352Sthorpej 	db_elf_sym_numargs,
7641ebaaafSjhawk 	db_elf_forall
77c8949352Sthorpej };
78c8949352Sthorpej 
79cd6b1c8fSad static db_symtab_t db_symtabs;
80cd6b1c8fSad 
81cd6b1c8fSad /*
82cd6b1c8fSad  * Add symbol table, with given name, to symbol tables.
83cd6b1c8fSad  */
84cd6b1c8fSad static int
db_add_symbol_table(char * start,char * end,const char * name,char * ref)85cd6b1c8fSad db_add_symbol_table(char *start, char *end, const char *name, char *ref)
86cd6b1c8fSad {
87cd6b1c8fSad 
88cd6b1c8fSad 	db_symtabs.start = start;
89cd6b1c8fSad 	db_symtabs.end = end;
90cd6b1c8fSad 	db_symtabs.name = name;
91cd6b1c8fSad 	db_symtabs.private = ref;
92cd6b1c8fSad 
93cd6b1c8fSad 	return(0);
94cd6b1c8fSad }
95cd6b1c8fSad 
965accaea9Sthorpej /*
975accaea9Sthorpej  * Find the symbol table and strings; tell ddb about them.
985accaea9Sthorpej  */
99712239e3Sthorpej static bool
db_elf_sym_init(int symsize,void * symtab,void * esymtab,const char * name)1004eaa4d66Ssimonb db_elf_sym_init(
1014eaa4d66Ssimonb 	int symsize,		/* size of symbol table */
1024eaa4d66Ssimonb 	void *symtab,		/* pointer to start of symbol table */
1034eaa4d66Ssimonb 	void *esymtab,		/* pointer to end of string table,
1045accaea9Sthorpej 				   for checking - rounded up to integer
1055accaea9Sthorpej 				   boundary */
1064eaa4d66Ssimonb 	const char *name
1074eaa4d66Ssimonb )
1085accaea9Sthorpej {
1095accaea9Sthorpej 	Elf_Ehdr *elf;
1105accaea9Sthorpej 	Elf_Shdr *shp;
1115accaea9Sthorpej 	Elf_Sym *symp, *symtab_start, *symtab_end;
11234c3239dSbjh21 	char *strtab_start, *strtab_end;
11334c3239dSbjh21 	int i, j;
1145accaea9Sthorpej 
1155accaea9Sthorpej 	if (ALIGNED_POINTER(symtab, long) == 0) {
116c8949352Sthorpej 		printf("[ %s symbol table has bad start address %p ]\n",
117c8949352Sthorpej 		    name, symtab);
1184f3d5a9cSthorpej 		return (false);
1195accaea9Sthorpej 	}
1205accaea9Sthorpej 
1215accaea9Sthorpej 	symtab_start = symtab_end = NULL;
1225accaea9Sthorpej 	strtab_start = strtab_end = NULL;
1235accaea9Sthorpej 
1245accaea9Sthorpej 	/*
1255accaea9Sthorpej 	 * The format of the symbols loaded by the boot program is:
1265accaea9Sthorpej 	 *
1275accaea9Sthorpej 	 *	Elf exec header
1285accaea9Sthorpej 	 *	first section header
1295accaea9Sthorpej 	 *	. . .
1305accaea9Sthorpej 	 *	. . .
1315accaea9Sthorpej 	 *	last section header
1325accaea9Sthorpej 	 *	first symbol or string table section
1335accaea9Sthorpej 	 *	. . .
1345accaea9Sthorpej 	 *	. . .
1355accaea9Sthorpej 	 *	last symbol or string table section
1365accaea9Sthorpej 	 */
1375accaea9Sthorpej 
1385accaea9Sthorpej 	/*
1395accaea9Sthorpej 	 * Validate the Elf header.
1405accaea9Sthorpej 	 */
1415accaea9Sthorpej 	elf = (Elf_Ehdr *)symtab;
142522cbf02Skleink 	if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
143522cbf02Skleink 	    elf->e_ident[EI_CLASS] != ELFCLASS)
1445accaea9Sthorpej 		goto badheader;
1455accaea9Sthorpej 
1465accaea9Sthorpej 	switch (elf->e_machine) {
1475accaea9Sthorpej 
14859b90d4aSerh 	ELFDEFNNAME(MACHDEP_ID_CASES)
1495accaea9Sthorpej 
1505accaea9Sthorpej 	default:
1515accaea9Sthorpej 		goto badheader;
1525accaea9Sthorpej 	}
1535accaea9Sthorpej 
1545accaea9Sthorpej 	/*
15534c3239dSbjh21 	 * Find the first (and, we hope, only) SHT_SYMTAB section in
15634c3239dSbjh21 	 * the file, and the SHT_STRTAB section that goes with it.
1575accaea9Sthorpej 	 */
158286faf20Sbjh21 	if (elf->e_shoff == 0)
159286faf20Sbjh21 		goto badheader;
160332d7c13Saugustss 	shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
1615accaea9Sthorpej 	for (i = 0; i < elf->e_shnum; i++) {
16234c3239dSbjh21 		if (shp[i].sh_type == SHT_SYMTAB) {
163286faf20Sbjh21 			if (shp[i].sh_offset == 0)
164286faf20Sbjh21 				continue;
16534c3239dSbjh21 			/* Got the symbol table. */
166332d7c13Saugustss 			symtab_start = (Elf_Sym *)((char *)symtab +
167332d7c13Saugustss 			    shp[i].sh_offset);
168332d7c13Saugustss 			symtab_end = (Elf_Sym *)((char *)symtab +
169332d7c13Saugustss 			    shp[i].sh_offset + shp[i].sh_size);
17034c3239dSbjh21 			/* Find the string table to go with it. */
17134c3239dSbjh21 			j = shp[i].sh_link;
172286faf20Sbjh21 			if (shp[j].sh_offset == 0)
173286faf20Sbjh21 				continue;
17434c3239dSbjh21 			strtab_start = (char *)symtab + shp[j].sh_offset;
17534c3239dSbjh21 			strtab_end = (char *)symtab + shp[j].sh_offset +
17634c3239dSbjh21 			    shp[j].sh_size;
17734c3239dSbjh21 			/* There should only be one symbol table. */
17834c3239dSbjh21 			break;
1795accaea9Sthorpej 		}
1805accaea9Sthorpej 	}
1815accaea9Sthorpej 
1825accaea9Sthorpej 	/*
1835accaea9Sthorpej 	 * Now, sanity check the symbols against the string table.
1845accaea9Sthorpej 	 */
185f576b48bSthorpej 	if (symtab_start == NULL || strtab_start == NULL ||
186f576b48bSthorpej 	    ALIGNED_POINTER(symtab_start, long) == 0 ||
187f576b48bSthorpej 	    ALIGNED_POINTER(strtab_start, long) == 0)
1885accaea9Sthorpej 		goto badheader;
1895accaea9Sthorpej 	for (symp = symtab_start; symp < symtab_end; symp++)
1905accaea9Sthorpej 		if (symp->st_name + strtab_start > strtab_end)
1915accaea9Sthorpej 			goto badheader;
1925accaea9Sthorpej 
1935accaea9Sthorpej 	/*
1945accaea9Sthorpej 	 * Link the symbol table into the debugger.
1955accaea9Sthorpej 	 */
1965accaea9Sthorpej 	if (db_add_symbol_table((char *)symtab_start,
197c8949352Sthorpej 	    (char *)symtab_end, name, (char *)symtab) != -1) {
1984f3d5a9cSthorpej 		return (true);
199c8949352Sthorpej 	}
200c8949352Sthorpej 
2014f3d5a9cSthorpej 	return (false);
2025accaea9Sthorpej 
2035accaea9Sthorpej  badheader:
204c8949352Sthorpej 	printf("[ %s ELF symbol table not valid ]\n", name);
2054f3d5a9cSthorpej 	return (false);
2065accaea9Sthorpej }
2075accaea9Sthorpej 
2085accaea9Sthorpej /*
2095accaea9Sthorpej  * Internal helper function - return a pointer to the string table
2105accaea9Sthorpej  * for the current symbol table.
2115accaea9Sthorpej  */
2125accaea9Sthorpej static char *
db_elf_find_strtab(db_symtab_t * stab)2134eaa4d66Ssimonb db_elf_find_strtab(db_symtab_t *stab)
2145accaea9Sthorpej {
2155accaea9Sthorpej 	Elf_Ehdr *elf = STAB_TO_EHDR(stab);
2165accaea9Sthorpej 	Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
2175accaea9Sthorpej 	int i;
2185accaea9Sthorpej 
219cd6b1c8fSad 	stab = &db_symtabs;
220cd6b1c8fSad 
221e415081aSchristos 	/*
222e415081aSchristos 	 * We don't load ELF header for ELF modules.
223e415081aSchristos 	 * Find out if this is a loadable module. If so,
224e415081aSchristos 	 * string table comes right after symbol table.
225e415081aSchristos 	 */
226e415081aSchristos 	if ((Elf_Sym *)elf == STAB_TO_SYMSTART(stab)) {
227e415081aSchristos 		return ((char *)STAB_TO_SYMEND(stab));
228e415081aSchristos 	}
2295accaea9Sthorpej 	for (i = 0; i < elf->e_shnum; i++) {
23034c3239dSbjh21 		if (shp[i].sh_type == SHT_SYMTAB)
23134c3239dSbjh21 			return ((char*)elf + shp[shp[i].sh_link].sh_offset);
2325accaea9Sthorpej 	}
2335accaea9Sthorpej 
2345accaea9Sthorpej 	return (NULL);
2355accaea9Sthorpej }
2365accaea9Sthorpej 
2375accaea9Sthorpej /*
2385accaea9Sthorpej  * Lookup the symbol with the given name.
2395accaea9Sthorpej  */
2404eaa4d66Ssimonb static db_sym_t
db_elf_lookup(db_symtab_t * stab,const char * symstr)241cd6b1c8fSad db_elf_lookup(db_symtab_t *stab, const char *symstr)
2425accaea9Sthorpej {
2435accaea9Sthorpej 	Elf_Sym *symp, *symtab_start, *symtab_end;
2445accaea9Sthorpej 	char *strtab;
2455accaea9Sthorpej 
246cd6b1c8fSad 	stab = &db_symtabs;
247cd6b1c8fSad 
2485accaea9Sthorpej 	symtab_start = STAB_TO_SYMSTART(stab);
2495accaea9Sthorpej 	symtab_end = STAB_TO_SYMEND(stab);
2505accaea9Sthorpej 
2515accaea9Sthorpej 	strtab = db_elf_find_strtab(stab);
2525accaea9Sthorpej 	if (strtab == NULL)
2535accaea9Sthorpej 		return ((db_sym_t)0);
2545accaea9Sthorpej 
2555accaea9Sthorpej 	for (symp = symtab_start; symp < symtab_end; symp++) {
2565accaea9Sthorpej 		if (symp->st_name != 0 &&
2575accaea9Sthorpej 		    db_eqname(strtab + symp->st_name, symstr, 0))
2585accaea9Sthorpej 			return ((db_sym_t)symp);
2595accaea9Sthorpej 	}
2605accaea9Sthorpej 
2615accaea9Sthorpej 	return ((db_sym_t)0);
2625accaea9Sthorpej }
2635accaea9Sthorpej 
2645accaea9Sthorpej /*
2655accaea9Sthorpej  * Search for the symbol with the given address (matching within the
2665accaea9Sthorpej  * provided threshold).
2675accaea9Sthorpej  */
2684eaa4d66Ssimonb static db_sym_t
db_elf_search_symbol(db_symtab_t * symtab,db_addr_t off,db_strategy_t strategy,db_expr_t * diffp)2694eaa4d66Ssimonb db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
2704eaa4d66Ssimonb     db_expr_t *diffp)
2715accaea9Sthorpej {
2725accaea9Sthorpej 	Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
27364f7cc2aSyamt 	db_addr_t diff = *diffp;
2745accaea9Sthorpej 
275cd6b1c8fSad 	symtab = &db_symtabs;
276cd6b1c8fSad 
2775accaea9Sthorpej 	symtab_start = STAB_TO_SYMSTART(symtab);
2785accaea9Sthorpej 	symtab_end = STAB_TO_SYMEND(symtab);
2795accaea9Sthorpej 
2805accaea9Sthorpej 	rsymp = NULL;
2815accaea9Sthorpej 
2825accaea9Sthorpej 	for (symp = symtab_start; symp < symtab_end; symp++) {
2835accaea9Sthorpej 		if (symp->st_name == 0)
2845accaea9Sthorpej 			continue;
285cd6b1c8fSad 
286a2dd74edSeeh #if 0
287a2dd74edSeeh 		/* This prevents me from seeing anythin in locore.s -- eeh */
288cd6b1c8fSad 		if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT &&
289cd6b1c8fSad 		    ELF_ST_TYPE(symp->st_info) != STT_FUNC)
2905accaea9Sthorpej 			continue;
291a2dd74edSeeh #endif
2925accaea9Sthorpej 
2935accaea9Sthorpej 		if (off >= symp->st_value) {
29464f7cc2aSyamt 			if (off - symp->st_value < diff) {
2955accaea9Sthorpej 				diff = off - symp->st_value;
2965accaea9Sthorpej 				rsymp = symp;
2975accaea9Sthorpej 				if (diff == 0) {
2985accaea9Sthorpej 					if (strategy == DB_STGY_PROC &&
299522cbf02Skleink 					    ELFDEFNNAME(ST_TYPE)(symp->st_info)
300522cbf02Skleink 					      == STT_FUNC &&
301522cbf02Skleink 					    ELFDEFNNAME(ST_BIND)(symp->st_info)
302522cbf02Skleink 					      != STB_LOCAL)
3035accaea9Sthorpej 						break;
3045accaea9Sthorpej 					if (strategy == DB_STGY_ANY &&
305522cbf02Skleink 					    ELFDEFNNAME(ST_BIND)(symp->st_info)
306522cbf02Skleink 					      != STB_LOCAL)
3075accaea9Sthorpej 						break;
3085accaea9Sthorpej 				}
30964f7cc2aSyamt 			} else if (off - symp->st_value == diff) {
3105accaea9Sthorpej 				if (rsymp == NULL)
3115accaea9Sthorpej 					rsymp = symp;
312522cbf02Skleink 				else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
313522cbf02Skleink 				      == STB_LOCAL &&
314522cbf02Skleink 				    ELFDEFNNAME(ST_BIND)(symp->st_info)
315522cbf02Skleink 				      != STB_LOCAL) {
3165accaea9Sthorpej 					/* pick the external symbol */
3175accaea9Sthorpej 					rsymp = symp;
3185accaea9Sthorpej 				}
3195accaea9Sthorpej 			}
3205accaea9Sthorpej 		}
3215accaea9Sthorpej 	}
3225accaea9Sthorpej 
3235accaea9Sthorpej 	if (rsymp == NULL)
3245accaea9Sthorpej 		*diffp = off;
3255accaea9Sthorpej 	else
3265accaea9Sthorpej 		*diffp = diff;
3275accaea9Sthorpej 
3285accaea9Sthorpej 	return ((db_sym_t)rsymp);
3295accaea9Sthorpej }
3305accaea9Sthorpej 
3315accaea9Sthorpej /*
3325accaea9Sthorpej  * Return the name and value for a symbol.
3335accaea9Sthorpej  */
3344eaa4d66Ssimonb static void
db_elf_symbol_values(db_symtab_t * symtab,db_sym_t sym,const char ** namep,db_expr_t * valuep)335cd6b1c8fSad db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, const char **namep,
3364eaa4d66Ssimonb     db_expr_t *valuep)
3375accaea9Sthorpej {
3385accaea9Sthorpej 	Elf_Sym *symp = (Elf_Sym *)sym;
3395accaea9Sthorpej 	char *strtab;
3405accaea9Sthorpej 
341cd6b1c8fSad 	symtab = &db_symtabs;
342cd6b1c8fSad 
3435accaea9Sthorpej 	if (namep) {
3445accaea9Sthorpej 		strtab = db_elf_find_strtab(symtab);
3455accaea9Sthorpej 		if (strtab == NULL)
3465accaea9Sthorpej 			*namep = NULL;
3475accaea9Sthorpej 		else
3485accaea9Sthorpej 			*namep = strtab + symp->st_name;
3495accaea9Sthorpej 	}
3505accaea9Sthorpej 
3515accaea9Sthorpej 	if (valuep)
3525accaea9Sthorpej 		*valuep = symp->st_value;
3535accaea9Sthorpej }
3545accaea9Sthorpej 
3555accaea9Sthorpej /*
3565accaea9Sthorpej  * Return the file and line number of the current program counter
3575accaea9Sthorpej  * if we can find the appropriate debugging symbol.
3585accaea9Sthorpej  */
359712239e3Sthorpej static bool
db_elf_line_at_pc(db_symtab_t * symtab,db_sym_t cursym,char ** filename,int * linenum,db_expr_t off)360454af1c0Sdsl db_elf_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename, int *linenum, db_expr_t off)
3615accaea9Sthorpej {
3625accaea9Sthorpej 
3635accaea9Sthorpej 	/*
3645accaea9Sthorpej 	 * XXX We don't support this (yet).
3655accaea9Sthorpej 	 */
3664f3d5a9cSthorpej 	return (false);
3675accaea9Sthorpej }
3685accaea9Sthorpej 
3695accaea9Sthorpej /*
3705accaea9Sthorpej  * Returns the number of arguments to a function and their
3715accaea9Sthorpej  * names if we can find the appropriate debugging symbol.
3725accaea9Sthorpej  */
373712239e3Sthorpej static bool
db_elf_sym_numargs(db_symtab_t * symtab,db_sym_t cursym,int * nargp,char ** argnamep)3744eaa4d66Ssimonb db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
3754eaa4d66Ssimonb     char **argnamep)
3765accaea9Sthorpej {
3775accaea9Sthorpej 
3785accaea9Sthorpej 	/*
3795accaea9Sthorpej 	 * XXX We don't support this (yet).
3805accaea9Sthorpej 	 */
3814f3d5a9cSthorpej 	return (false);
3825accaea9Sthorpej }
38341ebaaafSjhawk 
3844eaa4d66Ssimonb static void
db_elf_forall(db_symtab_t * stab,db_forall_func_t db_forall_func,void * arg)3854eaa4d66Ssimonb db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
38641ebaaafSjhawk {
38741ebaaafSjhawk 	char *strtab;
38841ebaaafSjhawk 	static char suffix[2];
38941ebaaafSjhawk 	Elf_Sym *symp, *symtab_start, *symtab_end;
39041ebaaafSjhawk 
391cd6b1c8fSad 	stab = &db_symtabs;
392cd6b1c8fSad 
39341ebaaafSjhawk 	symtab_start = STAB_TO_SYMSTART(stab);
39441ebaaafSjhawk 	symtab_end = STAB_TO_SYMEND(stab);
39541ebaaafSjhawk 
39641ebaaafSjhawk 	strtab = db_elf_find_strtab(stab);
39741ebaaafSjhawk 	if (strtab == NULL)
39841ebaaafSjhawk 		return;
39941ebaaafSjhawk 
40041ebaaafSjhawk 	for (symp = symtab_start; symp < symtab_end; symp++)
40141ebaaafSjhawk 		if (symp->st_name != 0) {
40241ebaaafSjhawk 			suffix[1] = '\0';
40341ebaaafSjhawk 			switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
40441ebaaafSjhawk 			case STT_OBJECT:
40541ebaaafSjhawk 				suffix[0] = '+';
40641ebaaafSjhawk 				break;
40741ebaaafSjhawk 			case STT_FUNC:
40841ebaaafSjhawk 				suffix[0] = '*';
40941ebaaafSjhawk 				break;
41041ebaaafSjhawk 			case STT_SECTION:
41141ebaaafSjhawk 				suffix[0] = '&';
41241ebaaafSjhawk 				break;
41341ebaaafSjhawk 			case STT_FILE:
41441ebaaafSjhawk 				suffix[0] = '/';
41541ebaaafSjhawk 				break;
41641ebaaafSjhawk 			default:
41741ebaaafSjhawk 				suffix[0] = '\0';
41841ebaaafSjhawk 			}
41941ebaaafSjhawk 			(*db_forall_func)(stab, (db_sym_t)symp,
42041ebaaafSjhawk 			    strtab + symp->st_name, suffix, 0, arg);
42141ebaaafSjhawk 		}
42241ebaaafSjhawk 	return;
42341ebaaafSjhawk }
4245accaea9Sthorpej #endif /* DB_ELF_SYMBOLS */
425