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:
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);