xref: /freebsd/sys/ddb/db_sym.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1dd3cb568SWarner Losh /*-
2796df753SPedro F. Giffuni  * SPDX-License-Identifier: MIT-CMU
3796df753SPedro F. Giffuni  *
45b81b6b3SRodney W. Grimes  * Mach Operating System
55b81b6b3SRodney W. Grimes  * Copyright (c) 1991,1990 Carnegie Mellon University
65b81b6b3SRodney W. Grimes  * All Rights Reserved.
75b81b6b3SRodney W. Grimes  *
85b81b6b3SRodney W. Grimes  * Permission to use, copy, modify and distribute this software and its
95b81b6b3SRodney W. Grimes  * documentation is hereby granted, provided that both the copyright
105b81b6b3SRodney W. Grimes  * notice and this permission notice appear in all copies of the
115b81b6b3SRodney W. Grimes  * software, derivative works or modified versions, and any portions
125b81b6b3SRodney W. Grimes  * thereof, and that both notices appear in supporting documentation.
135b81b6b3SRodney W. Grimes  *
145b81b6b3SRodney W. Grimes  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
155b81b6b3SRodney W. Grimes  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
165b81b6b3SRodney W. Grimes  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
175b81b6b3SRodney W. Grimes  *
185b81b6b3SRodney W. Grimes  * Carnegie Mellon requests users of this software to return to
195b81b6b3SRodney W. Grimes  *
205b81b6b3SRodney W. Grimes  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
215b81b6b3SRodney W. Grimes  *  School of Computer Science
225b81b6b3SRodney W. Grimes  *  Carnegie Mellon University
235b81b6b3SRodney W. Grimes  *  Pittsburgh PA 15213-3890
245b81b6b3SRodney W. Grimes  *
255b81b6b3SRodney W. Grimes  * any improvements or extensions that they make and grant Carnegie the
265b81b6b3SRodney W. Grimes  * rights to redistribute these changes.
275b81b6b3SRodney W. Grimes  */
285b81b6b3SRodney W. Grimes /*
295b81b6b3SRodney W. Grimes  * 	Author: David B. Golub, Carnegie Mellon University
305b81b6b3SRodney W. Grimes  *	Date:	7/90
315b81b6b3SRodney W. Grimes  */
32753960f7SDavid E. O'Brien 
33753960f7SDavid E. O'Brien #include <sys/cdefs.h>
34721555e7SZbigniew Bodek #include "opt_kstack_pages.h"
35721555e7SZbigniew Bodek 
36f540b106SGarrett Wollman #include <sys/param.h>
376f8a182bSMitchell Horne #include <sys/systm.h>
38530c0060SRobert Watson #include <sys/pcpu.h>
3989e5ef89SHans Petter Selasky #include <sys/proc.h>
40eddfbb76SRobert Watson #include <sys/smp.h>
41754cb545SMitchell Horne #include <sys/sysent.h>
42eddfbb76SRobert Watson 
43eddfbb76SRobert Watson #include <net/vnet.h>
445ccbc3ccSBruce Evans 
45f540b106SGarrett Wollman #include <ddb/ddb.h>
465b81b6b3SRodney W. Grimes #include <ddb/db_sym.h>
47eddfbb76SRobert Watson #include <ddb/db_variables.h>
485b81b6b3SRodney W. Grimes 
494e38d895SWarner Losh #include "opt_ddb.h"
509aece96fSPoul-Henning Kamp 
515b81b6b3SRodney W. Grimes /*
525b81b6b3SRodney W. Grimes  * Multiple symbol tables
535b81b6b3SRodney W. Grimes  */
54f7d75744SDavid Greenman #ifndef MAXNOSYMTABS
555b81b6b3SRodney W. Grimes #define	MAXNOSYMTABS	3	/* mach, ux, emulator */
56f7d75744SDavid Greenman #endif
575b81b6b3SRodney W. Grimes 
58f73a856dSPoul-Henning Kamp static db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
59f73a856dSPoul-Henning Kamp static int db_nsymtab = 0;
605b81b6b3SRodney W. Grimes 
6194e24bf0SBruce Evans static db_symtab_t	*db_last_symtab; /* where last symbol was found */
625b81b6b3SRodney W. Grimes 
6314e10f99SAlfred Perlstein static c_db_sym_t	db_lookup( const char *symstr);
6414e10f99SAlfred Perlstein static char		*db_qualify(c_db_sym_t sym, char *symtabname);
65cd508278SPedro F. Giffuni static bool		db_symbol_is_ambiguous(c_db_sym_t sym);
66cd508278SPedro F. Giffuni static bool		db_line_at_pc(c_db_sym_t, char **, int *, db_expr_t);
675b81b6b3SRodney W. Grimes 
68eddfbb76SRobert Watson static int db_cpu = -1;
69eddfbb76SRobert Watson 
70eddfbb76SRobert Watson #ifdef VIMAGE
71eddfbb76SRobert Watson static void *db_vnet = NULL;
72eddfbb76SRobert Watson #endif
73eddfbb76SRobert Watson 
74eddfbb76SRobert Watson /*
75eddfbb76SRobert Watson  * Validate the CPU number used to interpret per-CPU variables so we can
76eddfbb76SRobert Watson  * avoid later confusion if an invalid CPU is requested.
77eddfbb76SRobert Watson  */
78eddfbb76SRobert Watson int
db_var_db_cpu(struct db_variable * vp,db_expr_t * valuep,int op)79eddfbb76SRobert Watson db_var_db_cpu(struct db_variable *vp, db_expr_t *valuep, int op)
80eddfbb76SRobert Watson {
81eddfbb76SRobert Watson 
82eddfbb76SRobert Watson 	switch (op) {
83eddfbb76SRobert Watson 	case DB_VAR_GET:
84eddfbb76SRobert Watson 		*valuep = db_cpu;
85eddfbb76SRobert Watson 		return (1);
86eddfbb76SRobert Watson 
87eddfbb76SRobert Watson 	case DB_VAR_SET:
886e1c5d18SAndriy Gapon 		if (*(int *)valuep < -1 || *(int *)valuep > mp_maxid) {
896e1c5d18SAndriy Gapon 			db_printf("Invalid value: %d\n", *(int*)valuep);
90eddfbb76SRobert Watson 			return (0);
91eddfbb76SRobert Watson 		}
92eddfbb76SRobert Watson 		db_cpu = *(int *)valuep;
93eddfbb76SRobert Watson 		return (1);
94eddfbb76SRobert Watson 
95eddfbb76SRobert Watson 	default:
96eddfbb76SRobert Watson 		db_printf("db_var_db_cpu: unknown operation\n");
97eddfbb76SRobert Watson 		return (0);
98eddfbb76SRobert Watson 	}
99eddfbb76SRobert Watson }
100eddfbb76SRobert Watson 
101eddfbb76SRobert Watson /*
102eddfbb76SRobert Watson  * Read-only variable reporting the current CPU, which is what we use when
103eddfbb76SRobert Watson  * db_cpu is set to -1.
104eddfbb76SRobert Watson  */
105eddfbb76SRobert Watson int
db_var_curcpu(struct db_variable * vp,db_expr_t * valuep,int op)106eddfbb76SRobert Watson db_var_curcpu(struct db_variable *vp, db_expr_t *valuep, int op)
107eddfbb76SRobert Watson {
108eddfbb76SRobert Watson 
109eddfbb76SRobert Watson 	switch (op) {
110eddfbb76SRobert Watson 	case DB_VAR_GET:
111eddfbb76SRobert Watson 		*valuep = curcpu;
112eddfbb76SRobert Watson 		return (1);
113eddfbb76SRobert Watson 
114eddfbb76SRobert Watson 	case DB_VAR_SET:
115eddfbb76SRobert Watson 		db_printf("Read-only variable.\n");
116eddfbb76SRobert Watson 		return (0);
117eddfbb76SRobert Watson 
118eddfbb76SRobert Watson 	default:
119eddfbb76SRobert Watson 		db_printf("db_var_curcpu: unknown operation\n");
120eddfbb76SRobert Watson 		return (0);
121eddfbb76SRobert Watson 	}
122eddfbb76SRobert Watson }
123eddfbb76SRobert Watson 
124eddfbb76SRobert Watson #ifdef VIMAGE
125eddfbb76SRobert Watson /*
126eddfbb76SRobert Watson  * Validate the virtual network pointer used to interpret per-vnet global
127eddfbb76SRobert Watson  * variable expansion.  Right now we don't do much here, really we should
128eddfbb76SRobert Watson  * walk the global vnet list to check it's an OK pointer.
129eddfbb76SRobert Watson  */
130eddfbb76SRobert Watson int
db_var_db_vnet(struct db_variable * vp,db_expr_t * valuep,int op)131eddfbb76SRobert Watson db_var_db_vnet(struct db_variable *vp, db_expr_t *valuep, int op)
132eddfbb76SRobert Watson {
133eddfbb76SRobert Watson 
134eddfbb76SRobert Watson 	switch (op) {
135eddfbb76SRobert Watson 	case DB_VAR_GET:
136eddfbb76SRobert Watson 		*valuep = (db_expr_t)db_vnet;
137eddfbb76SRobert Watson 		return (1);
138eddfbb76SRobert Watson 
139eddfbb76SRobert Watson 	case DB_VAR_SET:
140eddfbb76SRobert Watson 		db_vnet = *(void **)valuep;
141eddfbb76SRobert Watson 		return (1);
142eddfbb76SRobert Watson 
143eddfbb76SRobert Watson 	default:
144eddfbb76SRobert Watson 		db_printf("db_var_db_vnet: unknown operation\n");
145eddfbb76SRobert Watson 		return (0);
146eddfbb76SRobert Watson 	}
147eddfbb76SRobert Watson }
148eddfbb76SRobert Watson 
149eddfbb76SRobert Watson /*
150eddfbb76SRobert Watson  * Read-only variable reporting the current vnet, which is what we use when
151eddfbb76SRobert Watson  * db_vnet is set to NULL.
152eddfbb76SRobert Watson  */
153eddfbb76SRobert Watson int
db_var_curvnet(struct db_variable * vp,db_expr_t * valuep,int op)154eddfbb76SRobert Watson db_var_curvnet(struct db_variable *vp, db_expr_t *valuep, int op)
155eddfbb76SRobert Watson {
156eddfbb76SRobert Watson 
157eddfbb76SRobert Watson 	switch (op) {
158eddfbb76SRobert Watson 	case DB_VAR_GET:
159eddfbb76SRobert Watson 		*valuep = (db_expr_t)curvnet;
160eddfbb76SRobert Watson 		return (1);
161eddfbb76SRobert Watson 
162eddfbb76SRobert Watson 	case DB_VAR_SET:
163eddfbb76SRobert Watson 		db_printf("Read-only variable.\n");
164eddfbb76SRobert Watson 		return (0);
165eddfbb76SRobert Watson 
166eddfbb76SRobert Watson 	default:
1678fe344faSBjoern A. Zeeb 		db_printf("db_var_curvnet: unknown operation\n");
168eddfbb76SRobert Watson 		return (0);
169eddfbb76SRobert Watson 	}
170eddfbb76SRobert Watson }
171eddfbb76SRobert Watson #endif
172eddfbb76SRobert Watson 
1735b81b6b3SRodney W. Grimes /*
1745b81b6b3SRodney W. Grimes  * Add symbol table, with given name, to list of symbol tables.
1755b81b6b3SRodney W. Grimes  */
1765b81b6b3SRodney W. Grimes void
db_add_symbol_table(char * start,char * end,char * name,char * ref)177a41dd031SPedro F. Giffuni db_add_symbol_table(char *start, char *end, char *name, char *ref)
1785b81b6b3SRodney W. Grimes {
1795b81b6b3SRodney W. Grimes 	if (db_nsymtab >= MAXNOSYMTABS) {
1805b81b6b3SRodney W. Grimes 		printf ("No slots left for %s symbol table", name);
1815b81b6b3SRodney W. Grimes 		panic ("db_sym.c: db_add_symbol_table");
1825b81b6b3SRodney W. Grimes 	}
1835b81b6b3SRodney W. Grimes 
1845b81b6b3SRodney W. Grimes 	db_symtabs[db_nsymtab].start = start;
1855b81b6b3SRodney W. Grimes 	db_symtabs[db_nsymtab].end = end;
1865b81b6b3SRodney W. Grimes 	db_symtabs[db_nsymtab].name = name;
1875b81b6b3SRodney W. Grimes 	db_symtabs[db_nsymtab].private = ref;
1885b81b6b3SRodney W. Grimes 	db_nsymtab++;
1895b81b6b3SRodney W. Grimes }
1905b81b6b3SRodney W. Grimes 
1915b81b6b3SRodney W. Grimes /*
1925b81b6b3SRodney W. Grimes  *  db_qualify("vm_map", "ux") returns "unix:vm_map".
1935b81b6b3SRodney W. Grimes  *
1945b81b6b3SRodney W. Grimes  *  Note: return value points to static data whose content is
1955b81b6b3SRodney W. Grimes  *  overwritten by each call... but in practice this seems okay.
1965b81b6b3SRodney W. Grimes  */
1975b81b6b3SRodney W. Grimes static char *
db_qualify(c_db_sym_t sym,char * symtabname)198a41dd031SPedro F. Giffuni db_qualify(c_db_sym_t sym, char *symtabname)
1995b81b6b3SRodney W. Grimes {
200a1c1e16aSMatthew Dillon 	const char	*symname;
2015b81b6b3SRodney W. Grimes 	static char     tmp[256];
2025b81b6b3SRodney W. Grimes 
2035b81b6b3SRodney W. Grimes 	db_symbol_values(sym, &symname, 0);
2042127f260SArchie Cobbs 	snprintf(tmp, sizeof(tmp), "%s:%s", symtabname, symname);
2055b81b6b3SRodney W. Grimes 	return tmp;
2065b81b6b3SRodney W. Grimes }
2075b81b6b3SRodney W. Grimes 
208cd508278SPedro F. Giffuni bool
db_eqname(const char * src,const char * dst,int c)209a41dd031SPedro F. Giffuni db_eqname(const char *src, const char *dst, int c)
2105b81b6b3SRodney W. Grimes {
2115b81b6b3SRodney W. Grimes 	if (!strcmp(src, dst))
2122b490bc7SPedro F. Giffuni 	    return (true);
2135b81b6b3SRodney W. Grimes 	if (src[0] == c)
2145b81b6b3SRodney W. Grimes 	    return (!strcmp(src+1,dst));
2152b490bc7SPedro F. Giffuni 	return (false);
2165b81b6b3SRodney W. Grimes }
2175b81b6b3SRodney W. Grimes 
218cd508278SPedro F. Giffuni bool
db_value_of_name(const char * name,db_expr_t * valuep)219a41dd031SPedro F. Giffuni db_value_of_name(const char *name, db_expr_t *valuep)
2205b81b6b3SRodney W. Grimes {
221fe08c21aSMatthew Dillon 	c_db_sym_t	sym;
2225b81b6b3SRodney W. Grimes 
2235b81b6b3SRodney W. Grimes 	sym = db_lookup(name);
224fe08c21aSMatthew Dillon 	if (sym == C_DB_SYM_NULL)
2252b490bc7SPedro F. Giffuni 	    return (false);
2265b81b6b3SRodney W. Grimes 	db_symbol_values(sym, &name, valuep);
2272b490bc7SPedro F. Giffuni 	return (true);
2285b81b6b3SRodney W. Grimes }
2295b81b6b3SRodney W. Grimes 
230cd508278SPedro F. Giffuni bool
db_value_of_name_pcpu(const char * name,db_expr_t * valuep)231a41dd031SPedro F. Giffuni db_value_of_name_pcpu(const char *name, db_expr_t *valuep)
232eddfbb76SRobert Watson {
233eddfbb76SRobert Watson 	static char     tmp[256];
234eddfbb76SRobert Watson 	db_expr_t	value;
235eddfbb76SRobert Watson 	c_db_sym_t	sym;
236eddfbb76SRobert Watson 	int		cpu;
237eddfbb76SRobert Watson 
238eddfbb76SRobert Watson 	if (db_cpu != -1)
239eddfbb76SRobert Watson 		cpu = db_cpu;
240eddfbb76SRobert Watson 	else
241eddfbb76SRobert Watson 		cpu = curcpu;
242eddfbb76SRobert Watson 	snprintf(tmp, sizeof(tmp), "pcpu_entry_%s", name);
243eddfbb76SRobert Watson 	sym = db_lookup(tmp);
244eddfbb76SRobert Watson 	if (sym == C_DB_SYM_NULL)
2452b490bc7SPedro F. Giffuni 		return (false);
246eddfbb76SRobert Watson 	db_symbol_values(sym, &name, &value);
247eddfbb76SRobert Watson 	if (value < DPCPU_START || value >= DPCPU_STOP)
2482b490bc7SPedro F. Giffuni 		return (false);
249eddfbb76SRobert Watson 	*valuep = (db_expr_t)((uintptr_t)value + dpcpu_off[cpu]);
2502b490bc7SPedro F. Giffuni 	return (true);
251eddfbb76SRobert Watson }
252eddfbb76SRobert Watson 
253cd508278SPedro F. Giffuni bool
db_value_of_name_vnet(const char * name,db_expr_t * valuep)254a41dd031SPedro F. Giffuni db_value_of_name_vnet(const char *name, db_expr_t *valuep)
255eddfbb76SRobert Watson {
256eddfbb76SRobert Watson #ifdef VIMAGE
257eddfbb76SRobert Watson 	static char     tmp[256];
258eddfbb76SRobert Watson 	db_expr_t	value;
259eddfbb76SRobert Watson 	c_db_sym_t	sym;
260eddfbb76SRobert Watson 	struct vnet	*vnet;
261eddfbb76SRobert Watson 
262eddfbb76SRobert Watson 	if (db_vnet != NULL)
263eddfbb76SRobert Watson 		vnet = db_vnet;
264eddfbb76SRobert Watson 	else
265eddfbb76SRobert Watson 		vnet = curvnet;
266eddfbb76SRobert Watson 	snprintf(tmp, sizeof(tmp), "vnet_entry_%s", name);
267eddfbb76SRobert Watson 	sym = db_lookup(tmp);
268eddfbb76SRobert Watson 	if (sym == C_DB_SYM_NULL)
2692b490bc7SPedro F. Giffuni 		return (false);
270eddfbb76SRobert Watson 	db_symbol_values(sym, &name, &value);
271eddfbb76SRobert Watson 	if (value < VNET_START || value >= VNET_STOP)
2722b490bc7SPedro F. Giffuni 		return (false);
273eddfbb76SRobert Watson 	*valuep = (db_expr_t)((uintptr_t)value + vnet->vnet_data_base);
2742b490bc7SPedro F. Giffuni 	return (true);
275eddfbb76SRobert Watson #else
2762b490bc7SPedro F. Giffuni 	return (false);
277eddfbb76SRobert Watson #endif
278eddfbb76SRobert Watson }
2795b81b6b3SRodney W. Grimes 
2805b81b6b3SRodney W. Grimes /*
2815b81b6b3SRodney W. Grimes  * Lookup a symbol.
2825b81b6b3SRodney W. Grimes  * If the symbol has a qualifier (e.g., ux:vm_map),
2835b81b6b3SRodney W. Grimes  * then only the specified symbol table will be searched;
2845b81b6b3SRodney W. Grimes  * otherwise, all symbol tables will be searched.
2855b81b6b3SRodney W. Grimes  */
286fe08c21aSMatthew Dillon static c_db_sym_t
db_lookup(const char * symstr)287a41dd031SPedro F. Giffuni db_lookup(const char *symstr)
2885b81b6b3SRodney W. Grimes {
289fe08c21aSMatthew Dillon 	c_db_sym_t sp;
2903e85b721SEd Maste 	int i;
2915b81b6b3SRodney W. Grimes 	int symtab_start = 0;
2925b81b6b3SRodney W. Grimes 	int symtab_end = db_nsymtab;
2933e85b721SEd Maste 	const char *cp;
2945b81b6b3SRodney W. Grimes 
2955b81b6b3SRodney W. Grimes 	/*
2965b81b6b3SRodney W. Grimes 	 * Look for, remove, and remember any symbol table specifier.
2975b81b6b3SRodney W. Grimes 	 */
2985b81b6b3SRodney W. Grimes 	for (cp = symstr; *cp; cp++) {
2995b81b6b3SRodney W. Grimes 		if (*cp == ':') {
3005b81b6b3SRodney W. Grimes 			for (i = 0; i < db_nsymtab; i++) {
301a1c1e16aSMatthew Dillon 				int n = strlen(db_symtabs[i].name);
302a1c1e16aSMatthew Dillon 
303a1c1e16aSMatthew Dillon 				if (
304a1c1e16aSMatthew Dillon 				    n == (cp - symstr) &&
305a1c1e16aSMatthew Dillon 				    strncmp(symstr, db_symtabs[i].name, n) == 0
306a1c1e16aSMatthew Dillon 				) {
3075b81b6b3SRodney W. Grimes 					symtab_start = i;
3085b81b6b3SRodney W. Grimes 					symtab_end = i + 1;
3095b81b6b3SRodney W. Grimes 					break;
3105b81b6b3SRodney W. Grimes 				}
3115b81b6b3SRodney W. Grimes 			}
3125b81b6b3SRodney W. Grimes 			if (i == db_nsymtab) {
3135b81b6b3SRodney W. Grimes 				db_error("invalid symbol table name");
3145b81b6b3SRodney W. Grimes 			}
3155b81b6b3SRodney W. Grimes 			symstr = cp+1;
3165b81b6b3SRodney W. Grimes 		}
3175b81b6b3SRodney W. Grimes 	}
3185b81b6b3SRodney W. Grimes 
3195b81b6b3SRodney W. Grimes 	/*
3205b81b6b3SRodney W. Grimes 	 * Look in the specified set of symbol tables.
3215b81b6b3SRodney W. Grimes 	 * Return on first match.
3225b81b6b3SRodney W. Grimes 	 */
3235b81b6b3SRodney W. Grimes 	for (i = symtab_start; i < symtab_end; i++) {
324169cd910SPoul-Henning Kamp 		sp = X_db_lookup(&db_symtabs[i], symstr);
325169cd910SPoul-Henning Kamp 		if (sp) {
3265b81b6b3SRodney W. Grimes 			db_last_symtab = &db_symtabs[i];
3275b81b6b3SRodney W. Grimes 			return sp;
3285b81b6b3SRodney W. Grimes 		}
3295b81b6b3SRodney W. Grimes 	}
3305b81b6b3SRodney W. Grimes 	return 0;
3315b81b6b3SRodney W. Grimes }
3325b81b6b3SRodney W. Grimes 
3335b81b6b3SRodney W. Grimes /*
3342b490bc7SPedro F. Giffuni  * If true, check across symbol tables for multiple occurrences
33594e24bf0SBruce Evans  * of a name.  Might slow things down quite a bit.
33694e24bf0SBruce Evans  */
337cd508278SPedro F. Giffuni static volatile bool db_qualify_ambiguous_names = false;
33894e24bf0SBruce Evans 
33994e24bf0SBruce Evans /*
3405b81b6b3SRodney W. Grimes  * Does this symbol name appear in more than one symbol table?
3415b81b6b3SRodney W. Grimes  * Used by db_symbol_values to decide whether to qualify a symbol.
3425b81b6b3SRodney W. Grimes  */
343cd508278SPedro F. Giffuni static bool
db_symbol_is_ambiguous(c_db_sym_t sym)344a41dd031SPedro F. Giffuni db_symbol_is_ambiguous(c_db_sym_t sym)
3455b81b6b3SRodney W. Grimes {
346a1c1e16aSMatthew Dillon 	const char	*sym_name;
3473e85b721SEd Maste 	int		i;
3483e85b721SEd Maste 	bool		found_once = false;
3495b81b6b3SRodney W. Grimes 
3505b81b6b3SRodney W. Grimes 	if (!db_qualify_ambiguous_names)
3512b490bc7SPedro F. Giffuni 		return (false);
3525b81b6b3SRodney W. Grimes 
3535b81b6b3SRodney W. Grimes 	db_symbol_values(sym, &sym_name, 0);
3545b81b6b3SRodney W. Grimes 	for (i = 0; i < db_nsymtab; i++) {
3555b81b6b3SRodney W. Grimes 		if (X_db_lookup(&db_symtabs[i], sym_name)) {
3565b81b6b3SRodney W. Grimes 			if (found_once)
357cd508278SPedro F. Giffuni 				return (true);
3582b490bc7SPedro F. Giffuni 			found_once = true;
3595b81b6b3SRodney W. Grimes 		}
3605b81b6b3SRodney W. Grimes 	}
3612b490bc7SPedro F. Giffuni 	return (false);
3625b81b6b3SRodney W. Grimes }
3635b81b6b3SRodney W. Grimes 
3645b81b6b3SRodney W. Grimes /*
3655b81b6b3SRodney W. Grimes  * Find the closest symbol to val, and return its name
3665b81b6b3SRodney W. Grimes  * and the difference between val and the symbol found.
3675b81b6b3SRodney W. Grimes  */
368fe08c21aSMatthew Dillon c_db_sym_t
db_search_symbol(db_addr_t val,db_strategy_t strategy,db_expr_t * offp)369a41dd031SPedro F. Giffuni db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
3705b81b6b3SRodney W. Grimes {
3715b81b6b3SRodney W. Grimes 	unsigned int	diff;
372ecbb00a2SDoug Rabson 	size_t		newdiff;
3733e85b721SEd Maste 	int		i;
3748310609fSEric van Gyzen 	c_db_sym_t	ret, sym;
3755b81b6b3SRodney W. Grimes 
3768310609fSEric van Gyzen 	/*
3778310609fSEric van Gyzen 	 * The kernel will never map the first page, so any symbols in that
3788310609fSEric van Gyzen 	 * range cannot refer to addresses.  Some third-party assembly files
3798310609fSEric van Gyzen 	 * define internal constants which appear in their symbol table.
3808310609fSEric van Gyzen 	 * Avoiding the lookup for those symbols avoids replacing small offsets
3818310609fSEric van Gyzen 	 * with those symbols during disassembly.
3828310609fSEric van Gyzen 	 */
3838310609fSEric van Gyzen 	if (val < PAGE_SIZE) {
3848310609fSEric van Gyzen 		*offp = 0;
3858310609fSEric van Gyzen 		return (C_DB_SYM_NULL);
3868310609fSEric van Gyzen 	}
3878310609fSEric van Gyzen 
3888310609fSEric van Gyzen 	ret = C_DB_SYM_NULL;
389ecb65f66SJohn Baldwin 	newdiff = diff = val;
3905b81b6b3SRodney W. Grimes 	for (i = 0; i < db_nsymtab; i++) {
3915b81b6b3SRodney W. Grimes 	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
392ecb65f66SJohn Baldwin 	    if ((uintmax_t)newdiff < (uintmax_t)diff) {
3935b81b6b3SRodney W. Grimes 		db_last_symtab = &db_symtabs[i];
3945b81b6b3SRodney W. Grimes 		diff = newdiff;
3955b81b6b3SRodney W. Grimes 		ret = sym;
3965b81b6b3SRodney W. Grimes 	    }
3975b81b6b3SRodney W. Grimes 	}
3985b81b6b3SRodney W. Grimes 	*offp = diff;
3995b81b6b3SRodney W. Grimes 	return ret;
4005b81b6b3SRodney W. Grimes }
4015b81b6b3SRodney W. Grimes 
4025b81b6b3SRodney W. Grimes /*
4035b81b6b3SRodney W. Grimes  * Return name and value of a symbol
4045b81b6b3SRodney W. Grimes  */
4055b81b6b3SRodney W. Grimes void
db_symbol_values(c_db_sym_t sym,const char ** namep,db_expr_t * valuep)406a41dd031SPedro F. Giffuni db_symbol_values(c_db_sym_t sym, const char **namep, db_expr_t *valuep)
4075b81b6b3SRodney W. Grimes {
4085b81b6b3SRodney W. Grimes 	db_expr_t	value;
4095b81b6b3SRodney W. Grimes 
4105b81b6b3SRodney W. Grimes 	if (sym == DB_SYM_NULL) {
4119f915a92SPedro F. Giffuni 		*namep = NULL;
4125b81b6b3SRodney W. Grimes 		return;
4135b81b6b3SRodney W. Grimes 	}
4145b81b6b3SRodney W. Grimes 
4156edf3d91SDoug Rabson 	X_db_symbol_values(db_last_symtab, sym, namep, &value);
4165b81b6b3SRodney W. Grimes 
4175b81b6b3SRodney W. Grimes 	if (db_symbol_is_ambiguous(sym))
4185b81b6b3SRodney W. Grimes 		*namep = db_qualify(sym, db_last_symtab->name);
4195b81b6b3SRodney W. Grimes 	if (valuep)
4205b81b6b3SRodney W. Grimes 		*valuep = value;
4215b81b6b3SRodney W. Grimes }
4225b81b6b3SRodney W. Grimes 
4235b81b6b3SRodney W. Grimes /*
4245b81b6b3SRodney W. Grimes  * Print a the closest symbol to value
4255b81b6b3SRodney W. Grimes  *
4265b81b6b3SRodney W. Grimes  * After matching the symbol according to the given strategy
4275b81b6b3SRodney W. Grimes  * we print it in the name+offset format, provided the symbol's
4285b81b6b3SRodney W. Grimes  * value is close enough (eg smaller than db_maxoff).
4295b81b6b3SRodney W. Grimes  * We also attempt to print [filename:linenum] when applicable
4305b81b6b3SRodney W. Grimes  * (eg for procedure names).
4315b81b6b3SRodney W. Grimes  *
4325b81b6b3SRodney W. Grimes  * If we could not find a reasonable name+offset representation,
4335b81b6b3SRodney W. Grimes  * then we just print the value in hex.  Small values might get
4345b81b6b3SRodney W. Grimes  * bogus symbol associations, e.g. 3 might get some absolute
4355b81b6b3SRodney W. Grimes  * value like _INCLUDE_VERSION or something, therefore we do
4367d350e72SBruce Evans  * not accept symbols whose value is "small" (and use plain hex).
4375b81b6b3SRodney W. Grimes  */
4385b81b6b3SRodney W. Grimes 
4393da6ef3cSBruce Evans db_expr_t	db_maxoff = 0x10000;
4405b81b6b3SRodney W. Grimes 
4415b81b6b3SRodney W. Grimes void
db_printsym(db_expr_t off,db_strategy_t strategy)442a41dd031SPedro F. Giffuni db_printsym(db_expr_t off, db_strategy_t strategy)
4435b81b6b3SRodney W. Grimes {
4445b81b6b3SRodney W. Grimes 	db_expr_t	d;
4455b81b6b3SRodney W. Grimes 	char 		*filename;
446a1c1e16aSMatthew Dillon 	const char	*name;
4475b81b6b3SRodney W. Grimes 	int 		linenum;
448fe08c21aSMatthew Dillon 	c_db_sym_t	cursym;
4495b81b6b3SRodney W. Grimes 
450f434f351SBruce Evans 	if (off < 0 && off >= -db_maxoff) {
451596dfc04SBruce Evans 		db_printf("%+#lr", (long)off);
4527d350e72SBruce Evans 		return;
4537d350e72SBruce Evans 	}
454f434f351SBruce Evans 	cursym = db_search_symbol(off, strategy, &d);
455f434f351SBruce Evans 	db_symbol_values(cursym, &name, NULL);
456f434f351SBruce Evans 	if (name == NULL || d >= (db_addr_t)db_maxoff) {
457596dfc04SBruce Evans 		db_printf("%#lr", (unsigned long)off);
4585b81b6b3SRodney W. Grimes 		return;
4595b81b6b3SRodney W. Grimes 	}
4609aece96fSPoul-Henning Kamp #ifdef DDB_NUMSYM
4619aece96fSPoul-Henning Kamp 	db_printf("%#lr = %s", (unsigned long)off, name);
4629aece96fSPoul-Henning Kamp #else
4635b81b6b3SRodney W. Grimes 	db_printf("%s", name);
4649aece96fSPoul-Henning Kamp #endif
4655b81b6b3SRodney W. Grimes 	if (d)
4661c6989faSPeter Wemm 		db_printf("+%+#lr", (long)d);
4675b81b6b3SRodney W. Grimes 	if (strategy == DB_STGY_PROC) {
4685b81b6b3SRodney W. Grimes 		if (db_line_at_pc(cursym, &filename, &linenum, off))
4695b81b6b3SRodney W. Grimes 			db_printf(" [%s:%d]", filename, linenum);
4705b81b6b3SRodney W. Grimes 	}
4715b81b6b3SRodney W. Grimes }
4725b81b6b3SRodney W. Grimes 
473cd508278SPedro F. Giffuni static bool
db_line_at_pc(c_db_sym_t sym,char ** filename,int * linenum,db_expr_t pc)474a41dd031SPedro F. Giffuni db_line_at_pc(c_db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
4755b81b6b3SRodney W. Grimes {
476cd508278SPedro F. Giffuni 	return (X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc));
4775b81b6b3SRodney W. Grimes }
478f7d75744SDavid Greenman 
479cd508278SPedro F. Giffuni bool
db_sym_numargs(c_db_sym_t sym,int * nargp,char ** argnames)480a41dd031SPedro F. Giffuni db_sym_numargs(c_db_sym_t sym, int *nargp, char **argnames)
481f7d75744SDavid Greenman {
482cd508278SPedro F. Giffuni 	return (X_db_sym_numargs(db_last_symtab, sym, nargp, argnames));
483f7d75744SDavid Greenman }
484754cb545SMitchell Horne 
485754cb545SMitchell Horne void
db_decode_syscall(struct thread * td,u_int number)486*aba921bdSMitchell Horne db_decode_syscall(struct thread *td, u_int number)
487754cb545SMitchell Horne {
488754cb545SMitchell Horne 	struct proc *p;
489754cb545SMitchell Horne 
490*aba921bdSMitchell Horne 	db_printf(" (%u", number);
491754cb545SMitchell Horne 	p = (td != NULL) ? td->td_proc : NULL;
492*aba921bdSMitchell Horne 	if (p != NULL) {
493*aba921bdSMitchell Horne 		db_printf(", %s, %s", p->p_sysent->sv_name,
494*aba921bdSMitchell Horne 		    syscallname(p, number));
495754cb545SMitchell Horne 	}
496754cb545SMitchell Horne 	db_printf(")");
497754cb545SMitchell Horne }
498