scc

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

coff32read.c (6442B)


      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 
     10 #include "../libmach.h"
     11 #include "coff32.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 	           "lls",
     39 	           &lp->l_symndx,
     40 	           &lp->l_paddr,
     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 
     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 
     66 static void
     67 unpack_ent(int order, unsigned char *buf, SYMENT *ent)
     68 {
     69 	int n;
     70 	char *s;
     71 
     72 	n = unpack(order,
     73 	           buf,
     74 	           "'8lsscc",
     75 	           ent->n_name,
     76 	           &ent->n_value,
     77 	           &ent->n_scnum,
     78 	           &ent->n_type,
     79 	           &ent->n_sclass,
     80 	           &ent->n_numaux);
     81 	assert(n == SYMESZ);
     82 
     83 	s = ent->n_name;
     84 	if (!s[0] && !s[1] && !s[2] && !s[3])
     85 		unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset);
     86 }
     87 
     88 static void
     89 unpack_reloc(int order, unsigned char *buf, RELOC *rel)
     90 {
     91 	int n;
     92 
     93 	n = unpack(order,
     94 	           buf,
     95 	           "lls",
     96 	           &rel->r_vaddr,
     97 	           &rel->r_symndx,
     98 	           &rel->r_type);
     99 	assert(n == RELSZ);
    100 }
    101 
    102 static void
    103 unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)
    104 {
    105 	int n;
    106 
    107 	n = unpack(order,
    108 	           buf,
    109 	           "ssllllll",
    110 	           &aout->magic,
    111 	           &aout->vstamp,
    112 	           &aout->tsize,
    113 	           &aout->dsize,
    114 	           &aout->bsize,
    115 	           &aout->entry,
    116 	           &aout->text_start,
    117 	           &aout->data_start);
    118 	assert(n == AOUTSZ);
    119 }
    120 
    121 static int
    122 readhdr(Obj *obj, FILE *fp)
    123 {
    124 	FILHDR *hdr;
    125 	struct coff32 *coff;
    126 	unsigned char buf[FILHSZ];
    127 
    128 	coff  = obj->data;
    129 	hdr = &coff->hdr;
    130 
    131 	if (fread(buf, FILHSZ, 1, fp) != 1)
    132 		return 0;
    133 	unpack_hdr(ORDER(obj->type), buf, hdr);
    134 
    135 	return 1;
    136 }
    137 
    138 static int
    139 readstr(Obj *obj, FILE *fp)
    140 {
    141 	FILHDR *hdr;
    142 	struct coff32 *coff;
    143 	long siz;
    144 	char *str;
    145 	unsigned char buf[10];
    146 
    147 	coff  = obj->data;
    148 	hdr = &coff->hdr;
    149 
    150 	coff->strsiz = 0;
    151 	coff->strtbl = NULL;
    152 
    153 	if (hdr->f_nsyms == 0)
    154 		return 1;
    155 
    156 	if (fread(buf, 4, 1, fp) != 1)
    157 		return 0;
    158 	unpack(ORDER(obj->type), buf, "l", &siz);
    159 	if (siz < 4 || siz > SIZE_MAX)
    160 		return 0;
    161 	if (siz == 4)
    162 		return 1;
    163 
    164 	if ((str = malloc(siz)) == NULL)
    165 		return 0;
    166 	coff->strtbl = str;
    167 	coff->strsiz = siz;
    168 
    169 	return fread(str+4, siz-4, 1, fp) == 1;
    170 }
    171 
    172 static int
    173 readreloc(Obj *obj, FILE *fp)
    174 {
    175 	int i;
    176 	long j;
    177 	RELOC **rels, *rp;
    178 	SCNHDR *scn;
    179 	FILHDR *hdr;
    180 	struct coff32 *coff;
    181 	unsigned char buf[RELSZ];
    182 
    183 	coff  = obj->data;
    184 	hdr = &coff->hdr;
    185 
    186 	if (hdr->f_nscns == 0)
    187 		return 1;
    188 
    189 	rels = calloc(hdr->f_nscns, sizeof(*rels));
    190 	if (!rels)
    191 		return 0;
    192 	coff->rels = rels;
    193 
    194 	for (i = 0; i < hdr->f_nscns; i++) {
    195 		scn = &coff->scns[i];
    196 		if (scn->s_nrelloc == 0)
    197 			continue;
    198 
    199 		if (!objpos(obj, fp, scn->s_relptr))
    200 			return 0;
    201 
    202 		rp = calloc(scn->s_nrelloc, sizeof(RELOC));
    203 		if (!rp)
    204 			return 0;
    205 		rels[i] = rp;
    206 
    207 		for (j = 0; j < scn->s_nrelloc; j++) {
    208 			if (fread(buf, RELSZ, 1, fp) != 1)
    209 				return 0;
    210 			unpack_reloc(ORDER(obj->type), buf, &rp[i]);
    211 			if (rp[i].r_symndx >= hdr->f_nsyms)
    212 				return 0;
    213 		}
    214 	}
    215 
    216 	return 1;
    217 }
    218 
    219 static int
    220 readents(Obj *obj, FILE *fp)
    221 {
    222 	FILHDR *hdr;
    223 	struct coff32 *coff;
    224 	SYMENT *ent;
    225 	long i;
    226 	unsigned char buf[SYMESZ];
    227 
    228 	coff  = obj->data;
    229 	hdr = &coff->hdr;
    230 
    231 	if (hdr->f_nsyms == 0)
    232 		return 1;
    233 
    234 	ent = calloc(hdr->f_nsyms, sizeof(*ent));
    235 	if (!ent)
    236 		return 0;
    237 	coff->ents = ent;
    238 
    239 	if (!objpos(obj, fp, hdr->f_symptr))
    240 		return 0;
    241 	for (i = 0; i < hdr->f_nsyms; i++) {
    242 		if (fread(buf, SYMESZ, 1, fp) != 1)
    243 			return 0;
    244 		unpack_ent(ORDER(obj->type), buf, &ent[i]);
    245 		if (ent->n_scnum > hdr->f_nscns)
    246 			return 0;		
    247 	}
    248 
    249 	return 1;
    250 }
    251 
    252 static int
    253 readscns(Obj *obj, FILE *fp)
    254 {
    255 	FILHDR *hdr;
    256 	struct coff32 *coff;
    257 	SCNHDR *scn;
    258 	long i;
    259 	unsigned char buf[SCNHSZ];
    260 
    261 	coff  = obj->data;
    262 	hdr = &coff->hdr;
    263 
    264 	if (hdr->f_nscns == 0)
    265 		return 1;
    266 
    267 	scn = calloc(hdr->f_nscns, sizeof(*scn));
    268 	if (!scn)
    269 		return 0;
    270 	coff->scns = scn;
    271 
    272 	for (i = 0; i < hdr->f_nscns; i++) {
    273 		if (fread(buf, SCNHSZ, 1, fp) < 0)
    274 			return 0;
    275 		unpack_scn(ORDER(obj->type), buf, &scn[i]);
    276 	}
    277 
    278 	return 1;
    279 }
    280 
    281 static int
    282 readlines(Obj *obj, FILE *fp)
    283 {
    284 	int i,j;
    285 	LINENO **lines, *lp;
    286 	FILHDR *hdr;
    287 	SCNHDR *scn;
    288 	struct coff32 *coff;
    289 	unsigned char buf[LINESZ];
    290 
    291 	coff  = obj->data;
    292 	hdr = &coff->hdr;
    293 
    294 	if (hdr->f_nscns == 0)
    295 		return 1;
    296 
    297 	lines = calloc(hdr->f_nscns, sizeof(lp));
    298 	if (!lines)
    299 		return 0;
    300 	coff->lines = lines;
    301 
    302 	for (i = 0; i < hdr->f_nscns; i++) {
    303 		scn = &coff->scns[i];
    304 		if (scn->s_nlnno == 0)
    305 			continue;
    306 
    307 		lp = calloc(sizeof(*lp), scn->s_nlnno);
    308 		if (!lp)
    309 			return 0;
    310 		lines[i] = lp;
    311 
    312 		for (j = 0; j < scn->s_nlnno; j++) {
    313 			if (!objpos(obj, fp, scn->s_lnnoptr))
    314 				return 0;
    315 			if (fread(buf, LINESZ, 1, fp) == 1)
    316 				return 0;
    317 			unpack_line(ORDER(obj->type), buf, &lp[j]);
    318 			if (lp[i].l_symndx >= hdr->f_nsyms)
    319 				return 0;
    320 		}
    321 	}
    322 
    323 	return 1;
    324 }
    325 
    326 static int
    327 readaout(Obj *obj, FILE *fp)
    328 {
    329 	struct coff32 *coff = obj->data;
    330 	FILHDR *hdr = &coff->hdr;
    331 	unsigned char buf[AOUTSZ];
    332 
    333 	if (hdr->f_opthdr == 0)
    334 		return 1;
    335 
    336 	if (fread(buf, AOUTSZ, 1, fp) != 1)
    337 		return 0;
    338 
    339 	unpack_aout(ORDER(obj->type), buf, &coff->aout);
    340 
    341 	return 1;
    342 }
    343 
    344 int
    345 coff32read(Obj *obj, FILE *fp)
    346 {
    347 	long i;
    348 	struct coff32 *coff = obj->data;
    349 	FILHDR *hdr = &coff->hdr;
    350 
    351 	if (!readhdr(obj, fp))
    352 		return -1;
    353 	if (!readaout(obj, fp))
    354 		return -1;
    355 	if (!readscns(obj, fp))
    356 		return -1;
    357 	if (!readents(obj, fp))
    358 		return -1;
    359 	if (!readstr(obj, fp))
    360 		return -1;
    361 	if (!readreloc(obj, fp))
    362 		return -1;
    363 	if (!readlines(obj, fp))
    364 		return -1;
    365 
    366 	for (i = 0; i < hdr->f_nsyms; i++) {
    367 		SYMENT *ent = &coff->ents[i];
    368 		if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz)
    369 			return -1;
    370 	}
    371 
    372 	return 0;
    373 }