1#include <assert.h>2#include <ctype.h>3#include <stdint.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>78#include <scc/mach.h>9#include <scc/coff32.h>1011#include "../libmach.h"12#include "fun.h"1314static void15unpack_hdr(int order, unsigned char *buf, FILHDR *hdr)16{17 int n;1819 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}3132static void33unpack_line(int order, unsigned char *buf, LINENO *lp)34{35 int n;3637 n = unpack(order,38 buf,39 "ls",40 &lp->l_addr.l_symndx,41 &lp->l_lnno);42 assert(n == LINESZ);43}4445static void46unpack_scn(int order, unsigned char *buf, SCNHDR *scn)47{48 int n;49 char *s;5051 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);6566 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}7071static void72unpack_ent(int order, unsigned char *buf, SYMENT *ent)73{74 int n;75 char *s;7677 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);8788 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}9293static void94unpack_reloc(int order, unsigned char *buf, RELOC *rel)95{96 int n;9798 n = unpack(order,99 buf,100 "lls",101 &rel->r_vaddr,102 &rel->r_symndx,103 &rel->r_type);104 assert(n == RELSZ);105}106107static void108unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)109{110 int n;111112 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}125126static void127unpack_aux_file(int order, unsigned char *buf, AUXENT *aux)128{129 int n;130 char *s;131132 n = unpack(order,133 buf,134 "'18",135 aux->x_fname);136 assert(n == AUXESZ);137138 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}142143static void144unpack_aux_scn(int order, unsigned char *buf, AUXENT *aux)145{146 char dummy1, dummy2, dummy3;147 int n;148149 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}163164static void165unpack_aux_fun(int order, unsigned char *buf, AUXENT *aux)166{167 int n;168169 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}179180static void181unpack_aux_ary(int order, unsigned char *buf, AUXENT *aux)182{183 int n;184185 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}198199static void200unpack_aux_sym(int order, unsigned char *buf, AUXENT *aux)201{202 int n;203204 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}215216static int217readhdr(Obj *obj, FILE *fp)218{219 FILHDR *hdr;220 struct coff32 *coff;221 unsigned char buf[FILHSZ];222223 coff = obj->data;224 hdr = &coff->hdr;225226 if (fread(buf, FILHSZ, 1, fp) != 1)227 return 0;228 unpack_hdr(ORDER(obj->type), buf, hdr);229230 if (hdr->f_nsyms < 0 || hdr->f_nscns < 0)231 return 0;232233 return 1;234}235236static int237readstr(Obj *obj, FILE *fp)238{239 FILHDR *hdr;240 struct coff32 *coff;241 long siz;242 char *str;243 unsigned char buf[10];244245 coff = obj->data;246 hdr = &coff->hdr;247248 coff->strsiz = 0;249 coff->strtbl = NULL;250251 if (hdr->f_nsyms == 0)252 return 1;253254 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;261262 if ((str = malloc(siz)) == NULL)263 return 0;264 coff->strtbl = str;265 coff->strsiz = siz;266267 return fread(str+4, siz-4, 1, fp) == 1;268}269270static int271readreloc(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];280281 coff = obj->data;282 hdr = &coff->hdr;283284 if (hdr->f_nscns == 0)285 return 1;286287 rels = calloc(hdr->f_nscns, sizeof(*rels));288 if (!rels)289 return 0;290 coff->rels = rels;291292 for (i = 0; i < hdr->f_nscns; i++) {293 scn = &coff->scns[i];294 if (scn->s_nrelloc == 0)295 continue;296297 if (!objpos(obj, fp, scn->s_relptr))298 return 0;299300 rp = calloc(scn->s_nrelloc, sizeof(RELOC));301 if (!rp)302 return 0;303 rels[i] = rp;304305 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 }313314 return 1;315}316317static int318readauxs(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];325326 if ((n = ent->n_numaux) == 0)327 return 1;328 if (fread(buf, sizeof(buf), 1, fp) != 1)329 return 0;330331 coff = obj->data;332 ep = &coff->ents[pos+1];333 typ = ent->n_type & 15;334 d1 = (ent->n_type >> 4) & 15;335336 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 }362363 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 }368369 return 1;370}371372static int373readents(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];381382 coff = obj->data;383 hdr = &coff->hdr;384385 if (hdr->f_nsyms == 0)386 return 1;387388 ep = calloc(hdr->f_nsyms, sizeof(*ep));389 if (!ep)390 return 0;391 coff->ents = ep;392393 if (!objpos(obj, fp, hdr->f_symptr))394 return 0;395396 for (i = 0; i < hdr->f_nsyms; i++) {397 SYMENT *ent;398399 if (fread(buf, SYMESZ, 1, fp) != 1)400 return 0;401402 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;408409 if (!readauxs(obj, fp, ent, i))410 return 0;411412 i += ent->n_numaux;413 }414415 return 1;416}417418static int419readscns(Obj *obj, FILE *fp)420{421 FILHDR *hdr;422 struct coff32 *coff;423 SCNHDR *scn;424 long i;425 unsigned char buf[SCNHSZ];426427 coff = obj->data;428 hdr = &coff->hdr;429430 if (hdr->f_nscns == 0)431 return 1;432433 scn = calloc(hdr->f_nscns, sizeof(*scn));434 if (!scn)435 return 0;436 coff->scns = scn;437438 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 }443444 return 1;445}446447static int448readlines(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];456457 coff = obj->data;458 hdr = &coff->hdr;459460 if (hdr->f_nscns == 0)461 return 1;462463 lines = calloc(hdr->f_nscns, sizeof(lp));464 if (!lines)465 return 0;466 coff->lines = lines;467468 for (i = 0; i < hdr->f_nscns; i++) {469 scn = &coff->scns[i];470 if (scn->s_nlnno == 0)471 continue;472473 lp = calloc(sizeof(*lp), scn->s_nlnno);474 if (!lp)475 return 0;476 lines[i] = lp;477478 if (!objpos(obj, fp, scn->s_lnnoptr))479 return 0;480481 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 != 0486 && lp->l_addr.l_symndx >= hdr->f_nsyms) {487 return 0;488 }489 ++lp;490 }491 }492493 return 1;494}495496static int497readaout(Obj *obj, FILE *fp)498{499 struct coff32 *coff = obj->data;500 FILHDR *hdr = &coff->hdr;501 unsigned char buf[AOUTSZ];502503 if (hdr->f_opthdr == 0)504 return 1;505506 if (fread(buf, AOUTSZ, 1, fp) != 1)507 return 0;508509 unpack_aout(ORDER(obj->type), buf, &coff->aout);510511 return 1;512}513514static int515validate(Obj *obj)516{517 long i, n;518 SYMENT *ent;519 struct coff32 *coff = obj->data;520 FILHDR *hdr = &coff->hdr;521522 ent = NULL;523 for (i = 0; i < hdr->f_nsyms; i++) {524 SCNHDR *scn;525 AUXENT *aux;526 Entry *ep = &coff->ents[i];527528 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 }567568 return 0;569}570571int572coff32read(Obj *obj, FILE *fp)573{574575 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;589590 return validate(obj);591}