1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)readobj.c 1.4 02/10/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 #include "objsym.rep" 19 20 #define MAXSYMNO 2000 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 linetab[ftp->lineindex].line = ftp->line; 119 } 120 oline = 0; 121 oaddr = 0; 122 for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) { 123 if (lp->line != 0) { 124 oline = lp->line; 125 } 126 info.together = getw(fp); 127 oline += info.separate.lineincr; 128 oaddr += info.separate.addrincr; 129 lp->line = oline; 130 lp->addr = oaddr; 131 } 132 } 133 134 /* 135 * read in the symbols 136 */ 137 138 readsyms(fp) 139 FILE *fp; 140 { 141 register int i; 142 int symno; 143 144 symtab = st_creat(nlhdr.nsyms); 145 for (i = 0; i < nlhdr.nsyms; i++) { 146 symno = getw(fp); 147 if (symno >= MAXSYMNO) { 148 panic("symbol number too large"); 149 } 150 sym[symno] = readsym(fp); 151 } 152 if (backpatch() != 0) { 153 panic("patchlist not empty after reading namelist"); 154 } 155 if (program == NIL) { 156 panic("no program"); 157 } 158 maketypes(); 159 } 160 161 typedef struct patchinfo { 162 SYM **patchsym; 163 struct patchinfo *next_patch; 164 } PATCH; 165 166 LOCAL PATCH *phead; 167 168 /* 169 * Go through patchlist looking for symbol numbers for which the 170 * sym array now has a non-NIL entry. 171 * 172 * Afterwards, zap the sym array. 173 */ 174 175 int backpatch() 176 { 177 register PATCH *p, *last, *next; 178 register SYM *s, **t; 179 int count; 180 181 last = NIL; 182 count = 0; 183 for (p = phead; p != NIL; p = next) { 184 next = p->next_patch; 185 t = p->patchsym; 186 if ((s = sym[(int) *t]) != NIL) { 187 *t = s; 188 if (last == NIL) { 189 phead = next; 190 } else { 191 last->next_patch = next; 192 } 193 dispose(p); 194 } else { 195 last = p; 196 count++; 197 } 198 } 199 for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) { 200 *t = NIL; 201 } 202 return(count); 203 } 204 205 /* 206 * Check to see if the given pointer (really symbol number) should 207 * be added to the patch list. The argument is double indirect 208 * to do call by reference passing. 209 */ 210 211 chkpatch(p) 212 SYM **p; 213 { 214 register SYM *s, *t; 215 register PATCH *patch; 216 217 if ((s = *p) != NIL) { 218 if ((t = sym[(int) s]) != NIL) { 219 *p = t; 220 } else { 221 patch = alloc(1, PATCH); 222 patch->patchsym = p; 223 patch->next_patch = phead; 224 phead = patch; 225 } 226 } 227 } 228 229 /* 230 * Free all the object information. 231 */ 232 233 objfree() 234 { 235 register int i; 236 237 st_destroy(symtab); 238 dispose(stringtab); 239 dispose(filetab); 240 dispose(linetab); 241 clrfunctab(); 242 for (i = 0; i < MAXSYMNO; i++) { 243 sym[i] = NIL; 244 } 245 } 246