scc

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

coff32write.c (9448B)


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