1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)readobj.c	5.1 (Berkeley) 06/07/85";
9 #endif not lint
10 
11 /*
12  * Read in the namelist from the obj file.
13  */
14 
15 #include "defs.h"
16 #include "sym.h"
17 #include "symtab.h"
18 #include "object.h"
19 #include "objfmt.h"
20 #include "main.h"
21 #include "mappings.h"
22 #include "mappings/filetab.h"
23 #include "mappings/linetab.h"
24 #include "objsym.rep"
25 
26 #define MAXSYMNO 6000
27 
28 char *objname = "obj";
29 
30 LOCAL SYM *sym[MAXSYMNO];
31 
32 readobj(file)
33 char *file;
34 {
35     register FILE *fp;
36     struct pxhdr hdr;
37 
38     if ((fp = fopen(file, "r")) == NIL) {
39 	panic("can't open %s", file);
40     }
41     get(fp, hdr);
42     if (hdr.magicnum != MAGICNUM) {
43 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
44 	get(fp, hdr);
45 	if (hdr.magicnum != MAGICNUM) {
46 	    fatal("%s is not a Pascal object file", file);
47 	}
48     }
49     if (hdr.symtabsize == 0) {
50 	fatal("%s doesn't have symbolic information", file);
51     }
52     objsize = hdr.objsize;
53     fseek(fp, (long) objsize, 1);
54     if (get(fp, nlhdr) != 1) {
55 	panic("can't read nlhdr");
56     }
57     if (option('h')) {
58 	printf("\nHeader information:\n");
59 	printf("\tobject size %d\n", objsize);
60 	printf("\tsymtab size %d\n", hdr.symtabsize);
61 	printf("\tstringsize  %d\n", nlhdr.stringsize);
62 	printf("\tnsyms       %d\n", nlhdr.nsyms);
63 	printf("\tnfiles      %d\n", nlhdr.nfiles);
64 	printf("\tnlines      %d\n", nlhdr.nlines);
65     }
66     stringtab = alloc(nlhdr.stringsize, char);
67     fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
68     readsyms(fp);
69     readfiles(fp);
70     readlines(fp);
71     fclose(fp);
72 }
73 
74 /*
75  * Allocate and read in file name information table.
76  */
77 
78 LOCAL readfiles(fp)
79 register FILE *fp;
80 {
81     register int i;
82     register FILETAB *ftp;
83     FILETAB temp;
84     ADDRESS prevaddr;
85 
86     filetab = alloc(nlhdr.nfiles, FILETAB);
87     ftp = &filetab[0];
88     prevaddr = 0;
89     for (i = 0; i < nlhdr.nfiles; i++) {
90 	fread(&temp, sizeof(FILETAB), 1, fp);
91 	if (temp.addr != prevaddr) {
92 	    ftp++;
93 	}
94 	*ftp = temp;
95 	ftp->filename += (int) stringtab;
96 	prevaddr = ftp->addr;
97     }
98     nlhdr.nfiles = (ftp - &filetab[0]) + 1;
99     skimsource(filetab[0].filename);
100     dotpfile = filetab[0].filename;
101 }
102 
103 /*
104  * Allocate and read in line number information table.
105  */
106 
107 LOCAL readlines(fp)
108 FILE *fp;
109 {
110     register LINENO oline;
111     register ADDRESS oaddr;
112     register LINETAB *lp;
113     FILETAB *ftp;
114     OBJLINE info;
115 
116     if (nlhdr.nlines == 0) {
117 	return;
118     }
119     linetab = alloc(nlhdr.nlines, LINETAB);
120     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
121 	lp->line = 0;
122     }
123     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
124 	if (ftp->lineindex < nlhdr.nlines) {
125 	    linetab[ftp->lineindex].line = ftp->line;
126 	}
127     }
128     oline = 0;
129     oaddr = 0;
130     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
131 	if (lp->line != 0) {
132 	    oline = lp->line;
133 	}
134 	info.together = getw(fp);
135 	oline += info.separate.lineincr;
136 	oaddr += info.separate.addrincr;
137 	lp->line = oline;
138 	lp->addr = oaddr;
139     }
140 }
141 
142 /*
143  * Read in the symbols.
144  */
145 
146 readsyms(fp)
147 FILE *fp;
148 {
149     register int i;
150     int symno;
151 
152     symtab = st_creat(nlhdr.nsyms);
153     for (i = 0; i < nlhdr.nsyms; i++) {
154 	symno = getw(fp);
155 	if (symno >= MAXSYMNO) {
156 	    panic("symbol number too large (%d)", symno);
157 	}
158 	sym[symno] = readsym(fp);
159     }
160     if (backpatch() != 0) {
161 	panic("patchlist not empty after reading namelist");
162     }
163     if (program == NIL) {
164 	panic("no program");
165     }
166     maketypes();
167 }
168 
169 typedef struct patchinfo {
170     SYM **patchsym;
171     struct patchinfo *next_patch;
172 } PATCH;
173 
174 LOCAL PATCH *phead;
175 
176 /*
177  * Go through patchlist looking for symbol numbers for which the
178  * sym array now has a non-NIL entry.
179  *
180  * Afterwards, zap the sym array.
181  */
182 
183 int backpatch()
184 {
185     register PATCH *p, *last, *next;
186     register SYM *s, **t;
187     int count;
188 
189     last = NIL;
190     count = 0;
191     for (p = phead; p != NIL; p = next) {
192 	next = p->next_patch;
193 	t = p->patchsym;
194 	if ((s = sym[(int) *t]) != NIL) {
195 	    *t = s;
196 	    if (last == NIL) {
197 		phead = next;
198 	    } else {
199 		last->next_patch = next;
200 	    }
201 	    dispose(p);
202 	} else {
203 	    last = p;
204 	    count++;
205 	}
206     }
207     for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
208 	*t = NIL;
209     }
210     return(count);
211 }
212 
213 /*
214  * Check to see if the given pointer (really symbol number) should
215  * be added to the patch list.  The argument is double indirect
216  * to do call by reference passing.
217  */
218 
219 chkpatch(p)
220 SYM **p;
221 {
222     register SYM *s, *t;
223     register PATCH *patch;
224 
225     if ((s = *p) != NIL) {
226 	if ((t = sym[(int) s]) != NIL) {
227 	    *p = t;
228 	} else {
229 	    patch = alloc(1, PATCH);
230 	    patch->patchsym = p;
231 	    patch->next_patch = phead;
232 	    phead = patch;
233 	}
234     }
235 }
236 
237 /*
238  * Free all the object information.
239  */
240 
241 objfree()
242 {
243     register int i;
244 
245     st_destroy(symtab);
246     dispose(stringtab);
247     dispose(filetab);
248     dispose(linetab);
249     clrfunctab();
250     for (i = 0; i < MAXSYMNO; i++) {
251 	sym[i] = NIL;
252     }
253 }
254