scc

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

coff32write.c (6703B)


      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, *name;
    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 		if (ent->n_zeroes == 0) {
    180 			name = &coff->strtbl[ent->n_offset];
    181 			len = strlen(name) + 1;
    182 			if (len > strsiz - LONG_MAX)
    183 				goto err;
    184 			s = realloc(strtbl, strsiz + len);
    185 			if (!s)
    186 				goto err;
    187 			memcpy(s + strsiz, name, len);
    188 			strtbl = s;
    189 			strsiz += len;
    190 		}
    191 
    192 		pack_ent(ORDER(obj->type), buf, ent);
    193 		if (fwrite(buf, SYMESZ, 1, fp) != 1)
    194 			return 0;
    195 	}
    196 
    197 	free(coff->strtbl);
    198 	coff->strtbl = strtbl;
    199 	coff->strsiz = strsiz;
    200 
    201 	return 1;
    202 
    203 err:
    204 	free(strtbl);
    205 	return 0;
    206 }
    207 
    208 static int
    209 writestr(Obj *obj, FILE *fp)
    210 {
    211 	struct coff32 *coff;
    212 	unsigned char buf[4];
    213 
    214 	coff = obj->data;
    215 	if ((coff->strsiz & 0xffff) != coff->strsiz)
    216 		return 0;
    217 
    218 	pack(ORDER(obj->type), buf, "l", coff->strsiz);
    219 	fwrite(buf, 4, 1, fp);
    220 	fwrite(coff->strtbl, coff->strsiz, 1, fp);
    221 
    222 	return 1;
    223 }
    224 
    225 static int
    226 writeaout(Obj *obj, FILE *fp)
    227 {
    228 	FILHDR *hdr;
    229 	struct coff32 *coff;
    230 	unsigned char buf[AOUTSZ];
    231 
    232 	coff  = obj->data;
    233 	hdr = &coff->hdr;
    234 
    235 	if (hdr->f_opthdr == 0)
    236 		return 1;
    237 	pack_aout(ORDER(obj->type), buf, &coff->aout);
    238 
    239 	return fread(buf, AOUTSZ, 1, fp) != 1;
    240 }
    241 
    242 static int
    243 writereloc(Obj *obj, FILE *fp)
    244 {
    245 	int i, j;
    246 	RELOC *rp;
    247 	SCNHDR *scn;
    248 	FILHDR *hdr;
    249 	struct coff32 *coff;
    250 	unsigned char buf[RELSZ];
    251 
    252 	coff  = obj->data;
    253 	hdr = &coff->hdr;
    254 
    255 	if (!coff->rels)
    256 		return 1;
    257 
    258 	for (i = 0; i < hdr->f_nscns; i++) {
    259 		rp = coff->rels[i];
    260 		if (!rp)
    261 			continue;
    262 		scn = &coff->scns[i];
    263 
    264 		for (j = 0; j < scn->s_nrelloc; j++) {
    265 			pack_reloc(ORDER(obj->type), buf, &rp[i]);
    266 			if (fwrite(buf, RELSZ, 1, fp) != 1)
    267 				return 0;
    268 		}
    269 	}
    270 
    271 	return 1;
    272 }
    273 
    274 static int
    275 writelines(Obj *obj, FILE *fp)
    276 {
    277 	int i;
    278 	long j;
    279 	LINENO *lp;
    280 	SCNHDR *scn;
    281 	struct coff32 *coff = obj->data;
    282 	FILHDR *hdr = &coff->hdr;
    283 	unsigned char buf[LINESZ];
    284 
    285 	if (!coff->lines)
    286 		return 1;
    287 
    288         for (i = 0; i < hdr->f_nscns; i++) {
    289 		lp = coff->lines[i];
    290 		if (!lp)
    291 			continue;
    292 		scn = &coff->scns[i];
    293 		for (j = 0; j < scn->s_nlnno; j++) {
    294 			pack_line(ORDER(obj->type), buf, &lp[j]);
    295 			if (fwrite(buf, LINESZ, 1, fp) == 1)
    296 				return 0;
    297 		}
    298 	}
    299 
    300 	return 1;
    301 }
    302 
    303 static int
    304 writedata(Obj *obj, Map *map, FILE *fp)
    305 {
    306 	int id;
    307 	long nsec;
    308 	unsigned long long n;
    309 	struct coff32 *coff = obj->data;
    310 	FILHDR *hdr = &coff->hdr;
    311 	SCNHDR *scn;
    312 	Mapsec *sec;
    313 
    314 	nsec = hdr->f_nscns;
    315 	for (scn = coff->scns; nsec--; scn++) {
    316 		if ((id = findsec(map, scn->s_name)) < 0)
    317 			continue;
    318 		sec = &map->sec[id];
    319 		if (!sec->fp)
    320 			continue;
    321 
    322 		fseek(sec->fp, sec->offset, SEEK_SET);
    323 
    324 		for (n = sec->end - sec->begin; n > 0; n--)
    325 			putc(getc(sec->fp), fp);
    326 
    327 		if (ferror(sec->fp))
    328 			return 0;
    329 	}
    330 
    331 	return 1;
    332 }
    333 
    334 int
    335 coff32write(Obj *obj, Map *map, FILE *fp)
    336 {
    337 	int id;
    338 	long ptr, n;
    339 	SCNHDR *scn;
    340 	Mapsec *sec;
    341 	struct coff32 *coff = obj->data;
    342 	FILHDR *hdr = &coff->hdr;
    343 
    344 	ptr = ftell(fp);
    345 	obj->pos = ptr;
    346 
    347 	n = hdr->f_nscns;
    348 	ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ;
    349 	for (scn = coff->scns; n--; scn++) {
    350 		scn->s_scnptr = 0;
    351 		if ((id = findsec(map, scn->s_name)) < 0)
    352 			continue;
    353 		sec = &map->sec[id];
    354 		if (!sec->fp)
    355 			continue;
    356 
    357 		scn->s_scnptr = ptr;
    358 		ptr += scn->s_size;
    359 	}
    360 	hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0;
    361 
    362 	n = hdr->f_nscns;
    363 	for (scn = coff->scns; n--; scn++) {
    364 		scn->s_relptr = ptr;
    365 		ptr += scn->s_nrelloc * RELSZ;
    366 	}
    367 
    368 	n = hdr->f_nscns;
    369 	for (scn = coff->scns; n--; scn++) {
    370 		scn->s_lnnoptr = ptr;
    371 		ptr += scn->s_nlnno * RELSZ;
    372 	}
    373 
    374 	/* and now update symbols */
    375 
    376 	if (!writehdr(obj, fp))
    377 		return -1;
    378 	if (!writeaout(obj, fp))
    379 		return -1;
    380 	if (!writescns(obj, fp))
    381 		return -1;
    382 	if (!writedata(obj, map, fp))
    383 		return -1;
    384 	if (!writereloc(obj, fp))
    385 		return -1;
    386 	if (!writelines(obj, fp))
    387 		return -1;
    388 	if (!writeents(obj, fp))
    389 		return -1;
    390 	if (!writestr(obj, fp))
    391 		return -1;
    392 	if (ferror(fp))
    393 		return -1;
    394 
    395 	return 0;
    396 }