scc

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

coff32write.c (6354B)


      1 #include <assert.h>
      2 #include <limits.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 pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
     15 {
     16 	int n;
     17 
     18 	n = pack(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 pack_scn(int order, unsigned char *buf, SCNHDR *scn)
     33 {
     34 	int n;
     35 
     36 	n = pack(order,
     37 	         buf,
     38 	         "'8llllllssl",
     39 	         scn->s_name,
     40 	         scn->s_paddr,
     41 	         scn->s_vaddr,
     42 	         scn->s_size,
     43 	         scn->s_scnptr,
     44 	         scn->s_relptr,
     45 	         scn->s_lnnoptr,
     46 	         scn->s_nrelloc,
     47 	         scn->s_nlnno,
     48 	         scn->s_flags);
     49 	assert(n == SCNHSZ);
     50 }
     51 
     52 static void
     53 pack_ent(int order, unsigned char *buf, SYMENT *ent)
     54 {
     55 	int n;
     56 	char *s;
     57 
     58 	/* TODO: What happens with the union? */
     59 
     60 	n = pack(order,
     61 	         buf,
     62 	         "'8lsscc",
     63 	         ent->n_name,
     64 	         ent->n_value,
     65 	         ent->n_scnum,
     66 	         ent->n_type,
     67 	         ent->n_sclass,
     68 	         ent->n_numaux);
     69 	assert(n == SYMESZ);
     70 }
     71 
     72 static void
     73 pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
     74 {
     75 	int n;
     76 
     77 	n = pack(order,
     78 	         buf,
     79 	         "ssllllll",
     80 	         aout->magic,
     81 	         aout->vstamp,
     82 	         aout->tsize,
     83 	         aout->dsize,
     84 	         aout->bsize,
     85 	         aout->entry,
     86 	         aout->text_start,
     87 	         aout->data_start);
     88 	assert(n == AOUTSZ);
     89 }
     90 
     91 static void
     92 pack_reloc(int order, unsigned char *buf, RELOC *rel)
     93 {
     94 	int n;
     95 
     96 	n = pack(order,
     97 	         buf,
     98 	         "lls",
     99 	         rel->r_vaddr,
    100 	         rel->r_symndx,
    101 	         rel->r_type);
    102 	assert(n == RELSZ);
    103 }
    104 
    105 static void
    106 pack_line(int order, unsigned char *buf, LINENO *lp)
    107 {
    108 	int n;
    109 
    110 	n = pack(order,
    111 	         buf,
    112 	         "lls",
    113 	         lp->l_symndx,
    114 	         lp->l_paddr,
    115 	         lp->l_lnno);
    116 	assert(n == LINESZ);
    117 }
    118 
    119 static int
    120 writehdr(Obj *obj, FILE *fp)
    121 {
    122 	FILHDR *hdr;
    123 	struct coff32 *coff;
    124 	unsigned char buf[FILHSZ];
    125 
    126 	coff  = obj->data;
    127 	hdr = &coff->hdr;
    128 
    129 	pack_hdr(ORDER(obj->type), buf, hdr);
    130 	if (fwrite(buf, FILHSZ, 1, fp) != 1)
    131 		return 0;
    132 
    133 	return 1;
    134 }
    135 
    136 static int
    137 writescns(Obj *obj, FILE *fp)
    138 {
    139 	int i;
    140 	SCNHDR *scn;
    141 	FILHDR *hdr;
    142 	struct coff32 *coff;
    143 	unsigned char buf[SCNHSZ];
    144 
    145 	coff  = obj->data;
    146 	hdr = &coff->hdr;
    147 
    148 	for (i = 0; i < hdr->f_nscns; i++) {
    149 		scn = &coff->scns[i];
    150 		pack_scn(ORDER(obj->type), buf, scn);
    151 		if (fwrite(buf, SCNHSZ, 1, fp) != 1)
    152 			return 0;
    153 	}
    154 
    155 	return 1;
    156 }
    157 
    158 static int
    159 writeents(Obj *obj, FILE *fp)
    160 {
    161 	long i, len, strsiz;
    162 	char *strtbl, *s;
    163 	FILHDR *hdr;
    164 	struct coff32 *coff;
    165 	unsigned char buf[SYMESZ];
    166 
    167 	coff  = obj->data;
    168 	hdr = &coff->hdr;
    169 
    170 	if (!coff->ents)
    171 		return 1;
    172 
    173 	strtbl = NULL;
    174 	strsiz = 0;
    175 
    176 	for (i = 0; i < hdr->f_nsyms; i++) {
    177 		SYMENT *ent = &coff->ents[i];
    178 
    179 		len = strlen(ent->n_name) + 1;
    180 		if (len > strsiz - LONG_MAX)
    181 			goto err;
    182 		s = realloc(strtbl, strsiz + len);
    183 		if (!s)
    184 			goto err;
    185 		memcpy(s + strsiz, ent->n_name, len);
    186 		strtbl = s;
    187 		strsiz += len;
    188 
    189 		pack_ent(ORDER(obj->type), buf, ent);
    190 		if (fwrite(buf, SYMESZ, 1, fp) != 1)
    191 			return 0;
    192 	}
    193 
    194 	free(coff->strtbl);
    195 	coff->strtbl = strtbl;
    196 	coff->strsiz = strsiz;
    197 
    198 	return 1;
    199 
    200 err:
    201 	free(strtbl);
    202 	return 0;
    203 }
    204 
    205 static int
    206 writestr(Obj *obj, FILE *fp)
    207 {
    208 	struct coff32 *coff;
    209 	unsigned char buf[4];
    210 
    211 	coff = obj->data;
    212 	if ((coff->strsiz & 0xffff) != coff->strsiz)
    213 		return 0;
    214 
    215 	pack(ORDER(obj->type), buf, "l", coff->strsiz);
    216 	fwrite(buf, 4, 1, fp);
    217 	fwrite(coff->strtbl, coff->strsiz, 1, fp);
    218 
    219 	return ferror(fp) == 0;
    220 }
    221 
    222 static int
    223 writeaout(Obj *obj, FILE *fp)
    224 {
    225 	FILHDR *hdr;
    226 	struct coff32 *coff;
    227 	unsigned char buf[AOUTSZ];
    228 
    229 	coff  = obj->data;
    230 	hdr = &coff->hdr;
    231 
    232 	if (hdr->f_opthdr == 0)
    233 		return 1;
    234 	pack_aout(ORDER(obj->type), buf, &coff->aout);
    235 
    236 	return fread(buf, AOUTSZ, 1, fp) != 1;
    237 }
    238 
    239 static int
    240 writereloc(Obj *obj, FILE *fp)
    241 {
    242 	int i, j;
    243 	RELOC *rp;
    244 	SCNHDR *scn;
    245 	FILHDR *hdr;
    246 	struct coff32 *coff;
    247 	unsigned char buf[RELSZ];
    248 
    249 	coff  = obj->data;
    250 	hdr = &coff->hdr;
    251 
    252 	if (!coff->rels)
    253 		return 1;
    254 
    255 	for (i = 0; i < hdr->f_nscns; i++) {
    256 		rp = coff->rels[i];
    257 		if (!rp)
    258 			continue;
    259 		scn = &coff->scns[i];
    260 
    261 		for (j = 0; j < scn->s_nrelloc; j++) {
    262 			pack_reloc(ORDER(obj->type), buf, &rp[i]);
    263 			if (fwrite(buf, RELSZ, 1, fp) != 1)
    264 				return 0;
    265 		}
    266 	}
    267 
    268 	return 1;
    269 }
    270 
    271 static int
    272 writelines(Obj *obj, FILE *fp)
    273 {
    274 	int i;
    275 	long j;
    276 	LINENO *lp;
    277 	SCNHDR *scn;
    278 	struct coff32 *coff = obj->data;
    279 	FILHDR *hdr = &coff->hdr;
    280 	unsigned char buf[LINESZ];
    281 
    282 	if (!coff->lines)
    283 		return 1;
    284 
    285         for (i = 0; i < hdr->f_nscns; i++) {
    286 		lp = coff->lines[i];
    287 		if (!lp)
    288 			continue;
    289 		scn = &coff->scns[i];
    290 		for (j = 0; j < scn->s_nlnno; j++) {
    291 			pack_line(ORDER(obj->type), buf, &lp[j]);
    292 			if (fwrite(buf, LINESZ, 1, fp) == 1)
    293 				return 0;
    294 		}
    295 	}
    296 
    297 	return 1;
    298 }
    299 
    300 static int
    301 writedata(Obj *obj, Map *map, FILE *fp)
    302 {
    303 	int id;
    304 	long nsec;
    305 	unsigned long long n;
    306 	struct coff32 *coff = obj->data;
    307 	FILHDR *hdr = &coff->hdr;
    308 	SCNHDR *scn;
    309 	Mapsec *sec;
    310 
    311 	nsec = hdr->f_nscns;
    312 	for (scn = coff->scns; nsec--; scn++) {
    313 		if ((id = findsec(map, scn->s_name)) < 0)
    314 			return 0;
    315 		sec = &map->sec[id];
    316 		fseek(sec->fp, sec->offset, SEEK_SET);
    317 
    318 		for (n = sec->end - sec->begin; n > 0; n--)
    319 			putc(getc(sec->fp), fp);
    320 	}
    321 
    322 	return !ferror(fp);
    323 }
    324 
    325 int
    326 coff32write(Obj *obj, Map *map, FILE *fp)
    327 {
    328 	long ptr, n;
    329 	SCNHDR *scn;
    330 	struct coff32 *coff = obj->data;
    331 	FILHDR *hdr = &coff->hdr;
    332 
    333 	ptr = ftell(fp);
    334 	obj->pos = ptr;
    335 	ptr += FILHSZ + AOUTSZ + n*hdr->f_nscns;
    336 
    337 	n = hdr->f_nscns;
    338 	for (scn = coff->scns; n--; scn++) {
    339 		scn->s_scnptr = ptr;
    340 		ptr += scn->s_size;
    341 	}
    342 
    343 	n = hdr->f_nscns;
    344 	for (scn = coff->scns; n--; scn++) {
    345 		scn->s_relptr = ptr;
    346 		ptr += scn->s_nrelloc * RELSZ;
    347 	}
    348 
    349 	n = hdr->f_nscns;
    350 	for (scn = coff->scns; n--; scn++) {
    351 		scn->s_lnnoptr = ptr;
    352 		ptr += scn->s_nlnno * RELSZ;
    353 	}
    354 
    355 	/* and now update symbols */
    356 
    357 	if (!writehdr(obj, fp))
    358 		return -1;
    359 	if (!writeaout(obj, fp))
    360 		return -1;
    361 	if (!writescns(obj, fp))
    362 		return -1;
    363 	if (!writedata(obj, map, fp))
    364 		return -1;
    365 	if (!writereloc(obj, fp))
    366 		return -1;
    367 	if (!writelines(obj, fp))
    368 		return -1;
    369 	if (!writeents(obj, fp))
    370 		return -1;
    371 	if (!writestr(obj, fp))
    372 		return -1;
    373 
    374 	return 0;
    375 }