scc

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

commit 25f3696093b4a1507117fad68010bb80dad89d79
parent 4dc9905bcd18e15446a589cdb4060b31050b5607
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 31 May 2018 18:01:36 +0100

[as/coff32] Check if a library member is needed

This patch adds the code that checks if a member of a library has
to be loaded or not.

Diffstat:
Mld/coff32.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mld/ld.h | 6++++--
Mld/main.c | 2+-
Mld/obj.c | 5++++-
4 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/ld/coff32.c b/ld/coff32.c @@ -122,18 +122,6 @@ readsects(Obj *obj, long off) if (fread(buff, SCNHSZ, 1, obj->fp) != 1) return -1; getscn(obj, buff, p); - sym = lookup(p->s_name); - - sym->size = (sym->size + a) & a; - if (sym->size > ULLONG_MAX - p->s_size) { - fprintf(stderr, - "ld: %s: overflow in section '%s'\n", - obj->fname, p->s_name); - exit(EXIT_FAILURE); - } - sym->size += p->s_size; - obj->sections[i] = sym; - newsect(sym); } return 0; @@ -259,14 +247,68 @@ bad_file: exit(EXIT_FAILURE); } +static char * +symname(Obj *obj, SYMENT *ent) +{ + long off; + + if (ent->n_zeroes != 0) + return ent->n_name; + + off = ent->n_offset; + if (off >= obj->strsiz) { + fprintf(stderr, + "ld: invalid offset in symbol table: %zd\n", off); + return ""; + } + + return &obj->strtbl[off]; +} + +static int +needed(Obj *obj) +{ + FILHDR *hdr = obj->filhdr; + SYMENT *ent, *ents = obj->enthdr; + long aux, i; + + aux = 0; + for (i = 0; i < hdr->f_nsyms; i++) { + if (aux > 0) { + aux--; + continue; + } + ent = ents + i; + if (ent->n_sclass != C_EXT) + continue; + + switch (ent->n_scnum) { + case N_DEBUG: + case N_UNDEF: + continue; + case N_ABS: + default: + if (!lookup(symname(obj, ent), NOINSTALL)) + continue; + return 1; + } + } + + return 0; +} + static void pass1(Obj *obj) { readobj(obj); - if (obj->member && !obj->define) { - delobj(obj); - return; + + if (obj->member) { + if (!needed(obj)) { + delobj(obj); + return; + } } + add(obj); } diff --git a/ld/ld.h b/ld/ld.h @@ -1,4 +1,7 @@ +#define INSTALL 1 +#define NOINSTALL 0 + typedef struct obj Obj; typedef struct symbol Symbol; typedef struct objfmt Fmt; @@ -22,7 +25,6 @@ struct obj { int (*unpack)(unsigned char *, char *, ...); int align; - int define; struct obj *next, *prev; }; @@ -53,7 +55,7 @@ extern Obj *newobj(char *fname, char *member, FILE *fp); extern void add(Obj *obj); extern void delobj(Obj *obj); extern void newsect(Symbol *sym); -extern Symbol *lookup(char *name); +extern Symbol *lookup(char *name, int install); /* main.c */ extern void outmem(void); diff --git a/ld/main.c b/ld/main.c @@ -223,7 +223,7 @@ main(int argc, char *argv[]) if (argc == 0) goto usage; ++argv, --argc; - lookup(*argv); + lookup(*argv, INSTALL); break; case 'o': if (argc == 0) diff --git a/ld/obj.c b/ld/obj.c @@ -104,7 +104,7 @@ hash(char *s) } Symbol * -lookup(char *name) +lookup(char *name, int install) { unsigned h; char *s; @@ -118,6 +118,9 @@ lookup(char *name) return sym; } + if (!install) + return NULL; + len = strlen(name) + 1; sym = malloc(sizeof(*sym)); s = malloc(len);