shithub: scc

Download patch

ref: 454313e5735b42a3c6d464bbb78be1dcc82a0034
parent: d31f41ad68c39eb244316ae777bcddfb98beca17
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Aug 28 10:51:43 EDT 2019

[libmach] Add getindex() and setindex()

--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -1,5 +1,6 @@
 typedef struct symbol Symbol;
 typedef struct section Section;
+typedef struct objops Objops;
 typedef struct obj Obj;
 
 enum sectype {
@@ -13,6 +14,14 @@
 	SSHARED = 1 << 7,
 };
 
+struct obj {
+	char *index;
+	Objops *ops;
+	int type;
+	long pos;
+	void *data;
+};
+
 struct section {
 	char *name;
 	unsigned long long base;
@@ -46,3 +55,6 @@
 
 extern Symbol *getsym(Obj *obj, long *index, Symbol *sym);
 extern Section *getsec(Obj *obj, long *index, Section *sec);
+
+extern int setindex(int, long, char **, long *, FILE *);
+extern int getindex(int, long *, char ***, long **, FILE *);
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -7,8 +7,8 @@
          $(BINDIR)/ar \
          $(BINDIR)/strip \
          $(BINDIR)/size \
+         $(BINDIR)/ranlib \
 
-#         $(BINDIR)/ranlib \
 #         $(BINDIR)/objdump \
 #         $(BINDIR)/objcopy \
 #         $(BINDIR)/addr2line \
--- a/src/cmd/ranlib.c
+++ b/src/cmd/ranlib.c
@@ -28,18 +28,11 @@
 static char *namidx;
 static long nsymbols;
 static int status, artype, nolib;
-static Objops *ops;
 static char *filename, *membname;
 static Symdef *htab[NR_SYMDEF], *head;
 static long offset;
 char *argv0;
 
-static char *
-errstr(void)
-{
-	return strerror(errno);
-}
-
 static void
 error(char *fmt, ...)
 {
@@ -94,7 +87,7 @@
 }
 
 static int
-newsymbol(Objsym *sym)
+newsymbol(Symbol *sym)
 {
 	Symdef *np;
 
@@ -102,7 +95,7 @@
 		return 1;
 
 	if ((np = lookup(sym->name)) == NULL) {
-		error("out of memory");
+		error(strerror(errno));
 		return 0;
 	}
 
@@ -142,17 +135,17 @@
 }
 
 static int
-newmember(FILE *fp, char *nam)
+newmember(FILE *fp)
 {
 	int t, ret = 0;
+	long i;
 	Obj *obj;
-	Objsym *sym;
+	Symbol sym;
 
-	membname = nam;
 	offset = ftell(fp);
 
 	if (offset == EOF) {
-		error(errstr());
+		error(strerror(errno));
 		return 0;
 	}
 
@@ -163,20 +156,19 @@
 	}
 	artype = t;
 
-	if ((obj = objnew(t)) == NULL) {
-		error("out of memory");
+	if ((obj = newobj(t)) == NULL) {
+		error(strerror(errno));
 		return 0;
 	}
-	ops = obj->ops;
 	namidx = obj->index;
 
-	if ((*ops->read)(obj, fp) < 0) {
-		error("file corrupted");
+	if (readobj(obj, fp) < 0) {
+		error(strerror(errno));
 		goto error;
 	}
 
-	for (sym = obj->syms; sym; sym = sym->next) {
-		if (!newsymbol(sym))
+	for (i = 0; getsym(obj, &i, &sym); i++) {
+		if (!newsymbol(&sym))
 			goto error;
 	}
 
@@ -183,7 +175,7 @@
 	ret = 1;
 
 error:
-	(ops->del)(obj);
+	delobj(obj);
 	return ret;
 }
 
@@ -190,36 +182,52 @@
 static int
 readsyms(FILE *fp)
 {
-	long r, off;
+	long cur, off;
 	char memb[SARNAM+1];
 
+	nolib = 0;
+	artype = -1;
+	nsymbols = 0;
+
 	if (!archive(fp)) {
 		error("file format not recognized");
 		return 0;
 	}
 
+	cur = ftell(fp);
 	if ((off = armember(fp, memb)) < 0)
 		goto corrupted;
 
-	if (strcmp(memb, "/") != 0 && strcmp(memb, "__.SYMDEF") != 0) {
-		if (fseek(fp, -off, SEEK_CUR) == EOF) {
-			error(errstr());
-			return 0;
+	if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0)
+		cur = ftell(fp) + off;
+
+	fseek(fp, SEEK_SET, cur);
+	for (;;) {
+		cur = ftell(fp);
+		off = armember(fp, memb);
+		switch (off) {
+		case -1:
+			goto corrupted;
+		case 0:
+			return (nolib || nsymbols == 0) ? -1 : 0;
+		default:
+			membname = memb;
+			if (objtype(fp, NULL) != -1)
+				newmember(fp);
+			membname = NULL;
+			fseek(fp, cur, SEEK_SET);
+			fseek(fp, off, SEEK_CUR);
+			break;
 		}
 	}
 
-	while ((r = armember(fp, memb)) > 0)
-		newmember(fp, memb);
-	if (r < 0)
-		goto corrupted;
-	return 1;
-
 corrupted:
-	error("corrupted ar file");
+	error(strerror(errno));
+	error("library corrupted");
 	return 0;
 }
 
-static int
+static void
 merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx)
 {
 	int c;
@@ -231,7 +239,7 @@
 	fseek(lib, SARMAG, SEEK_SET);
 
 	if (fread(&first, sizeof(first), 1, lib) != 1)
-		return 0;
+		return;
 
 	if (!strncmp(first.ar_name, namidx, SARNAM))
 		fseek(lib, atol(first.ar_size), SEEK_CUR);
@@ -259,67 +267,39 @@
 		putc(c, to);
 
 	fflush(to);
-
-	if (ferror(to) || ferror(lib) || ferror(idx))
-		return 0;
-
-	return 1;
 }
 
-static int
-copy(FILE *from, char *fname)
-{
-	int c, ret;
-	FILE *fp;
-
-	if ((fp = fopen(fname, "wb")) == NULL)
-		return 0;
-
-	rewind(from);
-	while ((c = getc(from)) != EOF)
-		putc(c, fp);
-	fflush(fp);
-
-	ret = !ferror(fp) && !ferror(from);
-
-	fclose(fp);
-
-	return ret;
-}
-
-
 static void
 ranlib(char *fname)
 {
+	size_t r;
 	long *offs, i;
 	char **names;
 	FILE *fp, *idx, *out;
 	Symdef *dp;
 	struct fprop prop;
+	char tmpname[FILENAME_MAX];
 
-	errno = 0;
-	nolib = 0;
-	artype = -1;
-	nsymbols = 0;
-	offs = NULL;
-	names = NULL;
 	filename = fname;
-	freehash();
+	if ((fp = fopen(fname, "rb")) == NULL) {
+		error(strerror(errno));
+		return;
+	}
 
-	fp = fopen(fname, "rb");
-	idx = tmpfile();
-	out = tmpfile();
-	if (!fp || !idx || !out)
-		goto error;
+	if (readsyms(fp) <0)
+		goto err2;
 
-	if (!readsyms(fp))
-		goto error;
+	if ((idx = tmpfile()) == NULL) {
+		error(strerror(errno));
+		goto err2;
+	}
 
-	if (nolib || nsymbols == 0)
-		goto error;
-
 	offs = malloc(sizeof(long) * nsymbols);
 	names = malloc(sizeof(*names) * nsymbols);
+	if (!offs || !names) {
+		error(strerror(errno));
+		goto err3;
+	}
 
 	for (dp = head, i = 0; i < nsymbols; dp = dp->next, i++) {
 		offs[i] = dp->offset;
@@ -326,44 +306,52 @@
 		names[i] = dp->name;
 	}
 
-	if ((*ops->setidx)(nsymbols, names, offs, idx) < 0)
-		goto error;
+	if (setindex(artype, nsymbols, names, offs, idx) < 0) {
+		error(strerror(errno));
+		goto err3;
+	}
 
-	if (getstat(fname, &prop) < 0)
-		goto error;
+	if (getstat(fname, &prop) < 0) {
+		error(strerror(errno));
+		goto err3;
+	}
 	prop.size = ftell(idx);
 	prop.time = time(NULL);
 
-	if (!merge(out, &prop, fp, idx))
-		goto error;
+	r = snprintf(tmpname, sizeof(tmpname), "%s.tmp", fname);
+	if (r >= sizeof(tmpname)) {
+		error("too long temporary name");
+		goto err3;
+	}
 
-	free(offs);
-	free(names);
-	fclose(fp);
-	fclose(idx);
-	offs = NULL;
-	names = NULL;
-	fp = idx = NULL;
+	if ((out = fopen(tmpname, "wb")) == NULL) {
+		error(strerror(errno));
+		goto err3;
+	}
 
-	if (!copy(out, fname))
-		goto error;
+	merge(out, &prop, fp, idx);
+	if (ferror(out) || ferror(fp) || ferror(idx)) {
+		error(strerror(errno));
+		fclose(out);
+		goto err4;
+	}
+
 	fclose(out);
+	if (rename(tmpname, fname) == EOF) {
+		error(strerror(errno));
+		goto err4;
+	}
 
-	return;
-
-error:
-	if (offs)
-		free(offs);
-	if (names)
-		free(names);
-	if (errno)
-		error(errstr());
-	if (idx)
-		fclose(idx);
-	if (out)
-		fclose(out);
-	if (fp)
-		fclose(fp);
+err4:
+	remove(tmpname);
+err3:
+	free(offs);
+	free(names);
+	fclose(idx);
+err2:
+	freehash();
+err1:
+	fclose(fp);
 }
 
 static void
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -18,6 +18,8 @@
        strip.o \
        pack.o \
        unpack.o \
+       setindex.o \
+       getindex.o \
 
 DIRS = coff32
 
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -4,7 +4,6 @@
 #define ARCH(t) (((t) >> 5) & 0x1f)
 #define ORDER(t) (((t) >> 10) & 0x1f)
 
-typedef struct objops Objops;
 
 enum objformat {
 	COFF32,
@@ -42,14 +41,6 @@
 
 	int (*setidx)(long nsyms, char *names[], long offset[], FILE *fp);
 	int (*getidx)(long *nsyms, char ***names, long **offset, FILE *fp);
-};
-
-struct obj {
-	char *index;
-	struct objops *ops;
-	int type;
-	long pos;
-	void *data;
 };
 
 /* common functions */