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;
+}