shithub: scc

Download patch

ref: c31d542ae4bfebfe4d44b0b4003ae9c9dc613b51
parent: a56932d42e29b8563691512e5be88d1d1faf553b
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu May 10 16:42:38 EDT 2018

[ld/coff32] Load sections and symbols in pass1

This is other step in having a linker working for coff32.

--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -14,7 +14,6 @@
 #include "ld.h"
 
 static int (*unpack)(unsigned char *, char *, ...);
-static long strtbl, symtbl, sectbl;
 
 static FILHDR *
 getfhdr(unsigned char *buff, FILHDR *hdr)
@@ -22,59 +21,147 @@
 	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);
+	              "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;
 }
 
+static int
+readstr(Obj *obj, long off)
+{
+	unsigned char buff[4];
+	char *str;
+	size_t siz;
+
+	if (fseek(obj->fp, off, SEEK_SET) == EOF)
+		return -1;
+
+	if (fread(buff, 4, 1, obj->fp) != 1)
+		return -1;
+
+	(*unpack)(buff, "l", &siz);
+
+	if (siz > SIZE_MAX || (str = malloc(siz)) == NULL)
+		outmem();
+
+	if (fread(str, siz, 1, obj->fp) != 1)
+		return -1;
+
+	obj->strtbl = str;
+	return 0;
+}
+
+static SCNHDR *
+getscn(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);
+	assert(n == SCNHSZ);
+	return scn;
+}
+
+static int
+readsects(Obj *obj, long off)
+{
+	unsigned i;
+	unsigned char buff[SCNHSZ];
+	SCNHDR scn;
+	FILHDR *hdr;
+
+	if (fseek(obj->fp, off, SEEK_SET) == EOF)
+		return -1;
+
+	hdr = obj->filhdr;
+	for (i = 0; i < hdr->f_nscns; i++) {
+		if (fread(buff, SCNHSZ, 1, obj->fp) != 1)
+			return -1;
+		getscn(buff, &scn);
+	}
+}
+
 static void
+getsym(unsigned char *buff, SYMENT *ent)
+{
+	int n;
+
+	n = (*unpack)(buff,
+		      "'8lsscc",
+		      &ent->n_name,
+		      &ent->n_value,
+		      &ent->n_scnum,
+		      &ent->n_type,
+		      &ent->n_sclass,
+		      &ent->n_numaux);
+	assert(n == SYMESZ);
+}
+
+static int
+loadobj(Obj *obj, long off)
+{
+	unsigned i;
+	unsigned char buff[SYMESZ];
+	SYMENT sym;
+	FILHDR *hdr;
+
+	for (i = 0; i < hdr->f_nsyms; i++) {
+		if (fread(buff, SYMESZ, 1, obj->fp) != 1)
+			return -1;
+		getsym(buff, &sym);
+	}
+}
+
+static void
 pass1(char *fname, char *member, FILE *fp)
 {
 	unsigned char buff[FILHSZ];
 	FILHDR *hdr;
 	Obj *obj;
-	long siz, pos = ftell(fp);
-	char *str;
+	char *strtbl;
+	long symoff, secoff, stroff, pos;
 
+	obj = newobj(fname, member);
+	obj->fp = fp;
+
+	pos = ftell(fp);
 	if (fread(buff, FILHSZ, 1, fp) != 1)
 		goto bad_file;
 
 	if ((hdr = malloc(sizeof(*hdr))) == NULL)
-		goto out_of_memory;
+		outmem();
+	getfhdr(buff, hdr);
+	obj->filhdr = hdr;
 
-	obj = newobj(fname);
-	obj->hdr = getfhdr(buff, hdr);
-
 	/* TODO: Check overflow */
-	strtbl = pos + hdr->f_symptr + hdr->f_nsyms* SYMESZ;
-	symtbl = pos + hdr->f_symptr;
-	sectbl = pos + FILHSZ + hdr->f_opthdr;
+	stroff = pos + hdr->f_symptr + hdr->f_nsyms*SYMESZ;
+	symoff = pos + hdr->f_symptr;
+	secoff = pos + FILHSZ + hdr->f_opthdr;
 
-	if (fseek(fp, strtbl, SEEK_SET) == EOF)
+	if (readstr(obj, stroff) < 0)
 		goto bad_file;
-
-	if (fread(buff, 4, 1, fp) != 1)
+	if (loadobj(obj, symoff) < 0)
 		goto bad_file;
-
-	(*unpack)(buff, "l", &siz);
-
-	if (siz > SIZE_MAX || (str = malloc(siz)) == NULL)
-		goto out_of_memory;
-
-	if (fread(str, siz, 1, fp) != 1)
+	if (readsects(obj, secoff) < 0)
 		goto bad_file;
 
-	obj->strtbl = str;
-
-out_of_memory:
-	die("ld: out of memory");
 bad_file:
 	if (ferror(fp))
 		die("ld: %s: %s", fname, strerror(errno));
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -4,7 +4,10 @@
 
 struct obj {
 	char *fname;
-	void *hdr;
+	char *member;
+	FILE *fp;
+	void *filhdr;
+	void *sechdr;
 	char *strtbl;
 	struct obj *next;
 };
@@ -13,14 +16,15 @@
 	char *name;
 };
 
-#ifdef stdin
 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);
 };
-#endif
 
 /* obj.c */
-extern Obj *newobj(char *fname);
+extern Obj *newobj(char *fname, char *member);
 extern Symbol *lookup(char *name);
+
+/* main.c */
+extern void outmem(void);
--- a/ld/main.c
+++ b/ld/main.c
@@ -12,10 +12,16 @@
 #include "../inc/syslibs.h"
 #include "ld.h"
 
-char *argv0;
 char *output = "a.out", *entry, *datasiz;
 int pass;
 int sflag, xflag, Xflag, rflag, dflag;
+
+void
+outmem(void)
+{
+	fputs("ld: out of memory\n", stderr);
+	exit(EXIT_FAILURE);
+}
 
 static int
 object(char *fname, char *member, FILE *fp)
--- a/ld/obj.c
+++ b/ld/obj.c
@@ -1,5 +1,6 @@
 static char sccsid[] = "@(#) ./ld/obj.c";
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -10,18 +11,20 @@
 static Obj *tail;
 
 Obj *
-newobj(char *fname)
+newobj(char *fname, char *member)
 {
 	Obj *obj;
-	char *s;
-	size_t len = strlen(fname);
+	char *s, *t;
+	size_t l1 = strlen(member), l2 = strlen(fname);
 
 	obj = malloc(sizeof(*obj));
-	s = malloc(len+1);
-	if (!obj || !s)
-		die("ld: out of memory");
+	s = malloc(l1+1);
+	t = malloc(l2+1);
+	if (!obj || !s || !t)
+		outmem();
 
-	obj->fname = memcpy(s, fname, len);
+	obj->fname = memcpy(s, fname, l1);
+	obj->member = memcpy(t, member, l2);
 	obj->next = NULL;
 
 	if (!objlst)