coff32read.c (6442B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <scc/mach.h> 9 10 #include "../libmach.h" 11 #include "coff32.h" 12 13 static void 14 unpack_hdr(int order, unsigned char *buf, FILHDR *hdr) 15 { 16 int n; 17 18 n = unpack(order, 19 buf, 20 "sslllss", 21 &hdr->f_magic, 22 &hdr->f_nscns, 23 &hdr->f_timdat, 24 &hdr->f_symptr, 25 &hdr->f_nsyms, 26 &hdr->f_opthdr, 27 &hdr->f_flags); 28 assert(n == FILHSZ); 29 } 30 31 static void 32 unpack_line(int order, unsigned char *buf, LINENO *lp) 33 { 34 int n; 35 36 n = unpack(order, 37 buf, 38 "lls", 39 &lp->l_symndx, 40 &lp->l_paddr, 41 &lp->l_lnno); 42 assert(n == LINESZ); 43 } 44 45 static void 46 unpack_scn(int order, unsigned char *buf, SCNHDR *scn) 47 { 48 int n; 49 50 n = unpack(order, 51 buf, 52 "'8llllllssl", 53 scn->s_name, 54 &scn->s_paddr, 55 &scn->s_vaddr, 56 &scn->s_size, 57 &scn->s_scnptr, 58 &scn->s_relptr, 59 &scn->s_lnnoptr, 60 &scn->s_nrelloc, 61 &scn->s_nlnno, 62 &scn->s_flags); 63 assert(n == SCNHSZ); 64 } 65 66 static void 67 unpack_ent(int order, unsigned char *buf, SYMENT *ent) 68 { 69 int n; 70 char *s; 71 72 n = unpack(order, 73 buf, 74 "'8lsscc", 75 ent->n_name, 76 &ent->n_value, 77 &ent->n_scnum, 78 &ent->n_type, 79 &ent->n_sclass, 80 &ent->n_numaux); 81 assert(n == SYMESZ); 82 83 s = ent->n_name; 84 if (!s[0] && !s[1] && !s[2] && !s[3]) 85 unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset); 86 } 87 88 static void 89 unpack_reloc(int order, unsigned char *buf, RELOC *rel) 90 { 91 int n; 92 93 n = unpack(order, 94 buf, 95 "lls", 96 &rel->r_vaddr, 97 &rel->r_symndx, 98 &rel->r_type); 99 assert(n == RELSZ); 100 } 101 102 static void 103 unpack_aout(int order, unsigned char *buf, AOUTHDR *aout) 104 { 105 int n; 106 107 n = unpack(order, 108 buf, 109 "ssllllll", 110 &aout->magic, 111 &aout->vstamp, 112 &aout->tsize, 113 &aout->dsize, 114 &aout->bsize, 115 &aout->entry, 116 &aout->text_start, 117 &aout->data_start); 118 assert(n == AOUTSZ); 119 } 120 121 static int 122 readhdr(Obj *obj, FILE *fp) 123 { 124 FILHDR *hdr; 125 struct coff32 *coff; 126 unsigned char buf[FILHSZ]; 127 128 coff = obj->data; 129 hdr = &coff->hdr; 130 131 if (fread(buf, FILHSZ, 1, fp) != 1) 132 return 0; 133 unpack_hdr(ORDER(obj->type), buf, hdr); 134 135 return 1; 136 } 137 138 static int 139 readstr(Obj *obj, FILE *fp) 140 { 141 FILHDR *hdr; 142 struct coff32 *coff; 143 long siz; 144 char *str; 145 unsigned char buf[10]; 146 147 coff = obj->data; 148 hdr = &coff->hdr; 149 150 coff->strsiz = 0; 151 coff->strtbl = NULL; 152 153 if (hdr->f_nsyms == 0) 154 return 1; 155 156 if (fread(buf, 4, 1, fp) != 1) 157 return 0; 158 unpack(ORDER(obj->type), buf, "l", &siz); 159 if (siz < 4 || siz > SIZE_MAX) 160 return 0; 161 if (siz == 4) 162 return 1; 163 164 if ((str = malloc(siz)) == NULL) 165 return 0; 166 coff->strtbl = str; 167 coff->strsiz = siz; 168 169 return fread(str+4, siz-4, 1, fp) == 1; 170 } 171 172 static int 173 readreloc(Obj *obj, FILE *fp) 174 { 175 int i; 176 long j; 177 RELOC **rels, *rp; 178 SCNHDR *scn; 179 FILHDR *hdr; 180 struct coff32 *coff; 181 unsigned char buf[RELSZ]; 182 183 coff = obj->data; 184 hdr = &coff->hdr; 185 186 if (hdr->f_nscns == 0) 187 return 1; 188 189 rels = calloc(hdr->f_nscns, sizeof(*rels)); 190 if (!rels) 191 return 0; 192 coff->rels = rels; 193 194 for (i = 0; i < hdr->f_nscns; i++) { 195 scn = &coff->scns[i]; 196 if (scn->s_nrelloc == 0) 197 continue; 198 199 if (!objpos(obj, fp, scn->s_relptr)) 200 return 0; 201 202 rp = calloc(scn->s_nrelloc, sizeof(RELOC)); 203 if (!rp) 204 return 0; 205 rels[i] = rp; 206 207 for (j = 0; j < scn->s_nrelloc; j++) { 208 if (fread(buf, RELSZ, 1, fp) != 1) 209 return 0; 210 unpack_reloc(ORDER(obj->type), buf, &rp[i]); 211 if (rp[i].r_symndx >= hdr->f_nsyms) 212 return 0; 213 } 214 } 215 216 return 1; 217 } 218 219 static int 220 readents(Obj *obj, FILE *fp) 221 { 222 FILHDR *hdr; 223 struct coff32 *coff; 224 SYMENT *ent; 225 long i; 226 unsigned char buf[SYMESZ]; 227 228 coff = obj->data; 229 hdr = &coff->hdr; 230 231 if (hdr->f_nsyms == 0) 232 return 1; 233 234 ent = calloc(hdr->f_nsyms, sizeof(*ent)); 235 if (!ent) 236 return 0; 237 coff->ents = ent; 238 239 if (!objpos(obj, fp, hdr->f_symptr)) 240 return 0; 241 for (i = 0; i < hdr->f_nsyms; i++) { 242 if (fread(buf, SYMESZ, 1, fp) != 1) 243 return 0; 244 unpack_ent(ORDER(obj->type), buf, &ent[i]); 245 if (ent->n_scnum > hdr->f_nscns) 246 return 0; 247 } 248 249 return 1; 250 } 251 252 static int 253 readscns(Obj *obj, FILE *fp) 254 { 255 FILHDR *hdr; 256 struct coff32 *coff; 257 SCNHDR *scn; 258 long i; 259 unsigned char buf[SCNHSZ]; 260 261 coff = obj->data; 262 hdr = &coff->hdr; 263 264 if (hdr->f_nscns == 0) 265 return 1; 266 267 scn = calloc(hdr->f_nscns, sizeof(*scn)); 268 if (!scn) 269 return 0; 270 coff->scns = scn; 271 272 for (i = 0; i < hdr->f_nscns; i++) { 273 if (fread(buf, SCNHSZ, 1, fp) < 0) 274 return 0; 275 unpack_scn(ORDER(obj->type), buf, &scn[i]); 276 } 277 278 return 1; 279 } 280 281 static int 282 readlines(Obj *obj, FILE *fp) 283 { 284 int i,j; 285 LINENO **lines, *lp; 286 FILHDR *hdr; 287 SCNHDR *scn; 288 struct coff32 *coff; 289 unsigned char buf[LINESZ]; 290 291 coff = obj->data; 292 hdr = &coff->hdr; 293 294 if (hdr->f_nscns == 0) 295 return 1; 296 297 lines = calloc(hdr->f_nscns, sizeof(lp)); 298 if (!lines) 299 return 0; 300 coff->lines = lines; 301 302 for (i = 0; i < hdr->f_nscns; i++) { 303 scn = &coff->scns[i]; 304 if (scn->s_nlnno == 0) 305 continue; 306 307 lp = calloc(sizeof(*lp), scn->s_nlnno); 308 if (!lp) 309 return 0; 310 lines[i] = lp; 311 312 for (j = 0; j < scn->s_nlnno; j++) { 313 if (!objpos(obj, fp, scn->s_lnnoptr)) 314 return 0; 315 if (fread(buf, LINESZ, 1, fp) == 1) 316 return 0; 317 unpack_line(ORDER(obj->type), buf, &lp[j]); 318 if (lp[i].l_symndx >= hdr->f_nsyms) 319 return 0; 320 } 321 } 322 323 return 1; 324 } 325 326 static int 327 readaout(Obj *obj, FILE *fp) 328 { 329 struct coff32 *coff = obj->data; 330 FILHDR *hdr = &coff->hdr; 331 unsigned char buf[AOUTSZ]; 332 333 if (hdr->f_opthdr == 0) 334 return 1; 335 336 if (fread(buf, AOUTSZ, 1, fp) != 1) 337 return 0; 338 339 unpack_aout(ORDER(obj->type), buf, &coff->aout); 340 341 return 1; 342 } 343 344 int 345 coff32read(Obj *obj, FILE *fp) 346 { 347 long i; 348 struct coff32 *coff = obj->data; 349 FILHDR *hdr = &coff->hdr; 350 351 if (!readhdr(obj, fp)) 352 return -1; 353 if (!readaout(obj, fp)) 354 return -1; 355 if (!readscns(obj, fp)) 356 return -1; 357 if (!readents(obj, fp)) 358 return -1; 359 if (!readstr(obj, fp)) 360 return -1; 361 if (!readreloc(obj, fp)) 362 return -1; 363 if (!readlines(obj, fp)) 364 return -1; 365 366 for (i = 0; i < hdr->f_nsyms; i++) { 367 SYMENT *ent = &coff->ents[i]; 368 if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz) 369 return -1; 370 } 371 372 return 0; 373 }