scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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:
Minclude/scc/scc/mach.h | 8++++++--
Msrc/cmd/ld/section.c | 6++++++
Msrc/cmd/ld/symbol.c | 5++---
Msrc/cmd/strip.c | 62++++++++++++++++++++++++++++++++++----------------------------
Msrc/libmach/Makefile | 4+++-
Msrc/libmach/coff32/Makefile | 1+
Msrc/libmach/coff32/coff32.c | 1+
Msrc/libmach/coff32/coff32.h | 1+
Asrc/libmach/coff32/coff32loadmap.c | 25+++++++++++++++++++++++++
Msrc/libmach/libmach.h | 12++++++++++++
Asrc/libmach/loadmap.c | 11+++++++++++
Dsrc/libmach/mapsec.c | 11-----------
Asrc/libmach/newmap.c | 39+++++++++++++++++++++++++++++++++++++++
Asrc/libmach/setmap.c | 34++++++++++++++++++++++++++++++++++
Msrc/libmach/writeobj.c | 2+-
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