shithub: scc

Download patch

ref: 2d1b151c900071e5362b23e2e673c3cc0221c166
parent: 26e92fcaa069bac388b1d0571e14957e012fdc4d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Aug 30 07:24:40 EDT 2019

[libmach] Add loadmap()

This function creates a map with all the information needed to
map a section to a specific file and offset.

--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -3,6 +3,7 @@
 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 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);
--- 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 @@
 		exit(EXIT_FAILURE);
 	}
 
+/*
 	if (mapsec(obj, osec->index, sp->tmpfp) < 0) {
 		error(strerror(errno));
 		return;
 	}
+*/
 
 	sec->size += osec->size;
 }
--- 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;
--- a/src/cmd/strip.c
+++ b/src/cmd/strip.c
@@ -29,51 +29,57 @@
 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
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -17,7 +17,9 @@
 	getsym.o\
 	getsec.o\
 	rebase.o\
-	mapsec.o\
+	loadmap.o\
+	newmap.o\
+	setmap.o\
 	strip.o\
 	pc2line.o\
 	pack.o\
--- a/src/libmach/coff32/Makefile
+++ b/src/libmach/coff32/Makefile
@@ -18,6 +18,7 @@
        coff32pc2line.o \
        coff32getsym.o \
        coff32getsec.o \
+	coff32loadmap.o\
 
 all: $(OBJS)
 
--- a/src/libmach/coff32/coff32.c
+++ b/src/libmach/coff32/coff32.c
@@ -17,4 +17,5 @@
 	.write = coff32write,
 	.getsym = coff32getsym,
 	.getsec = coff32getsec,
+	.loadmap = coff32loadmap,
 };
--- a/src/libmach/coff32/coff32.h
+++ b/src/libmach/coff32/coff32.h
@@ -41,3 +41,4 @@
 
 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);
--- /dev/null
+++ b/src/libmach/coff32/coff32loadmap.c
@@ -1,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;
+}
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -36,11 +36,23 @@
 	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);
 
 	int (*setidx)(long nsyms, char *names[], long offset[], FILE *fp);
 	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 */
--- /dev/null
+++ b/src/libmach/loadmap.c
@@ -1,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);
+}
--- a/src/libmach/mapsec.c
+++ /dev/null
@@ -1,11 +1,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-int
-mapsec(Obj *obj, int idx, FILE *fp)
-{
-	return 0;
-}
--- /dev/null
+++ b/src/libmach/newmap.c
@@ -1,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;
+}
--- /dev/null
+++ b/src/libmach/setmap.c
@@ -1,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
--- 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