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