scc

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

coff32read.c (6434B)


      1 #include <assert.h>
      2 #include <ctype.h>
      3 #include <errno.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include <scc/mach.h>
     10 
     11 #include "../libmach.h"
     12 #include "coff32.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 	           "lls",
     40 	           &lp->l_symndx,
     41 	           &lp->l_paddr,
     42 	           &lp->l_lnno);
     43 	assert(n == LINESZ);
     44 }
     45 
     46 static void
     47 unpack_scn(int order, unsigned char *buf, SCNHDR *scn)
     48 {
     49 	int n;
     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 
     67 static void
     68 unpack_ent(int order, unsigned char *buf, SYMENT *ent)
     69 {
     70 	int n;
     71 	char *s;
     72 
     73 	n = unpack(order,
     74 	           buf,
     75 	           "'8lsscc",
     76 	           ent->n_name,
     77 	           &ent->n_value,
     78 	           &ent->n_scnum,
     79 	           &ent->n_type,
     80 	           &ent->n_sclass,
     81 	           &ent->n_numaux);
     82 	assert(n == SYMESZ);
     83 
     84 	s = ent->n_name;
     85 	if (!s[0] && !s[1] && !s[2] && !s[3])
     86 		unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset);
     87 }
     88 
     89 static void
     90 unpack_reloc(int order, unsigned char *buf, RELOC *rel)
     91 {
     92 	int n;
     93 
     94 	n = unpack(order,
     95 	           buf,
     96 	           "lls",
     97 	           &rel->r_vaddr,
     98 	           &rel->r_symndx,
     99 	           &rel->r_type);
    100 	assert(n == RELSZ);
    101 }
    102 
    103 static void
    104 unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)
    105 {
    106 	int n;
    107 
    108 	n = unpack(order,
    109 	           buf,
    110 	           "ssllllll",
    111 	           &aout->magic,
    112 	           &aout->vstamp,
    113 	           &aout->tsize,
    114 	           &aout->dsize,
    115 	           &aout->bsize,
    116 	           &aout->entry,
    117 	           &aout->text_start,
    118 	           &aout->data_start);
    119 	assert(n == AOUTSZ);
    120 }
    121 
    122 static int
    123 readhdr(Obj *obj, FILE *fp)
    124 {
    125 	FILHDR *hdr;
    126 	struct coff32 *coff;
    127 	unsigned char buf[FILHSZ];
    128 
    129 	coff  = obj->data;
    130 	hdr = &coff->hdr;
    131 
    132 	if (fread(buf, FILHSZ, 1, fp) != 1)
    133 		return 0;
    134 	unpack_hdr(ORDER(obj->type), buf, hdr);
    135 
    136 	return 1;
    137 }
    138 
    139 static int
    140 readstr(Obj *obj, FILE *fp)
    141 {
    142 	FILHDR *hdr;
    143 	struct coff32 *coff;
    144 	long siz;
    145 	char *str;
    146 	unsigned char buf[10];
    147 
    148 	coff  = obj->data;
    149 	hdr = &coff->hdr;
    150 
    151 	if (hdr->f_nsyms == 0)
    152 		return 1;
    153 
    154 	if (fread(buf, 4, 1, fp) != 1)
    155 		return 0;
    156 	unpack(ORDER(obj->type), buf, "l", &siz);
    157 	coff->strsiz = 0;
    158 	if (siz < 4 || siz > SIZE_MAX) {
    159 		errno = ERANGE;
    160 		return 0;
    161 	}
    162 	if (siz == 4)
    163 		return 1;
    164 
    165 	if ((str = malloc(siz)) == NULL)
    166 		return 0;
    167 	coff->strtbl = str;
    168 	coff->strsiz = siz;
    169 
    170 	return fread(str+4, siz-4, 1, fp) == 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(hdr->f_nscns, 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 			if (rp[i].r_symndx >= hdr->f_nsyms) {
    210 				errno = ERANGE;
    211 				return 0;
    212 			}
    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 		scn = calloc(hdr->f_nscns, sizeof(*scn));
    266 		if (!scn)
    267 			return 0;
    268 		coff->scns = scn;
    269 	}
    270 
    271 	for (i = 0; i < hdr->f_nscns; i++) {
    272 		if (fread(buf, SCNHSZ, 1, fp) < 0)
    273 			return 0;
    274 		unpack_scn(ORDER(obj->type), buf, &scn[i]);
    275 	}
    276 
    277 	return 1;
    278 }
    279 
    280 static int
    281 readlines(Obj *obj, FILE *fp)
    282 {
    283 	int i,j;
    284 	LINENO **lines, *lp;
    285 	FILHDR *hdr;
    286 	SCNHDR *scn;
    287 	struct coff32 *coff;
    288 	unsigned char buf[LINESZ];
    289 
    290 	coff  = obj->data;
    291 	hdr = &coff->hdr;
    292 
    293 	lines = calloc(sizeof(lp), hdr->f_nscns);
    294 	if (!lines)
    295 		return 0;
    296 	coff->lines = lines;
    297 
    298 	for (i = 0; i < hdr->f_nscns; i++) {
    299 		scn = &coff->scns[i];
    300 		if (scn->s_nlnno == 0)
    301 			continue;
    302 
    303 		lp = calloc(sizeof(*lp), scn->s_nlnno);
    304 		if (!lp)
    305 			return 0;
    306 		lines[i] = lp;
    307 
    308 		for (j = 0; j < scn->s_nlnno; j++) {
    309 			if (!objpos(obj, fp, scn->s_lnnoptr))
    310 				return 0;
    311 			if (fread(buf, LINESZ, 1, fp) == 1)
    312 				return 0;
    313 			unpack_line(ORDER(obj->type), buf, &lp[j]);
    314 			if (lp[i].l_symndx >= hdr->f_nsyms)
    315 				return 0;
    316 		}
    317 	}
    318 
    319 	return 1;
    320 }
    321 
    322 static int
    323 readaout(Obj *obj, FILE *fp)
    324 {
    325 	struct coff32 *coff = obj->data;
    326 	FILHDR *hdr = &coff->hdr;
    327 	unsigned char buf[AOUTSZ];
    328 
    329 	if (hdr->f_opthdr == 0)
    330 		return 1;
    331 
    332 	if (fread(buf, AOUTSZ, 1, fp) != 1)
    333 		return 0;
    334 
    335 	unpack_aout(ORDER(obj->type), buf, &coff->aout);
    336 
    337 	return 1;
    338 }
    339 
    340 int
    341 coff32read(Obj *obj, FILE *fp)
    342 {
    343 	long i;
    344 	struct coff32 *coff = obj->data;
    345 	FILHDR *hdr = &coff->hdr;
    346 
    347 	if (!readhdr(obj, fp))
    348 		return -1;
    349 	if (!readaout(obj, fp))
    350 		return -1;
    351 	if (!readscns(obj, fp))
    352 		return -1;
    353 	if (!readents(obj, fp))
    354 		return -1;
    355 	if (!readstr(obj, fp))
    356 		return -1;
    357 	if (!readreloc(obj, fp))
    358 		return -1;
    359 	if (!readlines(obj, fp))
    360 		return -1;
    361 
    362 	for (i = 0; i < hdr->f_nsyms; i++) {
    363 		SYMENT *ent = &coff->ents[i];
    364 		if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz) {
    365 			errno = ERANGE;
    366 			return -1;
    367 		}
    368 	}
    369 
    370 	return 0;
    371 }