commit 6c2a74664485bac7db77609a1777c9c8143fd54f
parent a3cd0a32f3a32fc590f9ba2e87e018e044f13664
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 30 Aug 2019 11:24:40 +0100
[libmach] Add loadmap()
This function creates a map with all the information needed to
map a section to a specific file and offset.
Diffstat:
15 files changed, 176 insertions(+), 46 deletions(-)
diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h
@@ -3,6 +3,7 @@ typedef struct section Section;
 typedef struct symbol Symbol;
 typedef struct objops Objops;
 typedef struct obj Obj;
+typedef struct map Map;
 
 enum sectype {
 	SREAD   = 1 << 0,
@@ -61,12 +62,15 @@ extern Obj *newobj(int type);
 extern void delobj(Obj *obj);
 
 extern int readobj(Obj *obj, FILE *fp);
-extern int writeobj(Obj *obj, FILE *fp);
+extern int writeobj(Obj *obj, Map *map, FILE *fp);
 
 extern int strip(Obj *obj);
 extern int pc2line(Obj *obj, unsigned long long pc, char *fname, int *ln);
 extern int rebase(Obj *obj, int index, unsigned long long offset);
-extern int mapsec(Obj *obj, int idx, FILE *fp);
+
+extern Map *loadmap(Obj *obj, FILE *fp);
+extern Map *newmap(int n, FILE *fp);
+extern int setmap(Map *map, char *name, long off);
 
 extern Symbol *getsym(Obj *obj, int *index, Symbol *sym);
 extern Section *getsec(Obj *obj, int *index, Section *sec);
diff --git a/src/cmd/ld/section.c b/src/cmd/ld/section.c
@@ -12,6 +12,10 @@
 
 #define NR_SECTION 32
 
+/*
+ * struct sectab has a Section as first field because
+ * the code is going to cast from the sections to the tab.
+ */
 struct sectab {
 	Section sec;
 	FILE *tmpfp;
@@ -88,10 +92,12 @@ copy(Obj *obj, Section *osec, Section *sec)
 		exit(EXIT_FAILURE);
 	}
 
+/*
 	if (mapsec(obj, osec->index, sp->tmpfp) < 0) {
 		error(strerror(errno));
 		return;
 	}
+*/
 
 	sec->size += osec->size;
 }
