Commit | Line | Data |
---|---|---|
7222ebf4 BJ |
1 | static char sccsid[] = "@(#)sym.c 4.1 %G%"; |
2 | /* | |
3 | * adb - symbol table routines | |
4 | */ | |
5 | #include "defs.h" | |
6 | #include <stab.h> | |
7 | ||
8 | /* | |
9 | * Lookup a symbol by name. | |
10 | */ | |
11 | struct nlist * | |
12 | lookup(symstr) | |
13 | char *symstr; | |
14 | { | |
15 | register struct nlist *sp; | |
16 | ||
17 | cursym = 0; | |
18 | if (symtab) | |
19 | for (sp = symtab; sp < esymtab; sp++) | |
20 | /* SHOULD DO SOME OF EQSYM INLINE TO SAVE TIME */ | |
21 | if ((sp->n_type&N_STAB)==0 && eqsym(sp->n_un.n_name, symstr, '_')) | |
22 | return(cursym = sp); | |
23 | return (0); | |
24 | } | |
25 | ||
26 | /* | |
27 | * Find the closest symbol to val, and return | |
28 | * the difference between val and the symbol found. | |
29 | * Leave a pointer to the symbol found as cursym. | |
30 | */ | |
31 | findsym(val, type) | |
32 | long val; | |
33 | int type; | |
34 | { | |
35 | long diff; | |
36 | register struct nlist *sp; | |
37 | ||
38 | cursym = 0; | |
39 | diff = MAXINT; | |
40 | if (type == NSYM || symtab == 0) | |
41 | return (diff); | |
42 | for (sp = symtab; sp < esymtab; sp++) { | |
43 | if (sp->n_type&N_STAB || (sp->n_type&N_EXT)==0) | |
44 | continue; | |
45 | if (val - sp->n_value < diff && val >= sp->n_value) { | |
46 | diff = val - sp->n_value; | |
47 | cursym = sp; | |
48 | if (diff == 0) | |
49 | break; | |
50 | } | |
51 | } | |
52 | return (diff); | |
53 | } | |
54 | ||
55 | /* | |
56 | * Advance cursym to the next local variable. | |
57 | * Leave its value in localval as a side effect. | |
58 | * Return 0 at end of file. | |
59 | */ | |
60 | localsym(cframe, cargp) | |
61 | ADDR cframe, cargp; | |
62 | { | |
63 | register int type; | |
64 | register struct nlist *sp; | |
65 | ||
66 | if (cursym) | |
67 | for (sp = cursym; ++sp < esymtab; ) { | |
68 | if (sp->n_un.n_name[0] =='_' || sp->n_type == N_FN) | |
69 | return (0); | |
70 | type = sp->n_type; | |
71 | switch (sp->n_type) { | |
72 | ||
73 | case N_TEXT: | |
74 | case N_TEXT|N_EXT: | |
75 | case N_DATA: | |
76 | case N_DATA|N_EXT: | |
77 | case N_BSS: | |
78 | case N_BSS|N_EXT: | |
79 | localval = sp->n_value; | |
80 | cursym = sp; | |
81 | return (1); | |
82 | ||
83 | case N_LSYM: | |
84 | localval = cframe - sp->n_value; | |
85 | cursym = sp; | |
86 | return (1); | |
87 | ||
88 | case N_PSYM: | |
89 | /* code below works since n_value > 0 */ | |
90 | case N_ABS: | |
91 | if (sp->n_value < 0) | |
92 | localval = cframe + sp->n_value; | |
93 | else | |
94 | localval = cargp + sp->n_value; | |
95 | cursym = sp; | |
96 | return (1); | |
97 | } | |
98 | } | |
99 | cursym = 0; | |
100 | return (0); | |
101 | } | |
102 | ||
103 | /* | |
104 | * Print value v and then the string s. | |
105 | * If v is not zero, then we look for a nearby symbol | |
106 | * and print name+offset if we find a symbol for which | |
107 | * offset is small enough. | |
108 | * | |
109 | * For values which are just into kernel address space | |
110 | * that they match exactly or that they be more than maxoff | |
111 | * bytes into kernel space. | |
112 | */ | |
113 | psymoff(v, type, s) | |
114 | long v; | |
115 | int type; | |
116 | char *s; | |
117 | { | |
118 | long w; | |
119 | ||
120 | if (v) | |
121 | w = findsym(v, type); | |
122 | if (v==0 || w >= maxoff || (KVTOPH(v) < maxoff && w)) | |
123 | printf(LPRMODE, v); | |
124 | else { | |
125 | printf("%s", cursym->n_un.n_name); | |
126 | if (w) | |
127 | printf(OFFMODE, w); | |
128 | } | |
129 | printf(s); | |
130 | } | |
131 | ||
132 | /* | |
133 | * Print value v symbolically if it has a reasonable | |
134 | * interpretation as name+offset. If not, print nothing. | |
135 | * Used in printing out registers $r. | |
136 | */ | |
137 | valpr(v, idsp) | |
138 | long v; | |
139 | { | |
140 | off_t d; | |
141 | ||
142 | d = findsym(v, idsp); | |
143 | if (d >= maxoff) | |
144 | return; | |
145 | printf("%s", cursym->n_un.n_name); | |
146 | if (d) | |
147 | printf(OFFMODE, d); | |
148 | } |