scc

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

coff32read.c (6197B)


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