xref: /original-bsd/old/adb/common_source/sym.c (revision a1c2194a)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)sym.c	5.3 (Berkeley) 04/04/91";
10 #endif /* not lint */
11 
12 /*
13  * adb - symbol table routines
14  */
15 #include "defs.h"
16 #include <stab.h>
17 
18 #define	isstab(sp)	((sp)->n_type & N_STAB)
19 
20 /*
21  * Lookup a symbol by name.
22  */
23 struct nlist *
24 lookup(symstr)
25 	register char *symstr;
26 {
27 	register struct nlist *sp;
28 
29 	if (symtab)
30 		for (sp = symtab; sp < esymtab; sp++)
31 			if (!isstab(sp) && eqsym(sp->n_un.n_name, symstr, '_'))
32 				return (sp);
33 	return (0);
34 }
35 
36 /*
37  * Find the closest symbol to val, and return it and (through
38  * diffp) the difference between val and the symbol found.
39  */
40 struct nlist *
41 findsym(val, space, diffp)
42 	register addr_t val;
43 	int space;
44 	addr_t *diffp;
45 {
46 	register struct nlist *sp;
47 	register addr_t diff;
48 	struct nlist *sym;
49 
50 	diff = ~(addr_t)0;
51 	sym = NULL;
52 	if (space != SP_NONE && symtab != NULL) {
53 		for (sp = symtab; sp < esymtab; sp++) {
54 			/* must be global */
55 			if (isstab(sp) || (sp->n_type & N_EXT) == 0)
56 				continue;
57 			/* and not a function */
58 			if (sp->n_type == (N_FN|N_EXT))
59 				continue;
60 			/* and have a greater address */
61 			if (val < sp->n_value)
62 				continue;
63 			/* and be closer than the last one */
64 			if (val - sp->n_value >= diff)
65 				continue;
66 			sym = sp;
67 			diff = val - sp->n_value;
68 			if (diff == 0)
69 				break;
70 		}
71 	}
72 	*diffp = diff;
73 	return (sym);
74 }
75 
76 /*
77  * Return the next local symbol after sym, or NULL at end of such locals.
78  */
79 /* ARGSUSED */
80 struct nlist *
81 nextlocal(sym)
82 	struct nlist *sym;
83 {
84 
85 #ifdef busted
86 	/*
87 	 * none of this works at the moment, because the symbols are not in
88 	 * the desired order.
89 	 */
90 	if (sym == NULL)
91 		return (NULL);
92 	while (++sym < esymtab) {
93 		/*
94 		 * External and file name symbols terminate the
95 		 * list of local symbols.  Otherwise, if it is
96 		 * a .stabs parameter or local symbol, take it.
97 		 */
98 		if ((sym->n_type & N_EXT) || sym->n_type == N_FN)
99 			break;
100 		if (sym->n_type == N_LSYM || sym->n_type == N_PSYM)
101 			return (sym);
102 	}
103 #endif
104 	return (NULL);
105 }
106 
107 /*
108  * Print value v (in format f) and then (as another format) s.
109  * If v is not zero, we look for a nearby symbol and print name+offset
110  * if we find a symbol whose offset is small enough (less than o).
111  */
112 psymoff(f, v, space, o, s)
113 	char *f;
114 	addr_t v;
115 	int space;
116 	addr_t o;
117 	char *s;
118 {
119 	struct nlist *sp;
120 	addr_t offset;
121 
122 	if (v && (sp = findsym(v, space, &offset)) != NULL && offset < o)
123 		adbprintf("%s%?+R", sp->n_un.n_name,
124 			offset != 0, (expr_t)offset);
125 	else
126 		adbprintf(f, (expr_t)v);
127 	adbprintf(s);
128 }
129 
130 /*
131  * Print value v symbolically if it has a reasonable
132  * interpretation as name+offset.  If not, print nothing.
133  * Used in printing out registers $r.
134  */
135 valpr(v, space)
136 	addr_t v;
137 	int space;
138 {
139 	struct nlist *sp;
140 	addr_t offset;
141 
142 	if (v && (sp = findsym(v, space, &offset)) != NULL && offset < maxoff)
143 		adbprintf("%s%?+R", sp->n_un.n_name,
144 			offset != 0, (expr_t)offset);
145 }
146