scc

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

commit 06ac542c1d1eef0a4b0801f321a1efa65129804d
parent be5af009b81e52520a310c823d9d60313a26a563
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun,  1 Sep 2019 12:30:55 +0100

[libmach] Add findsec()

This function returns the index of the Mapsec inside of a
Map.

Diffstat:
Minclude/scc/scc/mach.h | 9++++++++-
Msrc/cmd/strip.c | 47++++++++++++++++++++++++++++++++++-------------
Msrc/libmach/Makefile | 1+
Msrc/libmach/coff32/coff32.h | 2+-
Msrc/libmach/coff32/coff32loadmap.c | 12+++++++++---
Msrc/libmach/coff32/coff32write.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Asrc/libmach/findsec.c | 20++++++++++++++++++++
Msrc/libmach/libmach.h | 4+++-
Msrc/libmach/setmap.c | 31+++++++++++++++----------------
Msrc/libmach/writeobj.c | 5++---
10 files changed, 152 insertions(+), 44 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -4,6 +4,7 @@ typedef struct symbol Symbol; typedef struct objops Objops; typedef struct obj Obj; typedef struct map Map; +typedef struct mapsec Mapsec; enum sectype { SREAD = 1 << 0, @@ -70,7 +71,13 @@ extern int rebase(Obj *obj, int index, unsigned long long offset); extern Map *loadmap(Obj *obj, FILE *fp); extern Map *newmap(int n, FILE *fp); -extern int setmap(Map *map, char *name, long off); +extern int findsec(Map *map, char *name); +extern int setmap(Map *map, + char *name, + FILE *fp, + unsigned long long begin, + unsigned long long end, + 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/strip.c b/src/cmd/strip.c @@ -42,28 +42,50 @@ doit(char *fname) error("%s: name too long", fname); return; } - if ((src = fopen(fname, "rb")) == NULL) + if ((src = fopen(fname, "rb")) == NULL) { + error("opening src file"); goto err0; - if ((type = objtype(src, NULL)) < 0) + } + if ((type = objtype(src, NULL)) < 0) { + error("getting object type"); goto err1; - if ((obj = newobj(type)) == NULL) + } + if ((obj = newobj(type)) == NULL) { + error("creating object"); goto err1; - if (readobj(obj, src) < 0) + } + if (readobj(obj, src) < 0) { + error("reading object"); goto err2; - if ((map = loadmap(obj, src)) == NULL) + } + if ((map = loadmap(obj, src)) == NULL) { + error("loading map"); goto err3; - if (strip(obj) < 0) + } + if (strip(obj) < 0) { + error("stripping"); goto err3; - if ((dst = fopen(tmpname, "wb")) == NULL) + } + if ((dst = fopen(tmpname, "wb")) == NULL) { + error("opening dst"); goto err3; - if (writeobj(obj, map, dst) < 0) + } + if (writeobj(obj, map, dst) < 0) { + error("writing object"); goto err5; - if (fclose(dst) == EOF) + } + if (fclose(dst) == EOF) { + error("closing dst"); goto err4; - if (remove(fname) == EOF) + } + if (remove(fname) == EOF) { + error("removing fname"); goto err4; - if (rename(tmpname, fname) == EOF) + } + if (rename(tmpname, fname) == EOF) { + error("rename fname"); goto err4; + } goto err3; @@ -78,8 +100,7 @@ err2: err1: fclose(src); err0: - if (errno) - error(strerror(errno)); + error("cannot strip it"); } static void diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -20,6 +20,7 @@ OBJS =\ loadmap.o\ newmap.o\ setmap.o\ + findsec.o\ strip.o\ pc2line.o\ pack.o\ diff --git a/src/libmach/coff32/coff32.h b/src/libmach/coff32/coff32.h @@ -31,7 +31,7 @@ extern int coff32getidx(long *nsyms, char ***namep, long **offsp, FILE *fp); extern int coff32pc2line(Obj *, unsigned long long , char *, int *); extern int coff32strip(Obj *obj); extern void coff32del(Obj *obj); -extern int coff32write(Obj *obj, FILE *fp); +extern int coff32write(Obj *obj, Map * map, FILE *fp); extern int coff32probe(unsigned char *buf, char **name); extern int coff32xsetidx(int order, diff --git a/src/libmach/coff32/coff32loadmap.c b/src/libmach/coff32/coff32loadmap.c @@ -10,16 +10,22 @@ coff32loadmap(Obj *obj, FILE *fp) { long i; Map *map; + long nsec; SCNHDR *scn; struct coff32 *coff = obj->data; FILHDR *hdr = &coff->hdr; - long nsec = hdr->f_nscns; + 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); + for (scn = coff->scns; nsec--; ++scn) { + unsigned long o = obj->pos + scn->s_scnptr; + unsigned long long b = scn->s_paddr; + unsigned long long e = b + scn->s_size; + + setmap(map, scn->s_name, fp, b, e, o); + } return map; } diff --git a/src/libmach/coff32/coff32write.c b/src/libmach/coff32/coff32write.c @@ -273,15 +273,12 @@ writelines(Obj *obj, FILE *fp) { int i; long j; - FILHDR *hdr; LINENO *lp; SCNHDR *scn; - struct coff32 *coff; + struct coff32 *coff = obj->data; + FILHDR *hdr = &coff->hdr; unsigned char buf[LINESZ]; - coff = obj->data; - hdr = &coff->hdr; - if (!coff->lines) return 1; @@ -300,15 +297,71 @@ writelines(Obj *obj, FILE *fp) return 1; } +static int +writedata(Obj *obj, Map *map, FILE *fp) +{ + int id; + long nsec; + unsigned long long n; + struct coff32 *coff = obj->data; + FILHDR *hdr = &coff->hdr; + SCNHDR *scn; + Mapsec *sec; + + nsec = hdr->f_nscns; + for (scn = coff->scns; nsec--; scn++) { + if ((id = findsec(map, scn->s_name)) < 0) + return 0; + sec = &map->sec[id]; + fseek(sec->fp, sec->offset, SEEK_SET); + + for (n = sec->end - sec->begin; n > 0; n--) + putc(getc(sec->fp), fp); + } + + return !ferror(fp); +} + int -coff32write(Obj *obj, FILE *fp) +coff32write(Obj *obj, Map *map, FILE *fp) { + long ptr, n; + SCNHDR *scn; + struct coff32 *coff = obj->data; + FILHDR *hdr = &coff->hdr; + + ptr = ftell(fp); + obj->pos = ptr; + ptr += FILHSZ + AOUTSZ + n*hdr->f_nscns; + + n = hdr->f_nscns; + for (scn = coff->scns; n--; scn++) { + scn->s_scnptr = ptr; + ptr += scn->s_size; + } + + n = hdr->f_nscns; + for (scn = coff->scns; n--; scn++) { + scn->s_relptr = ptr; + ptr += scn->s_nrelloc * RELSZ; + } + + n = hdr->f_nscns; + for (scn = coff->scns; n--; scn++) { + scn->s_lnnoptr = ptr; + ptr += scn->s_nlnno * RELSZ; + } + + /* and now update symbols */ + if (!writehdr(obj, fp)) return -1; if (!writeaout(obj, fp)) return -1; if (!writescns(obj, fp)) return -1; + if (!writedata(obj, map, fp)) + return -1; if (!writereloc(obj, fp)) return -1; if (!writelines(obj, fp)) diff --git a/src/libmach/findsec.c b/src/libmach/findsec.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +#include <scc/mach.h> + +#include "libmach.h" + +int +findsec(Map *map, char *name) +{ + int i; + struct mapsec *sec; + + for (i = 0; i < map->sec; i++) { + char *s = map->sec[i].name; + if (s && strcmp(s, name) == 0) + return i; + } + + return -1; +} diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -31,7 +31,7 @@ struct objops { void (*del)(Obj *obj); int (*read)(Obj *obj, FILE *fp); - int (*write)(Obj *obj, FILE *fp); + int (*write)(Obj *obj, Map *map, FILE *fp); int (*strip)(Obj *obj); int (*pc2line)(Obj *, unsigned long long , char *, int *); @@ -51,6 +51,8 @@ struct map { struct mapsec { char *name; FILE *fp; + unsigned long long begin; + unsigned long long end; long offset; } sec[]; }; diff --git a/src/libmach/setmap.c b/src/libmach/setmap.c @@ -6,28 +6,27 @@ #include "libmach.h" int -setmap(Map *map, char *name, long off) +setmap(Map *map, + char *name, + FILE *fp, + unsigned long long begin, + unsigned long long end, + long off) { int n; - struct mapsec *sec; + Mapsec *sec; n = map->n; for (sec = map->sec; n--; sec++) { - if (sec->name && strcmp(sec->name, name) == 0) - goto found; + if (!sec->name) { + sec->name = name; + sec->fp = fp, + sec->begin = begin; + sec->end = end; + sec->offset = off; + return 0; + } } - 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 @@ -7,5 +7,5 @@ int writeobj(Obj *obj, Map *map, FILE *fp) { - return (obj->ops->write)(obj, fp); -} -\ No newline at end of file + return (obj->ops->write)(obj, map, fp); +}