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
readobj(file)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
readfiles(fp)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
readlines(fp)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
readsyms(fp)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
backpatch()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
chkpatch(p)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
objfree()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