scc

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

commit e567abdd9acdb51e5c79cbb0ac7fd9f2ae3357e0
parent 3d5c5f4032f30a579d4ffa17cc77d7799676514d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 28 Aug 2019 14:51:43 +0100

[libmach] Add getindex() and setindex()

Diffstat:
Minclude/scc/scc/mach.h | 12++++++++++++
Msrc/cmd/Makefile | 2+-
Msrc/cmd/ranlib.c | 206+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/libmach/Makefile | 2++
Msrc/libmach/libmach.h | 9---------
5 files changed, 112 insertions(+), 119 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -1,5 +1,6 @@ typedef struct symbol Symbol; typedef struct section Section; +typedef struct objops Objops; typedef struct obj Obj; enum sectype { @@ -13,6 +14,14 @@ enum sectype { SSHARED = 1 << 7, }; +struct obj { + char *index; + Objops *ops; + int type; + long pos; + void *data; +}; + struct section { char *name; unsigned long long base; @@ -46,3 +55,6 @@ extern int strip(Obj *obj); extern Symbol *getsym(Obj *obj, long *index, Symbol *sym); extern Section *getsec(Obj *obj, long *index, Section *sec); + +extern int setindex(int, long, char **, long *, FILE *); +extern int getindex(int, long *, char ***, long **, FILE *); diff --git a/src/cmd/Makefile b/src/cmd/Makefile @@ -7,8 +7,8 @@ TARGET = $(BINDIR)/nm \ $(BINDIR)/ar \ $(BINDIR)/strip \ $(BINDIR)/size \ + $(BINDIR)/ranlib \ -# $(BINDIR)/ranlib \ # $(BINDIR)/objdump \ # $(BINDIR)/objcopy \ # $(BINDIR)/addr2line \ diff --git a/src/cmd/ranlib.c b/src/cmd/ranlib.c @@ -28,18 +28,11 @@ struct symdef { static char *namidx; static long nsymbols; static int status, artype, nolib; -static Objops *ops; static char *filename, *membname; static Symdef *htab[NR_SYMDEF], *head; static long offset; char *argv0; -static char * -errstr(void) -{ - return strerror(errno); -} - static void error(char *fmt, ...) { @@ -94,7 +87,7 @@ lookup(char *name) } static int -newsymbol(Objsym *sym) +newsymbol(Symbol *sym) { Symdef *np; @@ -102,7 +95,7 @@ newsymbol(Objsym *sym) return 1; if ((np = lookup(sym->name)) == NULL) { - error("out of memory"); + error(strerror(errno)); return 0; } @@ -142,17 +135,17 @@ freehash(void) } static int -newmember(FILE *fp, char *nam) +newmember(FILE *fp) { int t, ret = 0; + long i; Obj *obj; - Objsym *sym; + Symbol sym; - membname = nam; offset = ftell(fp); if (offset == EOF) { - error(errstr()); + error(strerror(errno)); return 0; } @@ -163,63 +156,78 @@ newmember(FILE *fp, char *nam) } artype = t; - if ((obj = objnew(t)) == NULL) { - error("out of memory"); + if ((obj = newobj(t)) == NULL) { + error(strerror(errno)); return 0; } - ops = obj->ops; namidx = obj->index; - if ((*ops->read)(obj, fp) < 0) { - error("file corrupted"); + if (readobj(obj, fp) < 0) { + error(strerror(errno)); goto error; } - for (sym = obj->syms; sym; sym = sym->next) { - if (!newsymbol(sym)) + for (i = 0; getsym(obj, &i, &sym); i++) { + if (!newsymbol(&sym)) goto error; } ret = 1; error: - (ops->del)(obj); + delobj(obj); return ret; } static int readsyms(FILE *fp) { - long r, off; + long cur, off; char memb[SARNAM+1]; + nolib = 0; + artype = -1; + nsymbols = 0; + if (!archive(fp)) { error("file format not recognized"); return 0; } + cur = ftell(fp); if ((off = armember(fp, memb)) < 0) goto corrupted; - if (strcmp(memb, "/") != 0 && strcmp(memb, "__.SYMDEF") != 0) { - if (fseek(fp, -off, SEEK_CUR) == EOF) { - error(errstr()); - return 0; + if (strcmp(memb, "/") == 0 || strcmp(memb, "__.SYMDEF") == 0) + cur = ftell(fp) + off; + + fseek(fp, SEEK_SET, cur); + for (;;) { + cur = ftell(fp); + off = armember(fp, memb); + switch (off) { + case -1: + goto corrupted; + case 0: + return (nolib || nsymbols == 0) ? -1 : 0; + default: + membname = memb; + if (objtype(fp, NULL) != -1) + newmember(fp); + membname = NULL; + fseek(fp, cur, SEEK_SET); + fseek(fp, off, SEEK_CUR); + break; } } - while ((r = armember(fp, memb)) > 0) - newmember(fp, memb); - if (r < 0) - goto corrupted; - return 1; - corrupted: - error("corrupted ar file"); + error(strerror(errno)); + error("library corrupted"); return 0; } -static int +static void merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx) { int c; @@ -231,7 +239,7 @@ merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx) fseek(lib, SARMAG, SEEK_SET); if (fread(&first, sizeof(first), 1, lib) != 1) - return 0; + return; if (!strncmp(first.ar_name, namidx, SARNAM)) fseek(lib, atol(first.ar_size), SEEK_CUR); @@ -259,111 +267,91 @@ merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx) putc(c, to); fflush(to); - - if (ferror(to) || ferror(lib) || ferror(idx)) - return 0; - - return 1; } -static int -copy(FILE *from, char *fname) -{ - int c, ret; - FILE *fp; - - if ((fp = fopen(fname, "wb")) == NULL) - return 0; - - rewind(from); - while ((c = getc(from)) != EOF) - putc(c, fp); - fflush(fp); - - ret = !ferror(fp) && !ferror(from); - - fclose(fp); - - return ret; -} - - static void ranlib(char *fname) { + size_t r; long *offs, i; char **names; FILE *fp, *idx, *out; Symdef *dp; struct fprop prop; + char tmpname[FILENAME_MAX]; - errno = 0; - nolib = 0; - artype = -1; - nsymbols = 0; - offs = NULL; - names = NULL; filename = fname; - freehash(); + if ((fp = fopen(fname, "rb")) == NULL) { + error(strerror(errno)); + return; + } - fp = fopen(fname, "rb"); - idx = tmpfile(); - out = tmpfile(); - if (!fp || !idx || !out) - goto error; + if (readsyms(fp) <0) + goto err2; - if (!readsyms(fp)) - goto error; - - if (nolib || nsymbols == 0) - goto error; + if ((idx = tmpfile()) == NULL) { + error(strerror(errno)); + goto err2; + } offs = malloc(sizeof(long) * nsymbols); names = malloc(sizeof(*names) * nsymbols); + if (!offs || !names) { + error(strerror(errno)); + goto err3; + } for (dp = head, i = 0; i < nsymbols; dp = dp->next, i++) { offs[i] = dp->offset; names[i] = dp->name; } - if ((*ops->setidx)(nsymbols, names, offs, idx) < 0) - goto error; + if (setindex(artype, nsymbols, names, offs, idx) < 0) { + error(strerror(errno)); + goto err3; + } - if (getstat(fname, &prop) < 0) - goto error; + if (getstat(fname, &prop) < 0) { + error(strerror(errno)); + goto err3; + } prop.size = ftell(idx); prop.time = time(NULL); - if (!merge(out, &prop, fp, idx)) - goto error; + r = snprintf(tmpname, sizeof(tmpname), "%s.tmp", fname); + if (r >= sizeof(tmpname)) { + error("too long temporary name"); + goto err3; + } - free(offs); - free(names); - fclose(fp); - fclose(idx); - offs = NULL; - names = NULL; - fp = idx = NULL; + if ((out = fopen(tmpname, "wb")) == NULL) { + error(strerror(errno)); + goto err3; + } - if (!copy(out, fname)) - goto error; - fclose(out); + merge(out, &prop, fp, idx); + if (ferror(out) || ferror(fp) || ferror(idx)) { + error(strerror(errno)); + fclose(out); + goto err4; + } - return; + fclose(out); + if (rename(tmpname, fname) == EOF) { + error(strerror(errno)); + goto err4; + } -error: - if (offs) - free(offs); - if (names) - free(names); - if (errno) - error(errstr()); - if (idx) - fclose(idx); - if (out) - fclose(out); - if (fp) - fclose(fp); +err4: + remove(tmpname); +err3: + free(offs); + free(names); + fclose(idx); +err2: + freehash(); +err1: + fclose(fp); } static void diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -18,6 +18,8 @@ OBJS = mach.o \ strip.o \ pack.o \ unpack.o \ + setindex.o \ + getindex.o \ DIRS = coff32 diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -4,7 +4,6 @@ #define ARCH(t) (((t) >> 5) & 0x1f) #define ORDER(t) (((t) >> 10) & 0x1f) -typedef struct objops Objops; enum objformat { COFF32, @@ -44,14 +43,6 @@ struct objops { int (*getidx)(long *nsyms, char ***names, long **offset, FILE *fp); }; -struct obj { - char *index; - struct objops *ops; - int type; - long pos; - void *data; -}; - /* common functions */ extern int pack(int order, unsigned char *dst, char *fmt, ...); extern int unpack(int order, unsigned char *src, char *fmt, ...);