shithub: scc

Download patch

ref: 4c00c4e8204f98a5859ef6c0bfe8d2e4d6f168d2
parent: da1885ebccf5d31fb4a695764b96311e493bde09
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue May 29 14:17:24 EDT 2018

[ld] Redefine interface between main and object formats

We only have to create once the object file.

--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -15,23 +15,20 @@
 #include "../inc/scc.h"
 #include "ld.h"
 
-static int (*unpack)(unsigned char *, char *, ...);
-static int align;
-
 static FILHDR *
-getfhdr(unsigned char *buff, FILHDR *hdr)
+getfhdr(Obj *obj, unsigned char *buff, FILHDR *hdr)
 {
 	int n;
 
-	n = (*unpack)(buff,
-	              "sslllss",
-	              &hdr->f_magic,
-	              &hdr->f_nscns,
-	              &hdr->f_timdat,
-	              &hdr->f_symptr,
-	              &hdr->f_nsyms,
-	              &hdr->f_opthdr,
-	              &hdr->f_flags);
+	n = (*obj->unpack)(buff,
+	                   "sslllss",
+	                   &hdr->f_magic,
+	                   &hdr->f_nscns,
+	                   &hdr->f_timdat,
+	                   &hdr->f_symptr,
+	                   &hdr->f_nsyms,
+	                   &hdr->f_opthdr,
+	                   &hdr->f_flags);
 	assert(n == FILHSZ);
 	return hdr;
 }
@@ -49,7 +46,7 @@
 	if (fread(buff, 4, 1, obj->fp) != 1)
 		return -1;
 
-	(*unpack)(buff, "l", &siz);
+	(*obj->unpack)(buff, "l", &siz);
 
 	siz -= 4;
 	if (siz == 0) {
@@ -71,22 +68,22 @@
 }
 
 static SCNHDR *
-getscn(unsigned char *buff, SCNHDR *scn)
+getscn(Obj *obj, unsigned char *buff, SCNHDR *scn)
 {
 	int n;
 
-	n = (*unpack)(buff,
-	              "'8llllllssl",
-	              scn->s_name,
-	              &scn->s_paddr,
-	              &scn->s_vaddr,
-	              &scn->s_size,
-	              &scn->s_scnptr,
-	              &scn->s_relptr,
-	              &scn->s_lnnoptr,
-	              &scn->s_nrelloc,
-	              &scn->s_nlnno,
-	              &scn->s_flags);
+	n = (*obj->unpack)(buff,
+	                   "'8llllllssl",
+	                   scn->s_name,
+	                   &scn->s_paddr,
+	                   &scn->s_vaddr,
+	                   &scn->s_size,
+	                   &scn->s_scnptr,
+	                   &scn->s_relptr,
+	                   &scn->s_lnnoptr,
+	                   &scn->s_nrelloc,
+	                   &scn->s_nlnno,
+	                   &scn->s_flags);
 	assert(n == SCNHSZ);
 	return scn;
 }
