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