1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)readobj.c 1.6 03/24/83"; 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 #include "objsym.rep" 19 20 #define MAXSYMNO 6000 21 22 char *objname = "obj"; 23 24 LOCAL SYM *sym[MAXSYMNO]; 25 26 readobj(file) 27 char *file; 28 { 29 register FILE *fp; 30 struct pxhdr hdr; 31 32 if ((fp = fopen(file, "r")) == NIL) { 33 panic("can't open %s", file); 34 } 35 get(fp, hdr); 36 if (hdr.magicnum != MAGICNUM) { 37 fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0); 38 get(fp, hdr); 39 if (hdr.magicnum != MAGICNUM) { 40 fatal("%s is not a Pascal object file", file); 41 } 42 } 43 if (hdr.symtabsize == 0) { 44 fatal("%s doesn't have symbolic information", file); 45 } 46 objsize = hdr.objsize; 47 fseek(fp, (long) objsize, 1); 48 if (get(fp, nlhdr) != 1) { 49 panic("can't read nlhdr"); 50 } 51 if (option('h')) { 52 printf("\nHeader information:\n"); 53 printf("\tobject size %d\n", objsize); 54 printf("\tsymtab size %d\n", hdr.symtabsize); 55 printf("\tstringsize %d\n", nlhdr.stringsize); 56 printf("\tnsyms %d\n", nlhdr.nsyms); 57 printf("\tnfiles %d\n", nlhdr.nfiles); 58 printf("\tnlines %d\n", nlhdr.nlines); 59 } 60 stringtab = alloc(nlhdr.stringsize, char); 61 fread(stringtab, sizeof(char), nlhdr.stringsize, fp); 62 readsyms(fp); 63 readfiles(fp); 64 readlines(fp); 65 fclose(fp); 66 } 67 68 /* 69 * Allocate and read in file name information table. 70 */ 71 72 LOCAL readfiles(fp) 73 register FILE *fp; 74 { 75 register int i; 76 register FILETAB *ftp; 77 FILETAB temp; 78 ADDRESS prevaddr; 79 80 filetab = alloc(nlhdr.nfiles, FILETAB); 81 ftp = &filetab[0]; 82 prevaddr = 0; 83 for (i = 0; i < nlhdr.nfiles; i++) { 84 fread(&temp, sizeof(FILETAB), 1, fp); 85 if (temp.addr != prevaddr) { 86 ftp++; 87 } 88 *ftp = temp; 89 ftp->filename += (int) stringtab; 90 prevaddr = ftp->addr; 91 } 92 nlhdr.nfiles = (ftp - &filetab[0]) + 1; 93 skimsource(filetab[0].filename); 94 dotpfile = filetab[0].filename; 95 } 96 97 /* 98 * Allocate and read in line number information table. 99 */ 100 101 LOCAL readlines(fp) 102 FILE *fp; 103 { 104 register LINENO oline; 105 register ADDRESS oaddr; 106 register LINETAB *lp; 107 FILETAB *ftp; 108 OBJLINE info; 109 110 if (nlhdr.nlines == 0) { 111 return; 112 } 113 linetab = alloc(nlhdr.nlines, LINETAB); 114 for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) { 115 lp->line = 0; 116 } 117 for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { 118 if (ftp->lineindex < nlhdr.nlines) { 119 linetab[ftp->lineindex].line = ftp->line; 120 } 121 } 122 oline = 0; 123 oaddr = 0; 124 for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) { 125 if (lp->line != 0) { 126 oline = lp->line; 127 } 128 info.together = getw(fp); 129 oline += info.separate.lineincr; 130 oaddr += info.separate.addrincr; 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 (%d)", symno); 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