shithub: scc

Download patch

ref: cca317cd8fc13ca96666ab889680cec67b9efd98
parent: bc9383cd3876e4e4548078caa4f3c5c32dfabf42
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Feb 10 13:27:30 EST 2019

[ld] Add support for indexed libraries

--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -63,10 +63,6 @@
                    int (*fn)(Objsect *sect, void *data),
                    void *data);
 
-extern int foridx(FILE *fp,
-                  int (*fn)(Objsymdef *def, void *data),
-                  void *data);
-
 extern int archive(FILE *fp);
 extern long armember(FILE *fp, char *member);
 extern int objtype(FILE *fp, char **name);
@@ -76,8 +72,9 @@
 extern int objread(Obj *obj, FILE *fp);
 extern Objsym *objlookup(Obj *obj, char *name, int install);
 extern int objstrip(Obj *obj);
-extern long arindex(int type, long nsyms, Objsymdef *def, FILE *fp);
 extern int objwrite(Obj *obj, FILE *fp);
+extern long setindex(int type, long nsyms, Objsymdef *def, FILE *fp);
+extern long getindex(int type, long *nsyms, Objsymdef **def, FILE *fp);
 
 /* TODO */
 extern int objload(Obj *obj, Obj *to);
--- a/src/cmd/ld/main.c
+++ b/src/cmd/ld/main.c
@@ -19,6 +19,11 @@
 typedef struct symbol Symbol;
 
 enum {
+	NOINSTALL,
+	INSTALL,
+};
+
+enum {
 	OUTLIB,
 	INLIB,
 };
@@ -31,7 +36,7 @@
 struct symbol {
 	char *name;
 	Obj *obj;
-	Objsym *sym;
+	Objsym *def;
 	struct symbol *next, *prev;
 	struct symbol *hash;
 };
@@ -38,6 +43,7 @@
 
 char *output = "a.out", *entry = "start", *datasiz;
 
+static int bintype = -1;
 static char *filename, *membname;
 static Objlst *objhead, *objlast;
 static Symbol *symtab[NR_SYMBOL];
@@ -85,12 +91,12 @@
 }
 
 static Symbol *
-lookup(Objsym *osym)
+lookup(char *name, int install)
 {
+	size_t len;
 	char *s;
 	unsigned h;
 	Symbol *sym;
-	char *name = osym->name;
 
 	h = 0;
 	for (s = name; *s; s++)
@@ -102,13 +108,19 @@
 			return sym;
 	}
 
