ref: 6661a93cfca897396c2803b9cd028068ad7c9a84
parent: 6f1a568924aa209ad591f3c540251f00006c655e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu May 31 14:01:36 EDT 2018
[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.
--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -122,18 +122,6 @@
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 @@
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);
}
--- 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 @@
int (*unpack)(unsigned char *, char *, ...);
int align;
- int define;
struct obj *next, *prev;
};
@@ -53,7 +55,7 @@
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);
--- a/ld/main.c
+++ b/ld/main.c
@@ -223,7 +223,7 @@
if (argc == 0)
goto usage;
++argv, --argc;
- lookup(*argv);
+ lookup(*argv, INSTALL);
break;
case 'o':
if (argc == 0)
--- a/ld/obj.c
+++ b/ld/obj.c
@@ -104,7 +104,7 @@
}
Symbol *
-lookup(char *name)
+lookup(char *name, int install)
{
unsigned h;
char *s;
@@ -117,6 +117,9 @@
if (*name == *s && !strcmp(name, s))
return sym;
}
+
+ if (!install)
+ return NULL;
len = strlen(name) + 1;
sym = malloc(sizeof(*sym));