scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 1b0d7ac17e996392d061fe4ae076094ccf569325
parent 25af93ba2433dadba394ac2f30640fccb37a81e5
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 10 Feb 2019 18:27:30 +0000

[ld] Add support for indexed libraries

Diffstat:
Minclude/scc/scc/mach.h | 7++-----
Msrc/cmd/ld/main.c | 148++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/cmd/ranlib.c | 10++++------
Msrc/libmach/.gitignore | 2++
Msrc/libmach/Makefile | 10++++++----
Dsrc/libmach/arindex.c | 20--------------------
Msrc/libmach/coff32/Makefile | 5++++-
Asrc/libmach/coff32/coff32getidx.c | 11+++++++++++
Asrc/libmach/coff32/coff32getindex.c | 12++++++++++++
Dsrc/libmach/coff32/coff32index.c | 12------------
Asrc/libmach/coff32/coff32setidx.c | 33+++++++++++++++++++++++++++++++++
Asrc/libmach/coff32/coff32setindex.c | 12++++++++++++
Dsrc/libmach/coffelf32.c | 33---------------------------------
Dsrc/libmach/foridx.c | 11-----------
Asrc/libmach/getindex.c | 20++++++++++++++++++++
Msrc/libmach/libmach.h | 13++++++++-----
Asrc/libmach/setindex.c | 20++++++++++++++++++++
17 files changed, 224 insertions(+), 155 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -63,10 +63,6 @@ extern int forsect(Obj *obj, 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 objreset(Obj *obj); 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); diff --git a/src/cmd/ld/main.c b/src/cmd/ld/main.c @@ -19,6 +19,11 @@ typedef struct objlst Objlst; typedef struct symbol Symbol; enum { + NOINSTALL, + INSTALL, +}; + +enum { OUTLIB, INLIB, }; @@ -31,13 +36,14 @@ struct objlst { struct symbol { char *name; Obj *obj; - Objsym *sym; + Objsym *def; struct symbol *next, *prev; struct symbol *hash; }; 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 @@ cleanup(void) } 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 @@ lookup(Objsym *osym) 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 @@ lookup(Objsym *osym) 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 @@ define(Objsym *osym, Obj *obj) } sym->obj = obj; - sym->sym = osym; + sym->def = osym; sym->next->prev = sym->prev; sym->prev->next = sym->next; @@ -145,7 +157,7 @@ newsym(Objsym *osym, void *obj) { switch (osym->type) { case 'U': - lookup(osym); + lookup(osym->name, INSTALL); case '?': case 'N': break; @@ -159,7 +171,7 @@ newsym(Objsym *osym, void *obj) } static void -load(Obj *obj) +loadobj(Obj *obj) { Objlst *lst; @@ -204,7 +216,7 @@ newobject(FILE *fp, int type, int inlib) if (sym == p) goto delete; } - load(obj); + loadobj(obj); return; @@ -213,58 +225,96 @@ delete: 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) - return 0; + membname = data; - for (sym = p->next; sym != p; sym = sym->next) { - if (strcmp(sym->name, def->name)) - continue; + if (bintype == -1) { + error("an object file is needed before any library"); + return 0; + } - if (fseek(fp, def->offset, SEEK_SET) == EOF) { - error(errstr()); - return 0; - } + /* TODO: This name depends of the format */ + if (*nmemb++ == 0 && !strncmp(name, "/", SARNAM)) { + loadlib(fp); + return 0; + } - if ((t = objtype(fp, NULL)) == -1) { - error("library file corrupted"); - return 0; - } + if ((t = objtype(fp, NULL)) == -1) + return 1; - 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 @@ Lpath(char *path) *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 @@ main(int argc, char *argv[]) if (argc == 0) goto usage; ++argv, --argc; - refer(*argv); + lookup(*argv, INSTALL); break; case 'o': if (argc == 0) diff --git a/src/cmd/ranlib.c b/src/cmd/ranlib.c @@ -210,17 +210,16 @@ merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx) 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); 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 @@ ranlib(char *fname) 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; diff --git a/src/libmach/.gitignore b/src/libmach/.gitignore @@ -6,3 +6,5 @@ probe.c read.c strip.c write.c +getidx.c +setidx.c diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -6,9 +6,7 @@ TARGET = $(LIBDIR)/libmach.a OBJS = addr2line.o \ archive.o \ - arindex.o \ armember.o \ - coffelf32.o \ objdel.o \ objlookup.o \ objnew.o \ @@ -16,9 +14,10 @@ OBJS = addr2line.o \ 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 @@ OBJS = addr2line.o \ 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 \ diff --git a/src/libmach/arindex.c b/src/libmach/arindex.c @@ -1,20 +0,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); -} diff --git a/src/libmach/coff32/Makefile b/src/libmach/coff32/Makefile @@ -3,12 +3,15 @@ PROJECTDIR =../../.. 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) diff --git a/src/libmach/coff32/coff32getidx.c b/src/libmach/coff32/coff32getidx.c @@ -0,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) +{ +} diff --git a/src/libmach/coff32/coff32getindex.c b/src/libmach/coff32/coff32getindex.c @@ -0,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); +} diff --git a/src/libmach/coff32/coff32index.c b/src/libmach/coff32/coff32index.c @@ -1,12 +0,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); -} diff --git a/src/libmach/coff32/coff32setidx.c b/src/libmach/coff32/coff32setidx.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32setindex.c b/src/libmach/coff32/coff32setindex.c @@ -0,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); +} diff --git a/src/libmach/coffelf32.c b/src/libmach/coffelf32.c @@ -1,33 +0,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; -} diff --git a/src/libmach/foridx.c b/src/libmach/foridx.c @@ -1,11 +0,0 @@ -#include <stdio.h> -#include <scc/mach.h> - -#include "libmach.h" - -int -foridx(FILE *fp, int (*fn)(Objsymdef *, void *), void *data) -{ - /* TODO */ - return 0; -} diff --git a/src/libmach/getindex.c b/src/libmach/getindex.c @@ -0,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); +} diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -28,13 +28,14 @@ enum freeflags { 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); 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 unpack(int order, unsigned char *src, char *fmt, ...); 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 coff32read(Obj *obj, FILE *fp); 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); diff --git a/src/libmach/setindex.c b/src/libmach/setindex.c @@ -0,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); +}