scc

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

coff32write.c (9373B)


      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 #include <scc/coff32.h>
     10 
     11 #include "../libmach.h"
     12 #include "fun.h"
     13 
     14 struct strtbl {
     15 	char *s;
     16 	long siz;
     17 };
     18 
     19 static void
     20 pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
     21 {
     22 	int n;
     23 
     24 	n = pack(order,
     25 	         buf,
     26 	         "sslllss",
     27 	         hdr->f_magic,
     28 	         hdr->f_nscns,
     29 	         hdr->f_timdat,
     30 	         hdr->f_symptr,
     31 	         hdr->f_nsyms,
     32 	         hdr->f_opthdr,
     33 	         hdr->f_flags);
     34 	assert(n == FILHSZ);
     35 }
     36 
     37 static void
     38 pack_scn(int order, unsigned char *buf, SCNHDR *scn)
     39 {
     40 	int n;
     41 
     42 	if (scn->s_zeroes == 0)
     43 		pack(order, buf, "ll", scn->s_zeroes, scn->s_offset);
     44 	else
     45 		memcpy(buf, scn->s_name, 8);
     46 
     47 	n = pack(order,
     48 	         buf + 8,
     49 	         "llllllssl",
     50 	         scn->s_paddr,
     51 	         scn->s_vaddr,
     52 	         scn->s_size,
     53 	         scn->s_scnptr,
     54 	         scn->s_relptr,
     55 	         scn->s_lnnoptr,
     56 	         scn->s_nrelloc,
     57 	         scn->s_nlnno,
     58 	         scn->s_flags);
     59 	n += 8;
     60 	assert(n == SCNHSZ);
     61 }
     62 
     63 static void
     64 pack_ent(int order, unsigned char *buf, SYMENT *ent)
     65 {
     66 	int n;
     67 
     68 	if (ent->n_zeroes == 0)
     69 		pack(order, buf, "ll", ent->n_zeroes, ent->n_offset);
     70 	else
     71 		memcpy(buf, ent->n_name, 8);
     72 
     73 	n = pack(order,
     74 	         buf + 8,
     75 	         "lsscc",
     76 		     ent->n_value,
     77 		     ent->n_scnum,
     78 		     ent->n_type,
     79 		     ent->n_sclass,
     80 		     ent->n_numaux);
     81 	n += 8;
     82 
     83 	assert(n == SYMESZ);
     84 }
     85 
     86 static void
     87 pack_aux_file(int order, unsigned char *buf, AUXENT *aux)
     88 {
     89 
     90 	if (aux->x_zeroes == 0) {
     91 		memset(buf, 0, sizeof(AUXESZ));
     92 		pack(order, buf, "ll", aux->x_zeroes, aux->x_offset);
     93 	} else {
     94 		memcpy(buf, aux->x_fname, E_FILNMLEN);
     95 	}
     96 }
     97 
     98 static void
     99 pack_aux_scn(int order, unsigned char *buf, AUXENT *aux)
    100 {
    101 	int n;
    102 
    103 	n = pack(order,
    104 	         buf,
    105 	         "lsslsc",
    106 	         aux->x_scnlen,
    107 	         aux->x_nreloc,
    108 	         aux->x_nlinno,
    109 	         aux->x_checksum,
    110 	         aux->x_associated,
    111 	         aux->x_comdat);
    112 	assert(n == AUXESZ);
    113 }
    114 
    115 static void
    116 pack_aux_fun(int order, unsigned char *buf, AUXENT *aux)
    117 {
    118 	int n;
    119 
    120 	n = pack(order,
    121 	         buf,
    122 	         "lllls",
    123 	         aux->x_tagndx,
    124 	         aux->x_fsize,
    125 	         aux->x_lnnoptr,
    126 	         aux->x_endndx,
    127 	         aux->x_tvndx);
    128 	assert(n == AUXESZ);
    129 }
    130 
    131 static void
    132 pack_aux_ary(int order, unsigned char *buf, AUXENT *aux)
    133 {
    134 	int n;
    135 
    136 	n = pack(order,
    137 	         buf,
    138 	         "lssssss",
    139 	         aux->x_tagndx,
    140 	         aux->x_lnno,
    141 	         aux->x_size,
    142 	         aux->x_dimen[0],
    143 	         aux->x_dimen[1],
    144 	         aux->x_dimen[2],
    145 	         aux->x_dimen[3],
    146 	         aux->x_tvndx);
    147 	assert(n == AUXESZ);
    148 }
    149 
    150 static void
    151 pack_aux_sym(int order, unsigned char *buf, AUXENT *aux)
    152 {
    153 	int n;
    154 
    155 	n = pack(order,
    156 	         buf,
    157 	         "lsslls",
    158 	         aux->x_tagndx,
    159 	         aux->x_lnno,
    160 	         aux->x_size,
    161 	         aux->x_lnnoptr,
    162 	         aux->x_endndx,
    163 	         aux->x_tvndx);
    164 	assert(n == AUXESZ);
    165 }
    166 
    167 static void
    168 pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
    169 {
    170 	int n;
    171 
    172 	n = pack(order,
    173 	         buf,
    174 	         "ssllllll",
    175 	         aout->magic,
    176 	         aout->vstamp,
    177 	         aout->tsize,
    178 	         aout->dsize,
    179 	         aout->bsize,
    180 	         aout->entry,
    181 	         aout->text_start,
    182 	         aout->data_start);
    183 	assert(n == AOUTSZ);
    184 }
    185 
    186 static void
    187 pack_reloc(int order, unsigned char *buf, RELOC *rel)
    188 {
    189 	int n;
    190 
    191 	n = pack(order,
    192 	         buf,
    193 	         "lls",
    194 	         rel->r_vaddr,
    195 	         rel->r_symndx,
    196 	         rel->r_type);
    197 	assert(n == RELSZ);
    198 }
    199 
    200 static void
    201 pack_line(int order, unsigned char *buf, LINENO *lp)
    202 {
    203 	int n;
    204 
    205 	n = pack(order,
    206 	         buf,
    207 	         "lls",
    208 	         lp->l_addr.l_symndx,
    209 	         lp->l_lnno);
    210 	assert(n == LINESZ);
    211 }
    212 
    213 static int
    214 writehdr(Obj *obj, FILE *fp)
    215 {
    216 	FILHDR *hdr;
    217 	struct coff32 *coff;
    218 	unsigned char buf[FILHSZ];
    219 
    220 	coff  = obj->data;
    221 	hdr = &coff->hdr;
    222 
    223 	pack_hdr(ORDER(obj->type), buf, hdr);
    224 	if (fwrite(buf, FILHSZ, 1, fp) != 1)
    225 		return 0;
    226 
    227 	return 1;
    228 }
    229 
    230 static int
    231 allocstring(struct coff32 *coff, long off, struct strtbl *tbl)
    232 {
    233 	char *s, *name;
    234 	long len, siz;
    235 
    236 	siz = tbl->siz;
    237 	name = &coff->strtbl[off];
    238 	len = strlen(name) + 1;
    239 	if (len > siz - LONG_MAX)
    240 		return 0;
    241 
    242 	s = realloc(tbl->s, siz + len);
    243 	if (!s)
    244 		return 0;
    245 	memcpy(s + siz, name, len);
    246 
    247 	tbl->s = s;
    248 	tbl->siz += len;
    249 
    250 	return 1;
    251 }
    252 
    253 static int
    254 writescns(Obj *obj, FILE *fp, struct strtbl *tbl)
    255 {
    256 	int i;
    257 	SCNHDR *scn;
    258 	FILHDR *hdr;
    259 	struct coff32 *coff;
    260 	unsigned char buf[SCNHSZ];
    261 
    262 	coff  = obj->data;
    263 	hdr = &coff->hdr;
    264 
    265 	for (i = 0; i < hdr->f_nscns; i++) {
    266 		scn = &coff->scns[i];
    267 		if (scn->s_zeroes == 0) {
    268 			if (!allocstring(coff, scn->s_offset, tbl))
    269 				return 0;
    270 		}
    271 		pack_scn(ORDER(obj->type), buf, scn);
    272 		if (fwrite(buf, SCNHSZ, 1, fp) != 1)
    273 			return 0;
    274 	}
    275 
    276 	return 1;
    277 }
    278 
    279 static int
    280 writeents(Obj *obj, FILE *fp, struct strtbl *tbl)
    281 {
    282 	long i;
    283 	FILHDR *hdr;
    284 	struct coff32 *coff;
    285 	unsigned char buf[SYMESZ];
    286 
    287 	coff  = obj->data;
    288 	hdr = &coff->hdr;
    289 
    290 	if (!coff->ents)
    291 		return 1;
    292 
    293 	for (i = 0; i < hdr->f_nsyms; i++) {
    294 		SYMENT *ent;
    295 		AUXENT *aux;
    296 		Entry *ep = &coff->ents[i];
    297 
    298 		aux = &ep->u.aux;
    299 		switch (ep->type) {
    300 		case SYM_ENT:
    301 			ent = &ep->u.sym;
    302 			if (ent->n_zeroes == 0) {
    303 				if (!allocstring(coff, ent->n_offset, tbl))
    304 					return 0;
    305 			}
    306 			pack_ent(ORDER(obj->type), buf, ent);
    307 			break;
    308 		case SYM_AUX_UNK:
    309 			memcpy(buf, ep->u.buf, AUXESZ);
    310 			break;
    311 		case SYM_AUX_SYM:
    312 			pack_aux_file(ORDER(obj->type), buf, aux);
    313 			break;
    314 		case SYM_AUX_FILE:
    315 			if (aux->x_zeroes == 0) {
    316 				if (!allocstring(coff, aux->x_offset, tbl))
    317 					return 0;
    318 			}
    319 			pack_aux_file(ORDER(obj->type), buf, aux);
    320 			break;
    321 		case SYM_AUX_SCN:
    322 			pack_aux_scn(ORDER(obj->type), buf, aux);
    323 			break;
    324 		case SYM_AUX_FUN:
    325 			pack_aux_fun(ORDER(obj->type), buf, aux);
    326 			break;
    327 		case SYM_AUX_ARY:
    328 			pack_aux_ary(ORDER(obj->type), buf, aux);
    329 			break;
    330 		}
    331 
    332 		if (fwrite(buf, SYMESZ, 1, fp) != 1)
    333 			return 0;
    334 	}
    335 
    336 	return 1;
    337 }
    338 
    339 static int
    340 writestr(Obj *obj, FILE *fp, struct strtbl *tbl)
    341 {
    342 	struct coff32 *coff;
    343 	unsigned char buf[4];
    344 
    345 	coff = obj->data;
    346 
    347 	free(coff->strtbl);
    348 	coff->strtbl = tbl->s;
    349 	coff->strsiz = tbl->siz;
    350 	tbl->s = NULL;
    351 	tbl->siz = 0;
    352 
    353 	if ((coff->strsiz & 0xffff) != coff->strsiz)
    354 		return 0;
    355 
    356 	pack(ORDER(obj->type), buf, "l", coff->strsiz);
    357 	fwrite(buf, 4, 1, fp);
    358 	fwrite(coff->strtbl, coff->strsiz, 1, fp);
    359 
    360 	return 1;
    361 }
    362 
    363 static int
    364 writeaout(Obj *obj, FILE *fp)
    365 {
    366 	FILHDR *hdr;
    367 	struct coff32 *coff;
    368 	unsigned char buf[AOUTSZ];
    369 
    370 	coff  = obj->data;
    371 	hdr = &coff->hdr;
    372 
    373 	if (hdr->f_opthdr == 0)
    374 		return 1;
    375 	pack_aout(ORDER(obj->type), buf, &coff->aout);
    376 
    377 	return fread(buf, AOUTSZ, 1, fp) != 1;
    378 }
    379 
    380 static int
    381 writereloc(Obj *obj, FILE *fp)
    382 {
    383 	int i, j;
    384 	RELOC *rp;
    385 	SCNHDR *scn;
    386 	FILHDR *hdr;
    387 	struct coff32 *coff;
    388 	unsigned char buf[RELSZ];
    389 
    390 	coff  = obj->data;
    391 	hdr = &coff->hdr;
    392 
    393 	if (!coff->rels)
    394 		return 1;
    395 
    396 	for (i = 0; i < hdr->f_nscns; i++) {
    397 		rp = coff->rels[i];
    398 		if (!rp)
    399 			continue;
    400 		scn = &coff->scns[i];
    401 
    402 		for (j = 0; j < scn->s_nrelloc; j++) {
    403 			pack_reloc(ORDER(obj->type), buf, &rp[i]);
    404 			if (fwrite(buf, RELSZ, 1, fp) != 1)
    405 				return 0;
    406 		}
    407 	}
    408 
    409 	return 1;
    410 }
    411 
    412 static int
    413 writelines(Obj *obj, FILE *fp)
    414 {
    415 	int i;
    416 	long j;
    417 	LINENO *lp;
    418 	SCNHDR *scn;
    419 	struct coff32 *coff = obj->data;
    420 	FILHDR *hdr = &coff->hdr;
    421 	unsigned char buf[LINESZ];
    422 
    423 	if (!coff->lines)
    424 		return 1;
    425 
    426         for (i = 0; i < hdr->f_nscns; i++) {
    427 		lp = coff->lines[i];
    428 		if (!lp)
    429 			continue;
    430 		scn = &coff->scns[i];
    431 		for (j = 0; j < scn->s_nlnno; j++) {
    432 			pack_line(ORDER(obj->type), buf, &lp[j]);
    433 			if (fwrite(buf, LINESZ, 1, fp) == 1)
    434 				return 0;
    435 		}
    436 	}
    437 
    438 	return 1;
    439 }
    440 
    441 static int
    442 writedata(Obj *obj, Map *map, FILE *fp)
    443 {
    444 	long n;
    445 	int id, nsec;
    446 	Mapsec *msec;
    447 	Section *sec;
    448 	struct coff32 *coff = obj->data;
    449 	FILHDR *hdr = &coff->hdr;
    450 	SCNHDR *scn;
    451 
    452 	nsec = hdr->f_nscns;
    453 	for (scn = coff->scns; nsec--; scn++) {
    454 		if ((id = findsec(map, scn->s_name)) < 0)
    455 			continue;
    456 		msec = &map->sec[id];
    457 		sec = &msec->sec;
    458 		if (!msec->fp)
    459 			continue;
    460 
    461 		if (copysec(msec, fp) < 0)
    462 			return -1;
    463 	}
    464 
    465 	return 1;
    466 }
    467 
    468 int
    469 coff32write(Obj *obj, Map *map, FILE *fp)
    470 {
    471 	int id;
    472 	long ptr, n;
    473 	SCNHDR *scn;
    474 	Mapsec *sec;
    475 	struct strtbl tbl;
    476 	struct coff32 *coff = obj->data;
    477 	FILHDR *hdr = &coff->hdr;
    478 
    479 	ptr = ftell(fp);
    480 	obj->pos = ptr;
    481 	tbl.s = NULL;
    482 	tbl.siz = 0;
    483 
    484 	n = hdr->f_nscns;
    485 	ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ;
    486 	for (scn = coff->scns; n--; scn++) {
    487 		scn->s_scnptr = 0;
    488 		if ((id = findsec(map, scn->s_name)) < 0)
    489 			continue;
    490 		sec = &map->sec[id];
    491 		if (!sec->fp)
    492 			continue;
    493 
    494 		scn->s_scnptr = ptr;
    495 		ptr += scn->s_size;
    496 	}
    497 	hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0;
    498 
    499 	n = hdr->f_nscns;
    500 	for (scn = coff->scns; n--; scn++) {
    501 		scn->s_relptr = (scn->s_nrelloc > 0) ? ptr : 0;
    502 		ptr += scn->s_nrelloc * RELSZ;
    503 	}
    504 
    505 	n = hdr->f_nscns;
    506 	for (scn = coff->scns; n--; scn++) {
    507 		scn->s_lnnoptr = (scn->s_nlnno > 0) ? ptr : 0;
    508 		ptr += scn->s_nlnno * RELSZ;
    509 	}
    510 
    511 	/* and now update symbols */
    512 
    513 	if (!writehdr(obj, fp))
    514 		goto err;
    515 	if (!writeaout(obj, fp))
    516 		goto err;
    517 	if (!writescns(obj, fp, &tbl))
    518 		goto err;
    519 	if (!writedata(obj, map, fp))
    520 		goto err;
    521 	if (!writereloc(obj, fp))
    522 		goto err;
    523 	if (!writelines(obj, fp))
    524 		goto err;
    525 	if (!writeents(obj, fp, &tbl))
    526 		goto err;
    527 	if (!writestr(obj, fp, &tbl))
    528 		goto err;
    529 	if (ferror(fp))
    530 		goto err;
    531 	return 0;
    532 
    533 err:
    534 	free(tbl.s);
    535 	return -1;
    536 }