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