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