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