shithub: scc

Download patch

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