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