diff --git a/src/cmd/ld/symbol.c b/src/cmd/ld/symbol.c
@@ -12,9 +12,8 @@
 #define NR_SYMBOL 128
 
 /*
- * struct symtab and struct sectab have a Symbol and a
- * Section as first field because the code is going to
- * cast from the symbols and the sections to the tab.
+ * struct symtab has a Symbol as first field because
+ * the code is going to cast from the symbols to the tab.
  */
 struct symtab {
 	Symbol sym;
diff --git a/src/cmd/strip.c b/src/cmd/strip.c
@@ -29,51 +29,57 @@ error(char *fmt, ...)
 static void
 doit(char *fname)
 {
-	int type;
+	int type;;
 	size_t r;
-	FILE *fp;
+	FILE *src, *dst;
+	Map *map;
 	Obj *obj;
 
+	errno = 0;
 	filename = fname;
-	if ((fp = fopen(fname, "rb")) == NULL)
+	r = snprintf(tmpname, sizeof(tmpname), "%s.tmp", fname);
+	if (r >= sizeof(tmpname)) {
+		error("%s: name too long", fname);
+		return;
+	}
+	if ((src = fopen(fname, "rb")) == NULL)
+		goto err0;
+	if ((type = objtype(src, NULL)) < 0)
 		goto err1;
-	if ((type = objtype(fp, NULL)) < 0)
-		goto err2;
 	if ((obj = newobj(type)) == NULL)
+		goto err1;
+	if (readobj(obj, src) < 0)
 		goto err2;
-	if (readobj(obj, fp) < 0)
+	if ((map = loadmap(obj, src)) == NULL)
 		goto err3;
-	fclose(fp);
-
 	if (strip(obj) < 0)
-		goto err2;
-
-	r = snprintf(tmpname, sizeof(tmpname), "%s.tmp", fname);
-	if (r >= sizeof(tmpname)) {
-		errno = ERANGE;
-		goto err2;
-	}
-
-	if ((fp = fopen(tmpname, "wb")) == NULL)
-		goto err2;
-
-	if (writeobj(obj, fp) < 0)
 		goto err3;
-	fclose(fp);
-	delobj(obj);
-
+	if ((dst = fopen(tmpname, "wb")) == NULL)
+		goto err3;
+	if (writeobj(obj, map, dst) < 0)
+		goto err5;
+	if (fclose(dst) == EOF)
+		goto err4;
+	if (remove(fname) == EOF)
+		goto err4;
 	if (rename(tmpname, fname) == EOF)
-		goto err1;
+		goto err4;
 
-	return;
+	goto err3;
 
+err5:
+	fclose(dst);
+err4:
+	remove(tmpname);
 err3:
-	fclose(fp);
+	free(map);
 err2:
 	delobj(obj);
 err1:
-	error(strerror(errno));
-	remove(tmpname);
+	fclose(src);
+err0:
+	if (errno)
+		error(strerror(errno));
 }
 
 static void
diff --git a/src/libmach/Makefile b/src/libmach/Makefile
@@ -17,7 +17,9 @@ OBJS =\
 	getsym.o\
 	getsec.o\
 	rebase.o\
-	mapsec.o\
+	loadmap.o\
+	newmap.o\
+	setmap.o\
 	strip.o\
 	pc2line.o\
 	pack.o\
diff --git a/src/libmach/coff32/Makefile b/src/libmach/coff32/Makefile
@@ -18,6 +18,7 @@ OBJS = coff32.o \
        coff32pc2line.o \
        coff32getsym.o \
        coff32getsec.o \
+	coff32loadmap.o\
 
 all: $(OBJS)
 
diff --git a/src/libmach/coff32/coff32.c b/src/libmach/coff32/coff32.c
@@ -17,4 +17,5 @@ struct objops coff32 = {
 	.write = coff32write,
 	.getsym = coff32getsym,
 	.getsec = coff32getsec,
+	.loadmap = coff32loadmap,
 };
diff --git a/src/libmach/coff32/coff32.h b/src/libmach/coff32/coff32.h
@@ -41,3 +41,4 @@ extern int coff32xgetidx(int order,
 
 extern Symbol *coff32getsym(Obj *obj, int *idx, Symbol *sym);
 extern Section *coff32getsec(Obj *obj, int *idx, Section *sec);
+extern Map *coff32loadmap(Obj *obj, FILE *fp);
diff --git a/src/libmach/coff32/coff32loadmap.c b/src/libmach/coff32/coff32loadmap.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+Map *
+coff32loadmap(Obj *obj, FILE *fp)
+{
+	long i;
+	Map *map;
+	SCNHDR *scn;
+	struct coff32 *coff = obj->data;
+	FILHDR *hdr = &coff->hdr;
+	long nsec = hdr->f_nscns;
+
+	if ((map = newmap(nsec, fp)) == NULL)
+		return NULL;
+
+	for (scn = coff->scns; nsec--; ++scn)
+		setmap(map, scn->s_name, obj->pos + scn->s_scnptr);
+
+	return map;
+}
diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h
@@ -36,6 +36,8 @@ struct objops {
 	int (*strip)(Obj *obj);
 	int (*pc2line)(Obj *, unsigned long long , char *, int *);
 
+	Map *(*loadmap)(Obj *obj, FILE *fp);
+
 	Symbol *(*getsym)(Obj *obj, int *index, Symbol *sym);
 	Section *(*getsec)(Obj *obj, int *index, Section *sec);
 
@@ -43,6 +45,16 @@ struct objops {
 	int (*getidx)(long *nsyms, char ***names, long **offset, FILE *fp);
 };
 
+
+struct map {
+	int n;
+	struct mapsec {
+		char *name;
+		FILE *fp;
+		long offset;
+	} sec[];
+};
+
 /* common functions */
 extern int pack(int order, unsigned char *dst, char *fmt, ...);
 extern int unpack(int order, unsigned char *src, char *fmt, ...);
diff --git a/src/libmach/loadmap.c b/src/libmach/loadmap.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+Map *
+loadmap(Obj *obj, FILE *fp)
+{
+	return (*obj->ops->loadmap)(obj, fp);
+}
diff --git a/src/libmach/mapsec.c b/src/libmach/mapsec.c
@@ -1,11 +0,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-int
-mapsec(Obj *obj, int idx, FILE *fp)
-{
-	return 0;
-}
diff --git a/src/libmach/newmap.c b/src/libmach/newmap.c
@@ -0,0 +1,39 @@
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+Map *
+newmap(int n, FILE *fp)
+{
+	size_t siz, vsiz;
+	struct mapsec *p;
+	Map *map;
+
+	siz = sizeof(*map);
+	if (n > SIZE_MAX/sizeof(struct mapsec))
+		goto out_range;
+
+	vsiz = n * sizeof(struct mapsec);
+	if (vsiz > SIZE_MAX - siz)
+		goto out_range;
+
+	if ((map = malloc(siz + vsiz)) == NULL)
+		return NULL;
+
+	map->n = n;
+	memset(map->sec, 0, vsiz);
+
+	for (p = map->sec; n--; ++p)
+		p->fp = fp;
+	return map;
+
+out_range:
+		errno = ERANGE;
+		return NULL;
+}
diff --git a/src/libmach/setmap.c b/src/libmach/setmap.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+int
+setmap(Map *map, char *name, long off)
+{
+	int n;
+	struct mapsec *sec;
+
+	n = map->n;
+	for (sec = map->sec; n--; sec++) {
+		if (sec->name && strcmp(sec->name, name) == 0)
+			goto found;
+	}
+
+	n = map->n;
+	for (sec = map->sec; n--; sec++) {
+		if (!sec->name)
+			goto found;
+	}
+
+	/* TODO: Set some errno here */
+	return -1;
+
+found:
+	sec->name = name;
+	sec->offset = off;
+	return 0;
+}
+\ No newline at end of file
diff --git a/src/libmach/writeobj.c b/src/libmach/writeobj.c
@@ -5,7 +5,7 @@
 #include "libmach.h"
 
 int
-writeobj(Obj *obj, FILE *fp)
+writeobj(Obj *obj, Map *map, FILE *fp)
 {
 	return (obj->ops->write)(obj, fp);
 }
 \ No newline at end of file