-	if ((sym = malloc(sizeof(*sym))) == NULL) {
+	if (!install)
+		return NULL;
+
+	len = strlen(name) + 1;
+	sym = malloc(sizeof(*sym));
+	s = malloc(len);
+	if (!len || !s) {
 		error("out of memory");
 		exit(EXIT_FAILURE);
 	}
 
 	sym->obj = NULL;
-	sym->name = osym->name;
+	sym->name = memcpy(s, name, len);
 	sym->hash = symtab[h];
 	symtab[h] = sym;
 
@@ -123,7 +135,7 @@
 static Symbol *
 define(Objsym *osym, Obj *obj)
 {
-	Symbol *sym = lookup(osym);
+	Symbol *sym = lookup(osym->name, INSTALL);
 
 	if (sym->obj) {
 		error("%s: symbol redefined", osym->name);
@@ -131,7 +143,7 @@
 	}
 
 	sym->obj = obj;
-	sym->sym = osym;
+	sym->def = osym;
 
 	sym->next->prev = sym->prev;
 	sym->prev->next = sym->next;
@@ -145,7 +157,7 @@
 {
 	switch (osym->type) {
 	case 'U':
-		lookup(osym);
+		lookup(osym->name, INSTALL);
 	case '?':
 	case 'N':
 		break;
@@ -159,7 +171,7 @@
 }
 
 static void
-load(Obj *obj)
+loadobj(Obj *obj)
 {
 	Objlst *lst;
 
@@ -204,7 +216,7 @@
 		if (sym == p)
 			goto  delete;
 	}
-	load(obj);
+	loadobj(obj);
 
 	return;
 
@@ -213,58 +225,96 @@
 	return;
 }
 
-static int
-newmember(FILE *fp, char *name, void *data)
+static void
+loadlib(FILE *fp)
 {
 	int t;
+	long n;
+	Objsymdef *def, *dp;
+	Symbol *sym, *p;
 
-	membname = data;
+	if (getindex(bintype, &n, &def, fp) < 0) {
+		error("corrupted index");
+		return;
+	}
 
-	if ((t = objtype(fp, NULL)) == -1)
-		return 1;
-	newobject(fp, t, INLIB);
+repeat:
+	p = &refhead;
+	if (p->next == p)
+		goto clean;
 
-	return 1;
+	for (dp = def; dp; dp = dp->next) {
+		if ((sym = lookup(dp->name, NOINSTALL)) == NULL)
+			continue;
+		if (!sym->def)
+			break;
+	}
+
+	if (!dp)
+		goto clean;
+
+	if (fseek(fp, dp->offset, SEEK_SET) == EOF) {
+		error(errstr());
+		goto clean;
+	}
+
+	if ((t = objtype(fp, NULL)) == -1) {
+		error("library file corrupted");
+		goto clean;
+	}
+
+	if (t != bintype) {
+		error("incompatible library");
+		goto clean;
+	}
+
+	newobject(fp, t, OUTLIB);
+	goto repeat;
+
+clean:
+	free(def);
 }
 
 static int
-newidx(Objsymdef *def, void *data)
+newmember(FILE *fp, char *name, void *data)
 {
+	int *nmemb = data;
 	int t;
-	Symbol *sym, *p;
-	FILE *fp = data;
 
-	p = &refhead;
-	if (p->next == p)
+	membname = data;
+
+	if (bintype == -1) {
+		error("an object file is needed before any library");
 		return 0;
+	}
 
-	for (sym = p->next; sym != p; sym = sym->next) {
-		if (strcmp(sym->name, def->name))
-			continue;
+	/* TODO: This name depends of the format */
+	if (*nmemb++ == 0 && !strncmp(name, "/", SARNAM)) {
+		loadlib(fp);
+		return 0;
+	}
 
-		if (fseek(fp, def->offset, SEEK_SET) == EOF) {
-			error(errstr());
-			return 0;
-		}
+	if ((t = objtype(fp, NULL)) == -1)
+		return 1;
 
-		if ((t = objtype(fp, NULL)) == -1) {
-			error("library file corrupted");
-			return 0;
-		}
-
-		newobject(fp, t, OUTLIB);
+	if (bintype == -1) {
+		bintype = t;
+	} else if (bintype != t) {
+		error("wrong object file format");
 		return 1;
 	}
 
-	return 0;
+	newobject(fp, t, INLIB);
+
+	return 1;
 }
 
 static int
 newlibrary(FILE *fp)
 {
-	if (foridx(fp, newidx, NULL))
-		return 1;
-	return formember(fp, newmember, NULL);
+	int nmemb = 0;
+
+	return formember(fp, newmember, &nmemb);
 }
 
 static FILE *
@@ -374,24 +424,6 @@
 	*bp = path;
 }
 
-static void
-refer(char *name)
-{
-	Objsym *osym;
-
-	if ((osym = malloc(sizeof(*osym))) == NULL) {
-		fputs("ld: out of memory\n", stderr);
-		return;
-	}
-
-	osym->name = name;
-	osym->type = 'U';
-	osym->size = osym->value = 0;
-	osym->next = osym->hash = NULL;
-
-	lookup(osym);
-}
-
 int
 main(int argc, char *argv[])
 {
@@ -435,7 +467,7 @@
 				if (argc == 0)
 					goto usage;
 				++argv, --argc;
-				refer(*argv);
+				lookup(*argv, INSTALL);
 				break;
 			case 'o':
 				if (argc == 0)
--- a/src/cmd/ranlib.c
+++ b/src/cmd/ranlib.c
@@ -210,10 +210,9 @@
 	if (fread(&first, sizeof(first), 1, lib) != 1)
 		return 0;
 
-	if (!strncmp(first.ar_name, "/", SARNAM) ||
-	    !strncmp(first.ar_name, "__.SYMDEF", SARNAM)) {
+	/* TODO: This name depends of the format */
+	if (!strncmp(first.ar_name, "/", SARNAM))
 		fseek(lib, atol(first.ar_size), SEEK_CUR);
-	}
 
 	fwrite(ARMAG, SARMAG, 1, to);
 
@@ -220,7 +219,7 @@
         strftime(mtime, sizeof(mtime), "%s", gmtime(&prop->time));
         fprintf(to,
                 "%-16.16s%-12s%-6u%-6u%-8lo%-10ld`\n",
-                "/",
+                "/",      /* TODO: This name depends of the format */
                 mtime,
                 prop->uid,
                 prop->gid,
@@ -289,8 +288,7 @@
 	if (nolib)
 		goto error;
 
-	/* TODO: Change arindex to returns -1 */
-	siz = arindex(artype, nsymbols, head, idx);
+	siz = setindex(artype, nsymbols, head, idx);
 	if (siz <= 0)
 		goto error;
 
--- a/src/libmach/.gitignore
+++ b/src/libmach/.gitignore
@@ -6,3 +6,5 @@
 read.c
 strip.c
 write.c
+getidx.c
+setidx.c
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -6,9 +6,7 @@
 
 OBJS = addr2line.o \
        archive.o \
-       arindex.o \
        armember.o \
-       coffelf32.o \
        objdel.o \
        objlookup.o \
        objnew.o \
@@ -16,9 +14,10 @@
        objread.o \
        objreset.o \
        objstrip.o \
+       getindex.o \
+       setindex.o \
        forsym.o \
        forsect.o \
-       foridx.o \
        formember.o \
        objtype.o \
        objwrite.o \
@@ -32,11 +31,14 @@
        strip.o \
        probe.o \
        write.o \
+       getidx.o \
+       setidx.o \
 
 
 DIRS = coff32
 
-TBLS = index.c \
+TBLS = setidx.c \
+       getidx.c \
        new.c \
        read.c \
        del.c \
--- a/src/libmach/arindex.c
+++ /dev/null
@@ -1,20 +1,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-extern indexfun_t indexv[];
-
-long
-arindex(int type, long nsyms, Objsymdef *head, FILE *fp)
-{
-	int fmt;
-	indexfun_t fn;
-
-	fmt = FORMAT(type);
-	if (fmt >= NFORMATS)
-		return -1;
-	fn = indexv[fmt];
-	return (*fn)(type, nsyms, head, fp);
-}
--- a/src/libmach/coff32/Makefile
+++ b/src/libmach/coff32/Makefile
@@ -3,12 +3,15 @@
 include $(PROJECTDIR)/scripts/rules.mk
 
 OBJS = coff32del.o \
-       coff32index.o \
        coff32new.o \
        coff32probe.o \
        coff32read.o \
        coff32strip.o \
        coff32write.o \
+       coff32setindex.o \
+       coff32getindex.o \
+       coff32setidx.o \
+       coff32getidx.o \
 
 all: $(OBJS)
 
--- /dev/null
+++ b/src/libmach/coff32/coff32getidx.c
@@ -1,0 +1,11 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+int
+coff32getidx(int order, long *nsyms, Objsymdef **def, FILE *fp)
+{
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32getindex.c
@@ -1,0 +1,12 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+int
+coff32getindex(int type, long *nsyms, Objsymdef **def, FILE *fp)
+{
+	return coff32getidx(BIG_ENDIAN, nsyms, def, fp);
+}
--- a/src/libmach/coff32/coff32index.c
+++ /dev/null
@@ -1,12 +1,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-
-#include "../libmach.h"
-#include "coff32.h"
-
-long
-coff32index(int type, long nsymbols, Objsymdef *head, FILE *fp)
-{
-	return coff32idx(BIG_ENDIAN, nsymbols, head, fp);
-}
--- /dev/null
+++ b/src/libmach/coff32/coff32setidx.c
@@ -1,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+
+long
+coff32setidx(int order, long nsyms, Objsymdef *head, FILE *fp)
+{
+	long i, n;
+	size_t len;
+	Objsymdef *def;
+	unsigned char buff[4];
+
+	pack(order, buff, "l", nsyms);
+	fwrite(buff, 4, 1, fp);
+	n = 4;
+
+	for (def = head; def; def = def->next) {
+		pack(order, buff, "l", (long) def->offset);
+		fwrite(buff, 4, 1, fp);
+		n += 4;
+	}
+
+	for (def = head; def; def = def->next) {
+		len = strlen(def->name);
+		fwrite(def->name, len+1, 1, fp);
+		n += len;
+	}
+
+	return fflush(fp) == EOF ? -1 : n;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32setindex.c
@@ -1,0 +1,12 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+long
+coff32setindex(int type, long nsymbols, Objsymdef *head, FILE *fp)
+{
+	return coff32setidx(BIG_ENDIAN, nsymbols, head, fp);
+}
--- a/src/libmach/coffelf32.c
+++ /dev/null
@@ -1,33 +1,0 @@
-#include <stdio.h>
-#include <string.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-long
-coff32idx(int order, long nsyms, Objsymdef *head, FILE *fp)
-{
-	long i, n;
-	size_t len;
-	Objsymdef *def;
-	unsigned char buff[4];
-
-	pack(order, buff, "l", nsyms);
-	fwrite(buff, 4, 1, fp);
-	n = 4;
-
-	for (def = head; def; def = def->next) {
-		pack(order, buff, "l", (long) def->offset);
-		fwrite(buff, 4, 1, fp);
-		n += 4;
-	}
-
-	for (def = head; def; def = def->next) {
-		len = strlen(def->name);
-		fwrite(def->name, len+1, 1, fp);
-		n += len;
-	}
-
-	return fflush(fp) == EOF ? -1 : n;
-}
--- a/src/libmach/foridx.c
+++ /dev/null
@@ -1,11 +1,0 @@
-#include <stdio.h>
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-int
-foridx(FILE *fp, int (*fn)(Objsymdef *, void *), void *data)
-{
-	/* TODO */
-	return 0;
-}
--- /dev/null
+++ b/src/libmach/getindex.c
@@ -1,0 +1,20 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern getidxfun_t getidxv[];
+
+long
+getindex(int type, long *nsyms, Objsymdef **head, FILE *fp)
+{
+	int fmt;
+	getidxfun_t fn;
+
+	fmt = FORMAT(type);
+	if (fmt >= NFORMATS)
+		return -1;
+	fn = getidxv[fmt];
+	return (*fn)(type, nsyms, head, fp);
+}
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -28,7 +28,6 @@
 	FREESECT,
 };
 
-typedef long (*indexfun_t)(int, long, Objsymdef *, FILE *);
 typedef int (*newfun_t)(Obj *obj);
 typedef int (*readfun_t)(Obj *obj, FILE *fp);
 typedef void (*delfun_t)(Obj *new);
@@ -35,6 +34,8 @@
 typedef void (*stripfun_t)(Obj *obj);
 typedef int (*probefun_t)(unsigned char *buf, char **name);
 typedef int (*writefun_t)(Obj *obj, FILE *fp);
+typedef long (*setidxfun_t)(int, long, Objsymdef *, FILE *);
+typedef int (*getidxfun_t)(int t, long *n, Objsymdef **def, FILE *fp);
 
 /* common functions */
 extern int pack(int order, unsigned char *dst, char *fmt, ...);
@@ -42,10 +43,6 @@
 extern int objpos(Obj *obj, FILE *fp, long pos);
 extern void objfree(Obj *obj, int what);
 
-/* idx functions */
-extern long coff32idx(int order, long nsyms, Objsymdef *def, FILE *fp);
-
-
 /* coff32 functions */
 extern long coff32index(int type, long nsyms, Objsymdef *head, FILE *fp);
 extern int coff32new(Obj *obj);
@@ -54,3 +51,9 @@
 extern int coff32write(Obj *obj, FILE *fp);
 extern void coff32strip(Obj *obj);
 extern int coff32probe(unsigned char *buf, char **name);
+
+extern long coff32setindex(int type, long nsymbols, Objsymdef *head, FILE *fp);
+extern long coff32setidx(int order, long nsyms, Objsymdef *head, FILE *fp);
+
+extern int coff32getindex(int type, long *nsyms, Objsymdef **def, FILE *fp);
+extern int coff32getidx(int order, long *nsyms, Objsymdef **def, FILE *fp);
--- /dev/null
+++ b/src/libmach/setindex.c
@@ -1,0 +1,20 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern setidxfun_t setidxv[];
+
+long
+setindex(int type, long nsyms, Objsymdef *head, FILE *fp)
+{
+	int fmt;
+	setidxfun_t fn;
+
+	fmt = FORMAT(type);
+	if (fmt >= NFORMATS)
+		return -1;
+	fn = setidxv[fmt];
+	return (*fn)(type, nsyms, head, fp);
+}