db_sym.c revision 1.4
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19 *  School of Computer Science
20 *  Carnegie Mellon University
21 *  Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26/*
27 * db_sym.c,v 1.2 1993/05/20 03:39:31 cgd Exp
28 *
29 * HISTORY
30 * db_sym.c,v
31 * Revision 1.2  1993/05/20  03:39:31  cgd
32 * add explicit rcs id
33 *
34 * Revision 1.1.1.1  1993/03/21  09:46:27  cgd
35 * initial import of 386bsd-0.1 sources
36 *
37 * Revision 1.1  1992/03/25  21:45:27  pace
38 * Initial revision
39 *
40 * Revision 2.5  91/02/05  17:07:07  mrt
41 * 	Changed to new Mach copyright
42 * 	[91/01/31  16:19:17  mrt]
43 *
44 * Revision 2.4  90/10/25  14:44:05  rwd
45 * 	Changed db_printsym to print unsigned.
46 * 	[90/10/19            rpd]
47 *
48 * Revision 2.3  90/09/09  23:19:56  rpd
49 * 	Avoid totally incorrect guesses of symbol names for small values.
50 * 	[90/08/30  17:39:48  af]
51 *
52 * Revision 2.2  90/08/27  21:52:18  dbg
53 * 	Removed nlist.h.  Fixed some type declarations.
54 * 	Qualifier character is ':'.
55 * 	[90/08/20            dbg]
56 * 	Modularized symtab info into a new db_symtab_t type.
57 * 	Modified db_add_symbol_table  and others accordingly.
58 * 	Defined db_sym_t, a new (opaque) type used to represent
59 * 	symbols.  This should support all sort of future symtable
60 * 	formats. Functions like db_qualify take a db_sym_t now.
61 * 	New db_symbol_values() function to explode the content
62 * 	of a db_sym_t.
63 * 	db_search_symbol() replaces db_find_sym_and_offset(), which is
64 * 	now a macro defined in our (new) header file.  This new
65 * 	function accepts more restrictive searches, which are
66 * 	entirely delegated to the symtab-specific code.
67 * 	Accordingly, db_printsym() accepts a strategy parameter.
68 * 	New db_line_at_pc() function.
69 * 	Renamed misleading db_eqsym into db_eqname.
70 * 	[90/08/20  10:47:06  af]
71 *
72 * 	Created.
73 * 	[90/07/25            dbg]
74 *
75 * Revision 2.1  90/07/26  16:43:52  dbg
76 * Created.
77 *
78 */
79/*
80 * 	Author: David B. Golub, Carnegie Mellon University
81 *	Date:	7/90
82 */
83#include "param.h"
84#include "proc.h"
85#include <machine/db_machdep.h>
86#include <ddb/db_sym.h>
87
88/*
89 * We import from the symbol-table dependent routines:
90 */
91extern db_sym_t	X_db_lookup();
92extern db_sym_t	X_db_search_symbol();
93extern boolean_t X_db_line_at_pc();
94extern void	X_db_symbol_values();
95
96/*
97 * Multiple symbol tables
98 */
99#ifndef MAXLKMS
100#define MAXLKMS 20
101#endif
102
103#ifndef MAXNOSYMTABS
104#define	MAXNOSYMTABS	MAXLKMS+1	/* Room for kernel + LKM's */
105#endif
106
107db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
108
109db_symtab_t	*db_last_symtab;
110
111db_sym_t	db_lookup();	/* forward */
112
113/*
114 * Add symbol table, with given name, to list of symbol tables.
115 */
116int
117db_add_symbol_table(start, end, name, ref)
118	char *start;
119	char *end;
120	char *name;
121	char *ref;
122{
123	int slot;
124
125	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
126		if (db_symtabs[slot].name == NULL)
127			break;
128	}
129	if (slot >= MAXNOSYMTABS) {
130		printf ("No slots left for %s symbol table", name);
131		return(-1);
132	}
133
134	db_symtabs[slot].start = start;
135	db_symtabs[slot].end = end;
136	db_symtabs[slot].name = name;
137	db_symtabs[slot].private = ref;
138
139	return(slot);
140}
141
142/*
143 * Delete a symbol table. Caller is responsible for freeing storage.
144 */
145void
146db_del_symbol_table(name)
147	char *name;
148{
149	int slot;
150
151	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
152		if (db_symtabs[slot].name &&
153		    ! strcmp(db_symtabs[slot].name, name))
154			break;
155	}
156	if (slot >= MAXNOSYMTABS) {
157		printf ("Unable to find symbol table slot for %s.", name);
158		return;
159	}
160
161	db_symtabs[slot].start = 0;
162	db_symtabs[slot].end = 0;
163	db_symtabs[slot].name = 0;
164	db_symtabs[slot].private = 0;
165}
166
167/*
168 *  db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
169 *
170 *  Note: return value points to static data whose content is
171 *  overwritten by each call... but in practice this seems okay.
172 */
173static char *
174db_qualify(sym, symtabname)
175	db_sym_t	sym;
176	register char	*symtabname;
177{
178	char		*symname;
179	static char     tmp[256];
180	register char	*s;
181
182	db_symbol_values(sym, &symname, 0);
183	s = tmp;
184	while (*s++ = *symtabname++) {
185	}
186	s[-1] = ':';
187	while (*s++ = *symname++) {
188	}
189	return tmp;
190}
191
192
193boolean_t
194db_eqname(src, dst, c)
195	char *src;
196	char *dst;
197	char c;
198{
199	if (!strcmp(src, dst))
200	    return (TRUE);
201	if (src[0] == c)
202	    return (!strcmp(src+1,dst));
203	return (FALSE);
204}
205
206boolean_t
207db_value_of_name(name, valuep)
208	char		*name;
209	db_expr_t	*valuep;
210{
211	db_sym_t	sym;
212
213	sym = db_lookup(name);
214	if (sym == DB_SYM_NULL)
215	    return (FALSE);
216	db_symbol_values(sym, &name, valuep);
217	return (TRUE);
218}
219
220
221/*
222 * Lookup a symbol.
223 * If the symbol has a qualifier (e.g., ux:vm_map),
224 * then only the specified symbol table will be searched;
225 * otherwise, all symbol tables will be searched.
226 */
227db_sym_t
228db_lookup(symstr)
229	char *symstr;
230{
231	db_sym_t sp;
232	register int i;
233	int symtab_start = 0;
234	int symtab_end = MAXNOSYMTABS;
235	register char *cp;
236
237	/*
238	 * Look for, remove, and remember any symbol table specifier.
239	 */
240	for (cp = symstr; *cp; cp++) {
241		if (*cp == ':') {
242			*cp = '\0';
243			for (i = 0; i < MAXNOSYMTABS; i++) {
244				if (db_symtabs[i].name &&
245				    ! strcmp(symstr, db_symtabs[i].name)) {
246					symtab_start = i;
247					symtab_end = i + 1;
248					break;
249				}
250			}
251			*cp = ':';
252			if (i == MAXNOSYMTABS) {
253				db_error("invalid symbol table name");
254			}
255			symstr = cp+1;
256		}
257	}
258
259	/*
260	 * Look in the specified set of symbol tables.
261	 * Return on first match.
262	 */
263	for (i = symtab_start; i < symtab_end; i++) {
264		if (db_symtabs[i].name &&
265		    (sp = X_db_lookup(&db_symtabs[i], symstr))) {
266			db_last_symtab = &db_symtabs[i];
267			return sp;
268		}
269	}
270	return 0;
271}
272
273/*
274 * Does this symbol name appear in more than one symbol table?
275 * Used by db_symbol_values to decide whether to qualify a symbol.
276 */
277boolean_t db_qualify_ambiguous_names = FALSE;
278
279boolean_t
280db_symbol_is_ambiguous(sym)
281	db_sym_t	sym;
282{
283	char		*sym_name;
284	register int	i;
285	register
286	boolean_t	found_once = FALSE;
287
288	if (!db_qualify_ambiguous_names)
289		return FALSE;
290
291	db_symbol_values(sym, &sym_name, 0);
292	for (i = 0; i < MAXNOSYMTABS; i++) {
293		if (db_symtabs[i].name &&
294		    X_db_lookup(&db_symtabs[i], sym_name)) {
295			if (found_once)
296				return TRUE;
297			found_once = TRUE;
298		}
299	}
300	return FALSE;
301}
302
303/*
304 * Find the closest symbol to val, and return its name
305 * and the difference between val and the symbol found.
306 */
307db_sym_t
308db_search_symbol( val, strategy, offp)
309	register db_addr_t	val;
310	db_strategy_t		strategy;
311	db_expr_t		*offp;
312{
313	register
314	unsigned int	diff;
315	unsigned int	newdiff;
316	register int	i;
317	db_sym_t	ret = DB_SYM_NULL, sym;
318
319	newdiff = diff = ~0;
320	db_last_symtab = 0;
321	for (i = 0; i < MAXNOSYMTABS; i++) {
322	    if (!db_symtabs[i].name)
323	        continue;
324	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
325	    if (newdiff < diff) {
326		db_last_symtab = &db_symtabs[i];
327		diff = newdiff;
328		ret = sym;
329	    }
330	}
331	*offp = diff;
332	return ret;
333}
334
335/*
336 * Return name and value of a symbol
337 */
338void
339db_symbol_values(sym, namep, valuep)
340	db_sym_t	sym;
341	char		**namep;
342	db_expr_t	*valuep;
343{
344	db_expr_t	value;
345
346	if (sym == DB_SYM_NULL) {
347		*namep = 0;
348		return;
349	}
350
351	X_db_symbol_values(sym, namep, &value);
352
353	if (db_symbol_is_ambiguous(sym))
354		*namep = db_qualify(sym, db_last_symtab->name);
355	if (valuep)
356		*valuep = value;
357}
358
359
360/*
361 * Print a the closest symbol to value
362 *
363 * After matching the symbol according to the given strategy
364 * we print it in the name+offset format, provided the symbol's
365 * value is close enough (eg smaller than db_maxoff).
366 * We also attempt to print [filename:linenum] when applicable
367 * (eg for procedure names).
368 *
369 * If we could not find a reasonable name+offset representation,
370 * then we just print the value in hex.  Small values might get
371 * bogus symbol associations, e.g. 3 might get some absolute
372 * value like _INCLUDE_VERSION or something, therefore we do
373 * not accept symbols whose value is zero (and use plain hex).
374 */
375
376unsigned int	db_maxoff = 0x10000000;
377
378void
379db_printsym(off, strategy)
380	db_expr_t	off;
381	db_strategy_t	strategy;
382{
383	db_expr_t	d;
384	char 		*filename;
385	char		*name;
386	db_expr_t	value;
387	int 		linenum;
388	db_sym_t	cursym;
389
390	cursym = db_search_symbol(off, strategy, &d);
391	db_symbol_values(cursym, &name, &value);
392	if (name == 0 || d >= db_maxoff || value == 0) {
393		db_printf("%#n", off);
394		return;
395	}
396	db_printf("%s", name);
397	if (d)
398		db_printf("+%#r", d);
399	if (strategy == DB_STGY_PROC) {
400		if (db_line_at_pc(cursym, &filename, &linenum, off))
401			db_printf(" [%s:%d]", filename, linenum);
402	}
403}
404
405
406boolean_t
407db_line_at_pc( sym, filename, linenum, pc)
408	db_sym_t	sym;
409	char		**filename;
410	int		*linenum;
411	db_expr_t	pc;
412{
413	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
414}
415
416int
417db_sym_numargs(sym, nargp, argnames)
418	db_sym_t	sym;
419	int		*nargp;
420	char		**argnames;
421{
422	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
423}
424