BSD 3 development
[unix-history] / usr / src / cmd / sdb / symt.c.old
CommitLineData
b4484850
HK
1#include "head.h"
2#include <a.out.h>
3#include <sys/stat.h>
4
5struct user u;
6int compar();
7char *symfil;
8
9/* initialize file and procedure tables */
10initfp() {
11 struct nlist stentry;
12 register struct proct *procp;
13 register struct filet *filep;
14 struct stat stbuf;
15
16 long soffset;
17 int i;
18 char class;
19 register char *p, *q;
20
21 sbuf.fd = txtmap.ufd;
22 soffset = ststart;
23 blseek(&sbuf,ststart,0);
24 filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
25 procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
26
27 for(;;) {
28 if (bread(&sbuf, &stentry, sizeof stentry) <
29 sizeof stentry) break;
30 class = stentry.n_type & STABMASK;
31 switch (class & STABMASK) {
32 case N_SO:
33 case N_SOL:
34 if (filep == badfile) {
35 p = sbrk(FILEINCR*sizeof filep[0]);
36 if (p < 0) {
37 perror("sdb");
38 exit(4);
39 }
40 q = p + FILEINCR*sizeof filep[0];
41 while (p > (char *) procs)
42 *--q = *--p;
43 badfile += FILEINCR;
44 procp = (struct proct *)
45 ((char *) procp +
46 FILEINCR*sizeof filep[0]);
47 procs = (struct proct *)
48 ((char *) procs +
49 FILEINCR*sizeof filep[0]);
50 badproc = (struct proct *)
51 ((char *)badproc +
52 FILEINCR*sizeof filep[0]);
53 }
54 filep->faddr = stentry.n_value;
55 filep->lineflag = (class == N_SOL);
56 filep->stf_offset = soffset;
57 p = filep->sfilename;
58 for (;;) {
59 for (i=0; i<8; i++) *p++ = stentry.n_name[i];
60 if (*(p-1) == '\0') break;
61 if (bread(&sbuf, &stentry, sizeof stentry)
62 < sizeof stentry)
63 error("Bad N_SO entry (1)");
64 if ((stentry.n_type & STABMASK) !=
65 (unsigned char) class)
66 error("Bad N_SO entry (2)");
67 soffset += sizeof stentry;
68 }
69 if (stat(filep->sfilename, &stbuf) == -1)
70 printf("Warning: `%s' not found\n",
71 filep->sfilename);
72 else if (stbuf.st_mtime > symtime)
73 printf("Warning: `%s' newer than `%s'\n",
74 filep->sfilename,
75 symfil);
76 filep++;
77 break;
78
79 case N_TEXT:
80 if (stentry.n_name[0] != '_') break;
81 case N_FUN:
82 case N_ENTRY:
83 if (procp == badproc) {
84 if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
85 perror("sdb");
86 exit(4);
87 }
88 badproc += PROCINCR;
89 }
90 for(i=0; i<8; i++)
91 procp->pname[i] = stentry.n_name[i];
92 procp->paddr = stentry.n_value;
93 procp->st_offset = soffset;
94 procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
95 procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
96 procp->entrypt = (class & STABMASK) == N_ENTRY;
97 procp++;
98 break;
99 }
100 if (stentry.n_type & N_EXT && !extstart) {
101 extstart = soffset;
102 }
103 soffset += sizeof stentry;
104 }
105 qsort(procs, procp-procs, sizeof procs[0], compar);
106 badproc->st_offset = soffset;
107 badproc->sfptr = procp->sfptr = badfile;
108 badproc->pname[0] = badfile->sfilename[0]=
109 procp->pname[0] = filep->sfilename[0] = '\0';
110
111 setcur(1);
112}
113
114/* returns current procedure from state (curfile, fline) */
115struct proct *
116curproc() {
117 register ADDR addr;
118
119 addr = getaddr("", fline);
120 if (addr == -1) return(badproc);
121 return(adrtoprocp(addr));
122
123}
124
125/* returns procedure s, uses curproc() if s == NULL */
126
127struct proct *
128findproc(s)
129char *s; {
130 register struct proct *p;
131
132 if (s[0] == '\0') return(curproc());
133
134 for(p=procs; p->pname[0]; p++)
135 if (eqstr(p->pname, s)) return(p);
136
137 if (debug) printf("%s(): unknown name\n", s);
138 return(badproc);
139}
140
141/* returns file s containing filename */
142struct filet *
143findfile(s)
144char *s; {
145 register struct filet *f;
146 for (f=files; f->sfilename[0]; f++) {
147 if (eqstr(f->sfilename, s)) {
148 for( ; f->lineflag; f--) ;
149 if (f < files) error("Bad file array");
150 return(f);
151 }
152 }
153 return(f);
154}
155
156/*
157 * slookup():
158 * looks up variable matching pat starting at offset in a.out, searching
159 * backwards, ignoring nested blocks to beginning to procedure.
160 * Returns its offset and symbol table entries decoded in sl_*
161 *
162 * If comblk == "*" then match both within and outside common blocks,
163 * if comblk == "" then match only outside common blocks,
164 * else match only within comblk.
165 */
166
167long
168slookup(pat, poffset, stelt)
169long poffset; char *pat; {
170 slookinit();
171 slooknext(pat, poffset, stelt, "*");
172}
173
174int clevel, level, fnameflag, comfound, incomm;
175
176slookinit() {
177 clevel = level = fnameflag = comfound = incomm = 0;
178}
179
180long
181slooknext(pat, poffset, stelt, comblk)
182long poffset; char *pat, *comblk; {
183 register int i;
184 register long offset;
185 char class, *q;
186 struct nlist stentry;
187 struct proct *procp, *p;
188
189 offset = poffset + sizeof stentry;
190 if (debug) printf("slookup(%s,%d)\n",pat,offset);
191 blseek(&sbuf, offset, 0);
192
193 for (;;) {
194 offset -= sizeof stentry;
195 if (offset < ststart) break;
196 if (bread(&sbuf, &stentry+1, -sizeof stentry)
197 < sizeof stentry) break;
198 class = stentry.n_type & STABMASK;
199 switch (class & STABMASK) {
200 case 0:
201 break;
202 case N_FUN:
203 return(-1);
204 case N_RBRAC:
205 level++;
206 break;
207 case N_LBRAC:
208 level--;
209 break;
210 case N_ECOMM:
211 for (q = &stentry.n_name[7]; q>=stentry.n_name; q--) {
212 if (*q == '_') {
213 *q = '\0';
214 break;
215 }
216 }
217 if (eqpat(comblk, stentry.n_name))
218 comfound = 1;
219 incomm = 1;
220 case N_ECOML:
221 clevel++;
222 break;
223 case N_BCOMM:
224 comfound = incomm = 0;
225 clevel--;
226 break;
227 case N_FNAME:
228 if (fnameflag)
229 break;
230 procp = findproc(stentry.n_name);
231 for (p=procs; p->pname[0]; p++) {
232 if (p->entrypt == 0 &&
233 p->st_offset > procp->st_offset &&
234 p->st_offset < offset)
235 offset = p->st_offset;
236 }
237 clevel = level = 0;
238 fnameflag++;
239 blseek(&sbuf, offset, 0);
240 break;
241 default:
242 if (level <= 0 && eqpat(pat, stentry.n_name) &&
243 stentry.n_name[0] && class & STABTYPES &&
244 (eqstr("*", comblk) ||
245 (comblk[0] == '\0' && incomm == 0) ||
246 comfound) &&
247 (stelt == (class == N_SSYM))) {
248 if (class == N_LENG) {
249 sl_size = stentry.n_value;
250 offset -= sizeof stentry;
251 bread(&sbuf, &stentry+1,
252 -sizeof stentry);
253 }
254 else sl_size = 0;
255 sl_class = stentry.n_type & STABMASK;
256 sl_type = stentry.n_desc;
257 sl_addr = stentry.n_value;
258 for (i=0; i<8; i++) sl_name[i] =
259 stentry.n_name[i];
260 if (clevel != 0) docomm(offset);
261 return(offset - sizeof stentry);
262 }
263 }
264 }
265 return(-1);
266}
267
268/*
269 * Look up global variable matching pat
270 * Return its offset and symbol table entries decoded in sl_*
271 */
272long
273globallookup(pat, filestart, stelt)
274char *pat; long filestart; {
275 register int offset, i;
276 struct nlist stentry;
277 int class, clevel;
278
279 if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
280 blseek(&sbuf, filestart, 0);
281 offset = filestart - sizeof stentry;
282 clevel = 0;
283 do {
284 if (bread(&sbuf, &stentry, sizeof stentry) <
285 sizeof stentry) return(-1);
286 offset += sizeof stentry;
287 } while ((stentry.n_type & STABMASK) == N_SO);
288 for (;;) {
289 class = stentry.n_type & STABMASK;
290 switch (class & STABMASK) {
291 case N_SO:
292 return(-1);
293 case N_ECOMM:
294 clevel--;
295 break;
296 case N_BCOMM:
297 clevel++;
298 break;
299 default:
300 if (eqpat(pat, stentry.n_name)
301 && stentry.n_name[0] && class & STABTYPES) {
302 sl_class = stentry.n_type & STABMASK;
303 if (sl_class != N_GSYM && sl_class != N_SSYM &&
304 sl_class != N_STSYM) goto g1;
305 if (stelt != (sl_class == N_SSYM)) goto g1;
306 sl_size = 0;
307 sl_type = stentry.n_desc;
308 sl_addr = stentry.n_value;
309 for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
310 if (clevel != 0) docomm(offset);
311 goto g2;
312 }
313 }
314g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
315 return(-1);
316 offset += sizeof stentry;
317 }
318g2: bread(&sbuf, &stentry, sizeof stentry);
319 if (((stentry.n_type & STABMASK) == N_LENG) &&
320 (eqpat(sl_name, stentry.n_name)))
321 sl_size = stentry.n_value;
322
323 if (sl_class == N_GSYM && (clevel == 0)) {
324 blseek(&sbuf, extstart, 0);
325 for(;;) {
326 if (bread(&sbuf, &stentry, sizeof stentry)
327 < sizeof stentry)
328 return(-1);
329 if (stentry.n_name[0] != '_') continue;
330 if (eqpatr(sl_name, stentry.n_name+1, 1)) {
331 sl_addr = stentry.n_value;
332 break;
333 }
334 }
335 }
336 return(offset + sizeof stentry);
337}
338
339/* core address to procedure (pointer to proc array) */
340struct proct *
341adrtoprocp(addr)
342ADDR addr; {
343 register struct proct *procp, *lastproc;
344 lastproc = badproc;
345 for (procp=procs; procp->pname[0]; procp++) {
346 if (procp->paddr > addr) break;
347 if (procp->entrypt == 0)
348 lastproc = procp;
349 }
350 return (lastproc);
351}
352
353
354/* core address to file (pointer to file array) */
355struct filet *
356adrtofilep(addr)
357ADDR addr; {
358 register struct filet *filep;
359 for (filep=files; filep->sfilename[0]; filep++) {
360 if (filep->faddr > addr) break;
361 }
362 return (filep != files ? filep-1 : badfile);
363}
364
365/* core address to linenumber */
366long lastoffset;
367
368adrtolineno(addr)
369ADDR addr; {
370 register int lineno;
371 long offset;
372 struct nlist stentry;
373
374 lineno = lastoffset = -1;
375 offset = adrtoproc(addr)->st_offset;
376 blseek(&sbuf, offset, 0);
377 for (;;) {
378 if (bread(&sbuf, &stentry, sizeof stentry)
379 < sizeof stentry) break;
380 if (stentry.n_type == N_SLINE) {
381 if (stentry.n_value > addr) break;
382 lastoffset = offset;
383 lineno = stentry.n_desc;
384 }
385 offset += sizeof stentry;
386 }
387 return (lineno);
388}
389
390
391/* address to a.out offset */
392long
393adrtostoffset(addr)
394ADDR addr; {
395 adrtolineno(addr);
396 return(lastoffset);
397}
398
399
400/*
401 * Set (curfile, lineno) from core image.
402 * Returns 1 if there is a core image, 0 otherwise.
403 *
404 * Print the current line iff verbose is set.
405 */
406setcur(verbose) {
407 register struct proct *procp;
408
409 dot = *(ADDR *) (((ADDR) &u) + PC);
410
411 if (dot == 0) {
412 printf("No core image\n");
413 goto setmain;
414 }
415 procp = adrtoprocp(dot);
416 if ((procp->sfptr) != badfile) {
417 finit(adrtofilep(dot)->sfilename);
418 ffind(adrtolineno(dot));
419 if (verbose) {
420 printf("%.8s:", procp->pname);
421 fprint();
422 }
423 return(1);
424 }
425 if (verbose) {
426 if (procp->pname[0] == '_')
427 printf("%.7s: address 0x%x\n", procp->pname+1, dot);
428 else
429 printf("%.8s: address %d\n", procp->pname, dot);
430 }
431
432setmain:
433 procp = findproc("MAIN_");
434 if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
435 procp = findproc("main");
436 if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
437 nolines = 1;
438 printf("main not compiled with debug flag\n");
439 return(0);
440 }
441 }
442 finit(procp->sfptr->sfilename);
443 ffind(procp->lineno);
444 return(0);
445}
446
447compar(a, b)
448struct proct *a, *b; {
449 if (a->paddr == b->paddr) {
450 if (a->pname[0] == '_') return(-1);
451 if (b->pname[0] == '_') return(1);
452 return(0);
453 }
454 return(a->paddr < b->paddr ? -1 : 1);
455}
456
457/* gets offset of file or procedure named s */
458nametooffset(s)
459char *s; {
460 register struct filet *f;
461 register struct proct *p;
462
463 if (*s == '\0')
464 return(-1);
465 if (eqany('.', s)) {
466 f = findfile(s);
467 return(f->sfilename[0] ? f->stf_offset : -1);
468 }
469 p = findproc(s);
470 return(p->pname[0] ? p->st_offset : -1);
471}
472/* returns s if its a filename, its file otherwise */
473char *
474nametofile(s)
475char *s; {
476 register struct proct *p;
477
478 if (eqany('.', s)) {
479 return(s);
480 }
481 p = findproc(s);
482 return(adrtofilep(p->paddr)->sfilename);
483}
484
485
486/* line number to address, starting at offset in a.out */
487/* assumes that offset is within file */
488lntoaddr(lineno, offset, file)
489long offset; char *file; {
490 struct nlist stentry;
491 register int i, ignore = 0;
492 register int bestln=BIGNUM;
493 ADDR bestaddr;
494 char *p;
495
496 blseek(&sbuf, offset, 0);
497
498 do {
499 if (bread(&sbuf, &stentry, sizeof stentry) <
500 sizeof stentry) return(-1);
501 } while ((stentry.n_type & STABMASK) == N_SO);
502 for (;;) {
503 switch(stentry.n_type & STABMASK) {
504 case N_SLINE:
505 if (!ignore) {
506 if (stentry.n_desc == lineno)
507 return(stentry.n_value);
508 if (stentry.n_desc > lineno &&
509 stentry.n_desc < bestln) {
510 bestln = stentry.n_desc;
511 bestaddr = stentry.n_value;
512 }
513 }
514 break;
515
516 case N_SO:
517 goto ret;
518
519 case N_SOL:
520 p = file;
521 for (;;) {
522 for (i=0; i<8; i++) {
523 if (*p != stentry.n_name[i]) goto neq;
524 if (*p++ == '\0') break;
525 }
526 if (stentry.n_name[7] == '\0')
527 break;
528 if (bread(&sbuf, &stentry, sizeof stentry)
529 < sizeof stentry)
530 error("Bad N_SO entry (1)");
531 if ((stentry.n_type & STABMASK) !=
532 (unsigned char) N_SOL)
533 error("Bad N_SO entry (2)");
534 }
535 ignore = 0;
536 break;
537
538neq: ignore++;
539 break;
540 }
541 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
542 break;
543 }
544ret: return(bestln == BIGNUM ? -1 : bestaddr);
545}
546
547/* gets address of proc:number */
548getaddr(proc,integ)
549char *proc; {
550 register long offset;
551 register char *s, *f;
552 ADDR addr;
553
554 s = proc[0] ? proc : curfile;
555 if (*s == '\0')
556 return(-1);
557 offset = nametooffset(s);
558 f = nametofile(s);
559 if (debug) printf("getaddr() computed offset %d", offset);
560 if (offset == -1) {
561 addr = extaddr(proc);
562 if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
563 if (debug) printf(" extaddr computed %d\n", addr);
564 return(addr);
565 }
566 if (integ)
567 addr = lntoaddr(integ, offset, s);
568 else {
569 addr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
570 addr = lntoaddr(adrtolineno(addr)+1, offset, f);
571 }
572 if (debug) printf(" and addr %d\n", addr);
573 if (addr == -1) return(-1);
574 return(addr);
575}
576
577/* returns address of external */
578ADDR
579extaddr(name)
580char *name; {
581 struct nlist stentry;
582 blseek(&sbuf, extstart, 0);
583
584 for (;;) {
585 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
586 return(-1);
587 if (stentry.n_name[0] == '_' &&
588 eqpatr(name, stentry.n_name+1, 1))
589 return(stentry.n_value);
590 }
591}
592
593/* find enclosing common blocks and fix up addresses */
594docomm(offset)
595long offset; {
596 struct nlist stentry;
597
598 for (;;) {
599 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
600 error("Bad common block");
601 return;
602 }
603 sl_class = N_GSYM;
604 if ((stentry.n_type & STABMASK) == N_ECOMM) {
605 sl_addr += extaddr(stentry.n_name);
606 blseek(&sbuf, offset, 0);
607 return;
608 }
609 if ((stentry.n_type & STABMASK) == N_ECOML) {
610 sl_addr += stentry.n_value;
611 blseek(&sbuf, offset, 0);
612 return;
613 }
614 }
615}
616
617/* determine if class is that of a variable */
618char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
619 N_PSYM, 0};
620varclass(class)
621char class; {
622 char *p;
623
624 for (p=pctypes; *p; p++) {
625 if (class == *p)
626 return(1);
627 }
628 return(0);
629}