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