Bell 32V development
[unix-history] / usr / src / cmd / sdb / symt.c
CommitLineData
11bd4012
TL
1#include "head.h"
2#include <a.out.h>
3
4struct user u;
5int compar();
6
7/* initialize file and procedure tables */
8initfp() {
9 struct nlist stentry;
10 register struct proct *procp;
11 register struct filet *filep;
12 long soffset;
13 int i;
14 char class;
15 register char *p, *q;
16
17 sbuf.fd = txtmap.ufd;
18 soffset = ststart;
19 blseek(&sbuf,ststart,0);
20 filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
21 procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
22
23 for(;;) {
24 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) break;
25 class = stentry.n_type & STABMASK;
26 switch (class & STABMASK) {
27 case N_SO:
28 case N_SOL:
29 if (filep == badfile) {
30 p = sbrk(FILEINCR*sizeof filep[0]);
31 q = p + FILEINCR*sizeof filep[0];
32 while (p > (char *) procs)
33 *--q = *--p;
34 badfile += FILEINCR;
35 procp = (struct proct *)
36 ((char *) procp + FILEINCR*sizeof filep[0]);
37 procs = (struct proct *)
38 ((char *) procs + FILEINCR*sizeof filep[0]);
39 badproc = (struct proct *)
40 ((char *)badproc + FILEINCR*sizeof filep[0]);
41 }
42 filep->faddr = stentry.n_value;
43 filep->lineflag = (class == N_SOL);
44 filep->stf_offset = soffset;
45 p = filep->sfilename;
46 for (;;) {
47 for (i=0; i<8; i++) *p++ = stentry.n_name[i];
48 if (*(p-1) == '\0') break;
49 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
50 error("Bad N_SO entry (1)");
51 if ((stentry.n_type & STABMASK) != (unsigned char) class)
52 error("Bad N_SO entry (2)");
53 soffset += sizeof stentry;
54 }
55 filep++;
56 break;
57
58 case N_TEXT:
59 if (stentry.n_name[0] != '_') break;
60 case N_FUN:
61 if (procp == badproc) {
62 if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
63 perror("sdb");
64 exit(4);
65 }
66 badproc += PROCINCR;
67 }
68 for(i=0; i<8; i++)
69 procp->pname[i] = stentry.n_name[i];
70 procp->paddr = stentry.n_value;
71 procp->st_offset = soffset;
72 procp->sfptr = (class==N_FUN) ? filep - 1 : badfile;
73 procp->lineno = (class == N_FUN) ? stentry.n_desc : 0;
74 procp++;
75 break;
76 }
77 if (stentry.n_type & N_EXT && !extstart) {
78 extstart = soffset;
79 }
80 soffset += sizeof stentry;
81 }
82 qsort(procs, procp-procs, sizeof procs[0], compar);
83 badproc->sfptr = procp->sfptr = badfile;
84 badproc->pname[0] = badfile->sfilename[0]=
85 procp->pname[0] = filep->sfilename[0] = '\0';
86
87 setcur();
88}
89
90/* returns current procedure from state (curfile, fline) */
91struct proct
92*curproc() {
93 register int i;
94 register ADDR addr;
95
96/* The 'i' stuff is a kludge */
97 for (i = 0; i<10000; i++) {
98 addr = getaddr("", fline+i);
99 if (addr != -1) break;
100 }
101 if (addr == -1) return(badproc);
102 return(adrtoprocp(addr));
103
104}
105
106/* returns procedure s, uses curproc() if s == NULL */
107
108struct proct *
109findproc(s)
110char *s; {
111 register struct proct *p;
112
113 if (s[0] == '\0') return(curproc());
114
115 for(p=procs; p->pname[0]; p++)
116 if (eqstr(p->pname, s)) return(p);
117
118 if (debug) printf("%s(): unknown name\n", s);
119 return(badproc);
120}
121
122/* returns file s containing filename */
123struct filet *
124findfile(s)
125char *s; {
126 register struct filet *f;
127 for (f=files; f->sfilename[0]; f++) {
128 if (eqstr(f->sfilename, s)) {
129 for( ; f->lineflag; f--) ;
130 if (f < files) error("Bad file array");
131 return(f);
132 }
133 }
134 return(f);
135}
136
137/* looks up variable matching pat starting at offset in a.out, searching
138 * backwards, ignoring nested blocks to beginning to procedure.
139 * Returns its offset and symbol table entries decoded in sl_*
140 */
141
142slookup(pat, offset)
143register long offset; char *pat; {
144 register int level, i;
145 char class;
146 struct nlist stentry;
147 if (debug) printf("slookup(%s,%d)\n",pat,offset);
148
149 offset += sizeof stentry;
150 level = 0;
151 blseek(&sbuf, offset, 0);
152
153 for (;;) {
154 offset -= sizeof stentry;
155 if (offset < ststart) break;
156 if (bread(&sbuf, &stentry+1, -sizeof stentry) < sizeof stentry) break;
157 class = stentry.n_type & STABMASK;
158 switch (class & STABMASK) {
159 case 0:
160 break;
161 case N_FUN:
162 return(-1);
163 case N_RBRAC:
164 level++;
165 break;
166 case N_LBRAC:
167 level--;
168 break;
169 default:
170 if (level <= 0 && eqpat(pat, stentry.n_name)) {
171 if (class == N_LENG) {
172 sl_size = stentry.n_value;
173 offset -= sizeof stentry;
174 bread(&sbuf, &stentry+1, -sizeof stentry);
175 }
176 else sl_size = 0;
177 sl_class = stentry.n_type & STABMASK;
178 sl_type = stentry.n_desc;
179 sl_addr = stentry.n_value;
180 for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
181 return(offset);
182 }
183 }
184 }
185 return(-1);
186}
187
188/*
189 * Look up global variable matching pat
190 * Return its offset and symbol table entries decoded in sl_*
191 */
192globallookup(pat, filestart)
193char *pat; long filestart; {
194 register int offset, i;
195 struct nlist stentry;
196
197 if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
198 blseek(&sbuf, filestart, 0);
199 offset = filestart - sizeof stentry;
200 do {
201 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) return(-1);
202 offset += sizeof stentry;
203 } while ((stentry.n_type & STABMASK) == N_SO);
204 for (;;) {
205 if ((stentry.n_type & STABMASK) == N_SO) return(-1);
206 if ((eqpat(pat, stentry.n_name))) {
207 sl_class = stentry.n_type & STABMASK;
208 if (sl_class != N_GSYM && sl_class != N_SSYM &&
209 sl_class != N_STSYM) goto g1;
210 sl_size = 0;
211 sl_type = stentry.n_desc;
212 sl_addr = stentry.n_value;
213 for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
214 break;
215 }
216g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
217 return(-1);
218 offset += sizeof stentry;
219 }
220 bread(&sbuf, &stentry, sizeof stentry);
221 if (((stentry.n_type & STABMASK) == N_LENG) && (eqpat(pat, stentry.n_name)))
222 sl_size = stentry.n_value;
223
224 if (sl_class == N_GSYM) {
225 blseek(&sbuf, extstart, 0);
226 for(;;) {
227 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
228 return(-1);
229 if (stentry.n_name[0] != '_') continue;
230 if (eqpatr(pat, stentry.n_name+1, 1)) {
231 sl_addr = stentry.n_value;
232 break;
233 }
234 }
235 }
236 return(offset);
237}
238
239/* core address to procedure (pointer to proc array) */
240struct proct *
241adrtoproc(addr)
242ADDR addr; {
243 register struct proct *procp;
244 for (procp=procs; procp->pname[0]; procp++) {
245 if (procp->paddr > addr) break;
246 }
247 return (procp != procs ? procp-1 : badproc);
248}
249
250
251/* core address to file (pointer to file array) */
252struct filet *
253adrtofilep(addr)
254ADDR addr; {
255 register struct filet *filep;
256 for (filep=files; filep->sfilename[0]; filep++) {
257 if (filep->faddr > addr) break;
258 }
259 return (filep != files ? filep-1 : badfile);
260}
261
262/* core address to linenumber */
263long lastoffset;
264
265adrtolineno(addr)
266ADDR addr; {
267 register int lineno;
268 long offset;
269 struct nlist stentry;
270
271 lineno = lastoffset = -1;
272 offset = adrtoproc(addr)->st_offset;
273 blseek(&sbuf, offset, 0);
274 for (;;) {
275 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) break;
276 if (stentry.n_type == N_SLINE) {
277 if (stentry.n_value > addr) break;
278 lastoffset = offset;
279 lineno = stentry.n_desc;
280 }
281 offset += sizeof stentry;
282 }
283 return (lineno);
284}
285
286
287/* address to a.out offset */
288long
289adrtostoffset(addr)
290ADDR addr; {
291 adrtolineno(addr);
292 return(lastoffset);
293}
294
295
296/*
297 * Set (curfile, lineno) from core image.
298 * Returns 1 if there is a core image, 0 otherwise.
299 */
300setcur() {
301 register struct proct *procp;
302
303 dot = *(ADDR *) (((ADDR) &u) + PC);
304
305 if (dot == 0) {
306 printf("No core image\n");
307 goto setmain;
308 }
309 procp = adrtoprocp(dot);
310 if ((procp->sfptr) != badfile) {
311 finit(adrtofilep(dot)->sfilename);
312 ffind(adrtolineno(dot));
313 printf("%.8s:", procp->pname);
314 fprint();
315 return(1);
316 }
317 if (procp->pname[0] == '_')
318 printf("%.7s: address 0x%x\n", procp->pname+1, dot);
319 else
320 printf("%.8s: address %d\n", procp->pname, dot);
321
322setmain:
323 procp = findproc("main");
324 if ((procp->pname[0] == 'm') && (procp->sfptr != badfile)) {
325 finit(procp->sfptr->sfilename);
326 ffind(procp->lineno);
327/*
328 printf("main() in \"%s\"\n", curfile);
329*/
330 }
331 else printf("main not compiled with debug flag\n");
332 return(0);
333}
334
335compar(a, b)
336struct proct *a, *b; {
337 if (a->paddr == b->paddr)
338 return(a->pname[0] == '_' ? -1 : 1);
339 return(a->paddr < b->paddr ? -1 : 1);
340}
341
342/* gets offset of file or procedure named s */
343nametooffset(s)
344char *s; {
345 register struct filet *f;
346 register struct proct *p;
347
348 if (eqany('.', s)) {
349 f = findfile(s);
350 return(f->sfilename[0] ? f->stf_offset : -1);
351 }
352 p = findproc(s);
353 return(p->pname[0] ? p->st_offset : -1);
354}
355
356
357/* line number to address, starting at offset in a.out */
358/* THIS SHOULD BE FIXED TO KNOW ABOUT #line FILES */
359lntoaddr(lineno, offset)
360long offset; {
361 struct nlist stentry;
362
363 blseek(&sbuf, offset, 0);
364
365 do {
366 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) return(-1);
367 } while ((stentry.n_type & STABMASK) == N_SO);
368 for (;;) {
369 switch(stentry.n_type & STABMASK) {
370 case N_SLINE:
371 if (stentry.n_desc == lineno) return(stentry.n_value);
372 break;
373 case N_SO:
374 return(-1);
375 }
376 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) break;
377 }
378 return(-1);
379}
380
381/* gets address of proc:number */
382getaddr(proc,integ)
383char *proc; {
384 register long offset;
385 register char *s;
386 ADDR addr;
387
388 s = proc[0] ? proc : curfile;
389 offset = nametooffset(s);
390 if (debug) printf("getaddr() computed offset %d", offset);
391 if (offset == -1) {
392 addr = extaddr(proc);
393 if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
394 if (debug) printf(" extaddr computed %d\n", addr);
395 return(addr);
396 }
397 if (integ)
398 addr = lntoaddr(integ, offset);
399 else {
400 addr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
401 addr = lntoaddr(adrtolineno(addr)+1, offset);
402 }
403 if (debug) printf(" and addr %d\n", addr);
404 if (addr == -1) return(-1);
405 return(addr);
406}
407
408/* returns address of external */
409ADDR
410extaddr(name)
411char *name; {
412 struct nlist stentry;
413 blseek(&sbuf, extstart, 0);
414
415 for (;;) {
416 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
417 return(-1);
418 if (stentry.n_name[0] == '_' &&
419 eqpatr(name, stentry.n_name+1, 1))
420 return(stentry.n_value);
421 }
422}