shithub: scc

Download patch

ref: b5356e984cde1e77d9cc9aa92e0b417a4f217908
parent: 06ee05139a10abc443176c37ac2de9c4993f237f
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Mar 14 17:03:03 EDT 2018

[ld/coff32] Add basic support for files

--- a/ld/Makefile
+++ b/ld/Makefile
@@ -4,7 +4,7 @@
 include $(PROJECTDIR)/rules.mk
 include $(LIBDIR)/libdep.mk
 
-OBJ = main.o formats.o coff32.o
+OBJ = main.o formats.o coff32.o obj.o
 
 all: ld
 	cp ld $(PROJECTDIR)/rootdir/bin
--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -1,6 +1,8 @@
 static char sccsid[] = "@(#) ./ld/coff32.c";
 
+#include <assert.h>
 #include <errno.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -11,12 +13,75 @@
 #include "../inc/scc.h"
 #include "ld.h"
 
-static int
+static int (*unpack)(unsigned char *, char *, ...);
+static long strtbl, symtbl, sectbl;
+
+static FILHDR *
+getfhdr(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);
+	assert(n == FILHSZ);
+	return hdr;
+}
+
+static void
 pass1(char *fname, char *member, FILE *fp)
 {
+	unsigned char buff[FILHSZ];
+	FILHDR *hdr;
+	Obj *obj;
+	long siz, pos = ftell(fp);
+	char *str;
+
+	if (fread(buff, FILHSZ, 1, fp) != 1)
+		goto bad_file;
+
+	if ((hdr = malloc(sizeof(*hdr))) == NULL)
+		goto out_of_memory;
+
+	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;
+
+	if (fseek(fp, strtbl, SEEK_SET) == EOF)
+		goto bad_file;
+
+	if (fread(buff, 4, 1, fp) != 1)
+		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)
+		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));
+	die("ld: %s: corrupted file", fname);
 }
 
-static int
+static void
 pass2(char *fname, char *member, FILE *fp)
 {
 }
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -1,6 +1,20 @@
 
+typedef struct obj Obj;
+
+struct obj {
+	char *fname;
+	void *hdr;
+	char *strtbl;
+	struct obj *next;
+};
+
+#ifdef stdin
 struct objfile {
 	int (*probe)(char *fname, char *member, FILE *fp);
-	int (*pass1)(char *fname, char *member, FILE *fp);
-	int (*pass2)(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);
--- a/ld/main.c
+++ b/ld/main.c
@@ -21,7 +21,7 @@
 	extern struct objfile *formats[];
 	struct objfile **p, *obj;
 	void *data;
-	int (*fun)(char *, char *, FILE *);
+	void (*fun)(char *, char *, FILE *);
 
 	for (p = formats; *p; ++p) {
 		obj = *p;
@@ -32,7 +32,8 @@
 		return 0;
 
 	fun = (pass == 1) ? obj->pass1 : obj->pass2;
-	return (*fun)(fname, member, fp);
+	(*fun)(fname, member, fp);
+	return 1;
 }
 
 static char *
--- /dev/null
+++ b/ld/obj.c
@@ -1,0 +1,33 @@
+static char sccsid[] = "@(#) ./ld/obj.c";
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../inc/scc.h"
+#include "ld.h"
+
+Obj *objlst;
+static Obj *tail;
+
+Obj *
+newobj(char *fname)
+{
+	Obj *obj;
+	char *s;
+	size_t len = strlen(fname);
+
+	obj = malloc(sizeof(*obj));
+	s = malloc(len+1);
+	if (!obj || !s)
+		die("ld: out of memory");
+
+	obj->fname = memcpy(s, fname, len);
+	obj->next = NULL;
+
+	if (!objlst)
+		tail = objlst = obj;
+	else
+		tail->next = obj;
+
+	return obj;
+}