scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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 }