scc

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

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 }