scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 14struct strtbl {
 15	char *s;
 16	long siz;
 17};
 18
 19static void
 20pack_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
 37static void
 38pack_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
 63static void
 64pack_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
 86static void
 87pack_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
 98static void
 99pack_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
115static void
116pack_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
131static void
132pack_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
150static void
151pack_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
167static void
168pack_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
186static void
187pack_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
200static void
201pack_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
213static int
214writehdr(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
230static int
231allocstring(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
253static int
254writescns(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
279static int
280writeents(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
339static int
340writestr(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
363static int
364writeaout(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
380static int
381writereloc(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
412static int
413writelines(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
441static int
442writedata(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
468int
469coff32write(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
533err:
534	free(tbl.s);
535	return -1;
536}