@@ -94,7 +91,7 @@
 static int
 readsects(Obj *obj, long off)
 {
-	unsigned nsec, i;
+	unsigned a, nsec, i;
 	unsigned char buff[SCNHSZ];
 	SCNHDR *scn, *p;
 	FILHDR *hdr;
@@ -111,13 +108,14 @@
 	if (fseek(obj->fp, off, SEEK_SET) == EOF)
 		return -1;
 
+	a = obj->align - 1;
 	for (p = scn; p < &scn[nsec]; ++p) {
 		if (fread(buff, SCNHSZ, 1, obj->fp) != 1)
 			return -1;
-		getscn(buff, p);
+		getscn(obj, buff, p);
 		sym = lookup(p->s_name);
 
-		sym->size = (sym->size + align-1) & align-1;
+		sym->size = (sym->size + a) & a;
 		if (sym->size > ULLONG_MAX - p->s_size) {
 			fprintf(stderr,
 			        "ld: %s: overflow in section '%s'\n",
@@ -132,25 +130,25 @@
 }
 
 static void
-getsym(unsigned char *buff, SYMENT *ent)
+getsym(Obj *obj, unsigned char *buff, SYMENT *ent)
 {
 	int n;
 	long off, zero;
 	char *name;
 
-	n = (*unpack)(buff,
-		      "'8lsscc",
-		      &ent->n_name,
-		      &ent->n_value,
-		      &ent->n_scnum,
-		      &ent->n_type,
-		      &ent->n_sclass,
-		      &ent->n_numaux);
+	n = (*obj->unpack)(buff,
+		           "'8lsscc",
+		           &ent->n_name,
+		           &ent->n_value,
+		           &ent->n_scnum,
+		           &ent->n_type,
+		           &ent->n_sclass,
+		           &ent->n_numaux);
 	assert(n == SYMESZ);
 
 	name = ent->n_name;
 	if (!name[0] && !name[1] && !name[2] && !name[3])
-		(*unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset);
+		(*obj->unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset);
 }
 
 static char *
@@ -267,7 +265,7 @@
 
 		if (fread(buff, SYMESZ, 1, obj->fp) != 1)
 			return -1;
-		getsym(buff, &ent);
+		getsym(obj, buff, &ent);
 		name = symname(obj, &ent);
 		type = typeof(obj, &ent);
 		sym = lookup(name);
@@ -321,7 +319,7 @@
 
 	if ((hdr = malloc(sizeof(*hdr))) == NULL)
 		outmem();
-	getfhdr(buff, hdr);
+	getfhdr(obj, buff, hdr);
 	obj->filhdr = hdr;
 
 	/* TODO: Check overflow */
@@ -344,28 +342,19 @@
 }
 
 static void
-pass1(char *fname, char *member, FILE *fp)
+pass1(Obj *obj)
 {
-	Obj *obj;
-	SYMENT *ent;
-	FILHDR *hdr;
-	unsigned n, nsyms;
-	int islib = member != NULL;
-
-	obj = newobj(fname, member);
-	obj->fp = fp;
 	readobj(obj);
-
-	hdr = obj->filhdr;
-	nsyms = hdr->f_nsyms;
 }
 
 static void
-pass2(char *fname, char *member, FILE *fp)
+pass2(Obj *obj)
 {
 }
 
-static int
+Fmt coff32;
+
+static Obj *
 probe(char *fname, char *member, FILE *fp)
 {
 	int c;
@@ -372,6 +361,9 @@
 	int c1, c2;
 	fpos_t pos;
 	unsigned short magic;
+	unsigned align;
+	int (*unpack)(unsigned char *, char *, ...);
+	Obj *obj;
 
 	fgetpos(fp, &pos);
 	c1 = getc(fp);
@@ -389,13 +381,21 @@
 	case COFF_Z80MAGIC:
 		unpack = lunpack;
 		align = 2;
-		return 1;
+		break;
 	default:
-		return 0;
+		return NULL;
 	}
+
+	obj = newobj(fname, member);
+	obj->fp = fp;
+	obj->unpack = unpack;
+	obj->align = align;
+	obj->fmt = &coff32;
+
+	return obj;
 }
 
-struct objfile coff32 = {
+Fmt coff32 = {
 	.probe = probe,
 	.pass1 = pass1,
 	.pass2 = pass2,
--- a/ld/formats.c
+++ b/ld/formats.c
@@ -6,9 +6,9 @@
 #include "ld.h"
 
 /* TODO: Autogenerate this file */
-struct objfile coff32;
+struct objfmt coff32;
 
-struct objfile *formats[] = {
+struct objfmt *formats[] = {
 	&coff32,
 	NULL,
 };
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -1,6 +1,7 @@
 
 typedef struct obj Obj;
 typedef struct symbol Symbol;
+typedef struct objfmt Fmt;
 
 struct obj {
 	char *fname;
@@ -11,6 +12,9 @@
 	Symbol **symbols;
 	char *strtbl;
 	size_t strsiz;
+	int (*unpack)(unsigned char *, char *, ...);
+	int align;
+	Fmt *fmt;
 	struct obj *next;
 };
 
@@ -24,10 +28,10 @@
 	struct symbol *hash;
 };
 
-struct objfile {
-	int (*probe)(char *fname, char *member, FILE *fp);
-	void (*pass1)(char *fname, char *member, FILE *fp);
-	void (*pass2)(char *fname, char *member, FILE *fp);
+struct objfmt {
+	Obj  *(*probe)(char *fname, char *member, FILE *fp);
+	void (*pass1)(Obj *obj);
+	void (*pass2)(Obj *obj);
 };
 
 /* obj.c */
--- a/ld/main.c
+++ b/ld/main.c
@@ -31,21 +31,22 @@
 static int
 object(char *fname, char *member, FILE *fp)
 {
-	extern struct objfile *formats[];
-	struct objfile **p, *obj;
-	void *data;
-	void (*fun)(char *, char *, FILE *);
+	extern Fmt *formats[];
+	Fmt **p, *fmt;
+	Obj *obj;
+	void (*fun)(Obj *obj);
 
 	for (p = formats; *p; ++p) {
-		obj = *p;
-		if ((*obj->probe)(fname, member, fp))
+		fmt = *p;
+		obj = (*fmt->probe)(fname, member, fp);
+		if (obj)
 			break;
 	}
 	if (*p == NULL)
 		return 0;
 
-	fun = (pass == 1) ? obj->pass1 : obj->pass2;
-	(*fun)(fname, member, fp);
+	(*obj->fmt->pass1)(obj);
+
 	return 1;
 }
 
@@ -156,8 +157,6 @@
 pass2(int argc, char *argv[])
 {
 	pass = 2;
-	while (*argv)
-		process(*argv++);
 }
 
 static void