coff32read.c (10615B)
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 #include <scc/coff32.h> 10 11 #include "../libmach.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 "ls", 39 &lp->l_addr.l_symndx, 40 &lp->l_lnno); 41 assert(n == LINESZ); 42 } 43 44 static void 45 unpack_scn(int order, unsigned char *buf, SCNHDR *scn) 46 { 47 int n; 48 char *s; 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 s = scn->s_name; 66 if (!s[0] && !s[1] && !s[2] && !s[3]) 67 unpack(order, buf, "ll", &scn->s_zeroes, &scn->s_offset); 68 } 69 70 static void 71 unpack_ent(int order, unsigned char *buf, SYMENT *ent) 72 { 73 int n; 74 char *s; 75 76 n = unpack(order, 77 buf, 78 "'8lsscc", 79 ent->n_name, 80 &ent->n_value, 81 &ent->n_scnum, 82 &ent->n_type, 83 &ent->n_sclass, 84 &ent->n_numaux); 85 assert(n == SYMESZ); 86 87 s = ent->n_name; 88 if (!s[0] && !s[1] && !s[2] && !s[3]) 89 unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset); 90 } 91 92 static void 93 unpack_reloc(int order, unsigned char *buf, RELOC *rel) 94 { 95 int n; 96 97 n = unpack(order, 98 buf, 99 "lls", 100 &rel->r_vaddr, 101 &rel->r_symndx, 102 &rel->r_type); 103 assert(n == RELSZ); 104 } 105 106 static void 107 unpack_aout(int order, unsigned char *buf, AOUTHDR *aout) 108 { 109 int n; 110 111 n = unpack(order, 112 buf, 113 "ssllllll", 114 &aout->magic, 115 &aout->vstamp, 116 &aout->tsize, 117 &aout->dsize, 118 &aout->bsize, 119 &aout->entry, 120 &aout->text_start, 121 &aout->data_start); 122 assert(n == AOUTSZ); 123 } 124 125 static void 126 unpack_aux_file(int order, unsigned char *buf, AUXENT *aux) 127 { 128 int n; 129 char *s; 130 131 n = unpack(order, 132 buf, 133 "'18", 134 aux->x_fname); 135 assert(n == AUXESZ); 136 137 s = aux->x_fname; 138 if (!s[0] && !s[1] && !s[2] && !s[3]) 139 unpack(order, buf, "ll", &aux->x_zeroes, &aux->x_offset); 140 } 141 142 static void 143 unpack_aux_scn(int order, unsigned char *buf, AUXENT *aux) 144 { 145 char dummy1, dummy2, dummy3; 146 int n; 147 148 n = unpack(order, 149 buf, 150 "lsslscccc", 151 &aux->x_scnlen, 152 &aux->x_nreloc, 153 &aux->x_nlinno, 154 &aux->x_checksum, 155 &aux->x_associated, 156 &aux->x_comdat, 157 &dummy1, 158 &dummy2, 159 &dummy3); 160 assert(n == AUXESZ); 161 } 162 163 static void 164 unpack_aux_fun(int order, unsigned char *buf, AUXENT *aux) 165 { 166 int n; 167 168 n = unpack(order, 169 buf, 170 "lllls", 171 &aux->x_tagndx, 172 &aux->x_fsize, 173 &aux->x_lnnoptr, 174 &aux->x_endndx, 175 &aux->x_tvndx); 176 assert(n == AUXESZ); 177 } 178 179 static void 180 unpack_aux_ary(int order, unsigned char *buf, AUXENT *aux) 181 { 182 int n; 183 184 n = unpack(order, 185 buf, 186 "lssssss", 187 &aux->x_tagndx, 188 &aux->x_lnno, 189 &aux->x_size, 190 &aux->x_dimen[0], 191 &aux->x_dimen[1], 192 &aux->x_dimen[2], 193 &aux->x_dimen[3], 194 &aux->x_tvndx); 195 assert(n == AUXESZ); 196 } 197 198 static void 199 unpack_aux_sym(int order, unsigned char *buf, AUXENT *aux) 200 { 201 int n; 202 203 n = unpack(order, 204 buf, 205 "lsslls", 206 &aux->x_tagndx, 207 &aux->x_lnno, 208 &aux->x_size, 209 &aux->x_lnnoptr, 210 &aux->x_endndx, 211 &aux->x_tvndx); 212 assert(n == AUXESZ); 213 } 214 215 static int 216 readhdr(Obj *obj, FILE *fp) 217 { 218 FILHDR *hdr; 219 struct coff32 *coff; 220 unsigned char buf[FILHSZ]; 221 222 coff = obj->data; 223 hdr = &coff->hdr; 224 225 if (fread(buf, FILHSZ, 1, fp) != 1) 226 return 0; 227 unpack_hdr(ORDER(obj->type), buf, hdr); 228 229 if (hdr->f_nsyms < 0 || hdr->f_nscns < 0) 230 return 0; 231 232 return 1; 233 } 234 235 static int 236 readstr(Obj *obj, FILE *fp) 237 { 238 FILHDR *hdr; 239 struct coff32 *coff; 240 long siz; 241 char *str; 242 unsigned char buf[10]; 243 244 coff = obj->data; 245 hdr = &coff->hdr; 246 247 coff->strsiz = 0; 248 coff->strtbl = NULL; 249 250 if (hdr->f_nsyms == 0) 251 return 1; 252 253 if (fread(buf, 4, 1, fp) != 1) 254 return 0; 255 unpack(ORDER(obj->type), buf, "l", &siz); 256 if (siz < 4 || siz > SIZE_MAX) 257 return 0; 258 if (siz == 4) 259 return 1; 260 261 if ((str = malloc(siz)) == NULL) 262 return 0; 263 coff->strtbl = str; 264 coff->strsiz = siz; 265 266 return fread(str+4, siz-4, 1, fp) == 1; 267 } 268 269 static int 270 readreloc(Obj *obj, FILE *fp) 271 { 272 int i; 273 long j; 274 RELOC **rels, *rp; 275 SCNHDR *scn; 276 FILHDR *hdr; 277 struct coff32 *coff; 278 unsigned char buf[RELSZ]; 279 280 coff = obj->data; 281 hdr = &coff->hdr; 282 283 if (hdr->f_nscns == 0) 284 return 1; 285 286 rels = calloc(hdr->f_nscns, sizeof(*rels)); 287 if (!rels) 288 return 0; 289 coff->rels = rels; 290 291 for (i = 0; i < hdr->f_nscns; i++) { 292 scn = &coff->scns[i]; 293 if (scn->s_nrelloc == 0) 294 continue; 295 296 if (!objpos(obj, fp, scn->s_relptr)) 297 return 0; 298 299 rp = calloc(scn->s_nrelloc, sizeof(RELOC)); 300 if (!rp) 301 return 0; 302 rels[i] = rp; 303 304 for (j = 0; j < scn->s_nrelloc; j++) { 305 if (fread(buf, RELSZ, 1, fp) != 1) 306 return 0; 307 unpack_reloc(ORDER(obj->type), buf, &rp[i]); 308 if (rp[i].r_symndx >= hdr->f_nsyms) 309 return 0; 310 } 311 } 312 313 return 1; 314 } 315 316 static int 317 readauxs(Obj *obj, FILE *fp, SYMENT *ent, long pos) 318 { 319 int i, n, typ, d1; 320 Entry *ep; 321 FILHDR *hdr; 322 struct coff32 *coff; 323 unsigned char buf[AUXESZ]; 324 325 if ((n = ent->n_numaux) == 0) 326 return 1; 327 if (fread(buf, sizeof(buf), 1, fp) != 1) 328 return 0; 329 330 coff = obj->data; 331 ep = &coff->ents[pos+1]; 332 typ = ent->n_type & 15; 333 d1 = (ent->n_type >> 4) & 15; 334 335 switch (ent->n_sclass) { 336 case C_FILE: 337 ep->type = SYM_AUX_FILE; 338 unpack_aux_file(ORDER(obj->type), buf, &ep->u.aux); 339 break; 340 case C_STAT: 341 if (d1 == DT_NON && typ == T_NULL) { 342 ep->type = SYM_AUX_SCN; 343 unpack_aux_scn(ORDER(obj->type), buf, &ep->u.aux); 344 break; 345 } 346 default: 347 switch (d1) { 348 case DT_FCN: 349 ep->type = SYM_AUX_FUN; 350 unpack_aux_fun(ORDER(obj->type), buf, &ep->u.aux); 351 break; 352 case DT_ARY: 353 ep->type = SYM_AUX_ARY; 354 unpack_aux_ary(ORDER(obj->type), buf, &ep->u.aux); 355 break; 356 default: 357 ep->type = SYM_AUX_SYM; 358 unpack_aux_sym(ORDER(obj->type), buf, &ep->u.aux); 359 } 360 } 361 362 for (++ep; --n > 0; ++ep) { 363 ep->type = SYM_AUX_UNK; 364 if (fread(ep->u.buf, AUXESZ, 1, fp) != 1) 365 return 0; 366 } 367 368 return 1; 369 } 370 371 static int 372 readents(Obj *obj, FILE *fp) 373 { 374 int n; 375 long i; 376 Entry *ep; 377 FILHDR *hdr; 378 struct coff32 *coff; 379 unsigned char buf[SYMESZ]; 380 381 coff = obj->data; 382 hdr = &coff->hdr; 383 384 if (hdr->f_nsyms == 0) 385 return 1; 386 387 ep = calloc(hdr->f_nsyms, sizeof(*ep)); 388 if (!ep) 389 return 0; 390 coff->ents = ep; 391 392 if (!objpos(obj, fp, hdr->f_symptr)) 393 return 0; 394 395 for (i = 0; i < hdr->f_nsyms; i++) { 396 SYMENT *ent; 397 398 if (fread(buf, SYMESZ, 1, fp) != 1) 399 return 0; 400 401 ep = &coff->ents[i]; 402 ep->type = SYM_ENT; 403 ent = &ep->u.sym; 404 unpack_ent(ORDER(obj->type), buf, ent); 405 if (ent->n_scnum > hdr->f_nscns) 406 return 0; 407 408 if (!readauxs(obj, fp, ent, i)) 409 return 0; 410 411 i += ent->n_numaux; 412 } 413 414 return 1; 415 } 416 417 static int 418 readscns(Obj *obj, FILE *fp) 419 { 420 FILHDR *hdr; 421 struct coff32 *coff; 422 SCNHDR *scn; 423 long i; 424 unsigned char buf[SCNHSZ]; 425 426 coff = obj->data; 427 hdr = &coff->hdr; 428 429 if (hdr->f_nscns == 0) 430 return 1; 431 432 scn = calloc(hdr->f_nscns, sizeof(*scn)); 433 if (!scn) 434 return 0; 435 coff->scns = scn; 436 437 for (i = 0; i < hdr->f_nscns; i++) { 438 if (fread(buf, SCNHSZ, 1, fp) < 0) 439 return 0; 440 unpack_scn(ORDER(obj->type), buf, &scn[i]); 441 } 442 443 return 1; 444 } 445 446 static int 447 readlines(Obj *obj, FILE *fp) 448 { 449 int i,j; 450 LINENO **lines, *lp, *p; 451 FILHDR *hdr; 452 SCNHDR *scn; 453 struct coff32 *coff; 454 unsigned char buf[LINESZ]; 455 456 coff = obj->data; 457 hdr = &coff->hdr; 458 459 if (hdr->f_nscns == 0) 460 return 1; 461 462 lines = calloc(hdr->f_nscns, sizeof(lp)); 463 if (!lines) 464 return 0; 465 coff->lines = lines; 466 467 for (i = 0; i < hdr->f_nscns; i++) { 468 scn = &coff->scns[i]; 469 if (scn->s_nlnno == 0) 470 continue; 471 472 lp = calloc(sizeof(*lp), scn->s_nlnno); 473 if (!lp) 474 return 0; 475 lines[i] = lp; 476 477 if (!objpos(obj, fp, scn->s_lnnoptr)) 478 return 0; 479 480 for (j = 0; j < scn->s_nlnno; j++) { 481 if (fread(buf, LINESZ, 1, fp) != 1) 482 return 0; 483 unpack_line(ORDER(obj->type), buf, lp); 484 if (lp->l_lnno != 0 485 && lp->l_addr.l_symndx >= hdr->f_nsyms) { 486 return 0; 487 } 488 ++lp; 489 } 490 } 491 492 return 1; 493 } 494 495 static int 496 readaout(Obj *obj, FILE *fp) 497 { 498 struct coff32 *coff = obj->data; 499 FILHDR *hdr = &coff->hdr; 500 unsigned char buf[AOUTSZ]; 501 502 if (hdr->f_opthdr == 0) 503 return 1; 504 505 if (fread(buf, AOUTSZ, 1, fp) != 1) 506 return 0; 507 508 unpack_aout(ORDER(obj->type), buf, &coff->aout); 509 510 return 1; 511 } 512 513 static int 514 validate(Obj *obj) 515 { 516 long i, n; 517 SYMENT *ent; 518 struct coff32 *coff = obj->data; 519 FILHDR *hdr = &coff->hdr; 520 521 ent = NULL; 522 for (i = 0; i < hdr->f_nsyms; i++) { 523 SCNHDR *scn; 524 AUXENT *aux; 525 Entry *ep = &coff->ents[i]; 526 527 aux = &ep->u.aux; 528 switch (ep->type) { 529 case SYM_ENT: 530 ent = &ep->u.sym; 531 if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz) 532 return -1; 533 break; 534 case SYM_AUX_FILE: 535 if (aux->x_zeroes != 0 && aux->x_offset > coff->strsiz) 536 return -1; 537 break; 538 case SYM_AUX_SCN: 539 if (aux->x_scnlen < 0) 540 return -1; 541 n = ent->n_scnum; 542 if (n <= 0) 543 return -1; 544 scn = &coff->scns[n-1]; 545 if (scn->s_nrelloc != aux->x_nreloc) 546 return -1; 547 if (scn->s_nlnno != aux->x_nlinno) 548 return -1; 549 break; 550 case SYM_AUX_FUN: 551 case SYM_AUX_SYM: 552 if (aux->x_endndx < 0 || aux->x_endndx > hdr->f_nsyms) 553 return -1; 554 case SYM_AUX_ARY: 555 if (aux->x_tagndx < 0 || aux->x_tagndx > hdr->f_nsyms) 556 return -1; 557 if (aux->x_tvndx < 0 || aux->x_tvndx > hdr->f_nsyms) 558 return -1; 559 break; 560 case SYM_AUX_UNK: 561 break; 562 default: 563 return -1; 564 } 565 } 566 567 return 0; 568 } 569 570 int 571 coff32read(Obj *obj, FILE *fp) 572 { 573 574 if (!readhdr(obj, fp)) 575 return -1; 576 if (!readaout(obj, fp)) 577 return -1; 578 if (!readscns(obj, fp)) 579 return -1; 580 if (!readents(obj, fp)) 581 return -1; 582 if (!readstr(obj, fp)) 583 return -1; 584 if (!readreloc(obj, fp)) 585 return -1; 586 if (!readlines(obj, fp)) 587 return -1; 588 589 return validate(obj); 590 }