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