scc

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

commit 405c21e1ee69f42a6b29efde8403dac3e02aa674
parent a4f85de611cb9d2a03a294833a95939d3a4a47af
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 30 Jan 2019 10:53:59 +0000

[ranlib] Build index file

Until now, ranlib was only a placeholder because
it didn't build the actual index. After this change
it actually did it.

Diffstat:
Minclude/scc/scc/mach.h | 14++++++++++++++
Msrc/cmd/Makefile | 4++--
Msrc/cmd/ar.c | 5+++--
Msrc/cmd/posix.c | 4++++
Msrc/cmd/ranlib.c | 240+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Asrc/cmd/scc/posix/.gitignore | 1+
Msrc/libmach/Makefile | 1+
Msrc/libmach/artraverse.c | 2+-
Msrc/libmach/coff32.c | 44++++++++++++++++++++++++++++++++++++++++++--
Asrc/libmach/coffelf32.c | 33+++++++++++++++++++++++++++++++++
Msrc/libmach/libmach.h | 4++++
Msrc/libmach/object.c | 14++++++++++++++
12 files changed, 267 insertions(+), 99 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -2,6 +2,7 @@ typedef struct section Section; typedef struct symbol Symbol; +typedef struct symdef Symdef; typedef struct object Obj; enum sectype { @@ -17,6 +18,10 @@ enum sectype { struct section { char *name; unsigned flags; + FILE *fp; + long offset; + unsigned long long size; + Section *next; }; struct symbol { @@ -28,11 +33,19 @@ struct symbol { Symbol *hash; }; +struct symdef { + char *name; + int type; + long offset; + Symdef *hash, *next; +}; + struct object { int type; Symbol *htab[NR_SYMHASH]; Symbol *head; fpos_t pos; + Section *sections; void *data; }; @@ -55,6 +68,7 @@ extern int objsize(Obj *obj, unsigned long long *text, unsigned long long *data, unsigned long long *bss); +extern long arindex(int type, long nsyms, Symdef *def, FILE *fp); /* TODO */ extern int objload(Obj *obj, Obj *to); diff --git a/src/cmd/Makefile b/src/cmd/Makefile @@ -31,8 +31,8 @@ $(BINDIR)/strip: strip.o $(BINDIR)/size: size.o $(CC) $(SCC_LDFLAGS) size.o -lmach -o $@ -$(BINDIR)/ranlib: ranlib.o - $(CC) $(SCC_LDFLAGS) ranlib.o -lmach -o $@ +$(BINDIR)/ranlib: ranlib.o $(DRIVER).o + $(CC) $(SCC_LDFLAGS) ranlib.o $(DRIVER).o -lmach -o $@ $(BINDIR)/objdump: objdump.o $(CC) $(SCC_LDFLAGS) objdump.o -lmach -o $@ diff --git a/src/cmd/ar.c b/src/cmd/ar.c @@ -123,15 +123,16 @@ archive(char *pname, FILE *to, char letter) error("opening member '%s': %s", pname, errstr()); if (getstat(pname, &prop) < 0) error("error getting '%s' attributes", pname); + strftime(mtime, sizeof(mtime), "%s", gmtime(&prop.time)); fprintf(to, - "%-16.16s%-12s%-6u%-6u%-8lo%-10llu`\n", + "%-16.16s%-12s%-6u%-6u%-8lo%-10ld`\n", fname, mtime, prop.uid, prop.gid, prop.mode, - (unsigned long long) prop.size); + prop.size); for (n = 0; (c = getc(from)) != EOF; n++) putc(c, to); if (n & 1) diff --git a/src/cmd/posix.c b/src/cmd/posix.c @@ -7,6 +7,8 @@ static char sccsid[] = "@(#) ./ar/posix/driver.c"; #include <unistd.h> #include <utime.h> +#include <limits.h> + #include "sys.h" const char invalidchars[] = " "; @@ -31,6 +33,8 @@ getstat(char *fname, struct fprop *prop) if (stat(fname, &st) < 0) return -1; + if (st.st_size > LONG_MAX) + return -1; prop->uid = st.st_uid; prop->gid = st.st_gid; prop->mode = st.st_mode; diff --git a/src/cmd/ranlib.c b/src/cmd/ranlib.c @@ -1,27 +1,24 @@ #include <ctype.h> #include <errno.h> +#include <limits.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> +#include <scc/ar.h> #include <scc/arg.h> #include <scc/mach.h> -#define NR_NAMES 32 +#include "sys.h" -typedef struct name Name; +#define NR_SYMDEF 32 -struct name { - char *name; - int type; - long offset; - Name *hash, *next; -}; - -static int status, tflag, artype, nolib; +static long nsymbols; +static int status, artype, nolib; static char *filename, *membname; -static Name *htab[NR_NAMES], *head; +static Symdef *htab[NR_SYMDEF], *head; static long offset; char *argv0; @@ -47,50 +44,52 @@ error(char *fmt, ...) status = EXIT_FAILURE; } -Name * +Symdef * lookup(char *name) { unsigned h; - Name *np; + Symdef *dp; char *s; size_t len; h = 0; for (s = name; *s; s++) h += *s; - h %= NR_NAMES; + h %= NR_SYMDEF; - for (np = htab[h]; np; np = np->next) { - if (!strcmp(np->name, name)) - return np; + for (dp = htab[h]; dp; dp = dp->next) { + if (!strcmp(dp->name, name)) + return dp; } len = strlen(name) + 1; - np = malloc(sizeof(*np)); + dp = malloc(sizeof(*dp)); s = malloc(len); - if (!np || !s) { + if (!dp || !s) { free(s); - free(np); + free(dp); return NULL; } - memcpy(np->name, s, len); - np->type = 'U'; - np->offset = -1; - np->hash = htab[h]; - htab[h] = np; - np->next = head; - head = np; - - return np; + nsymbols++; + dp->name = s; + memcpy(dp->name, name, len); + dp->type = 'U'; + dp->offset = -1; + dp->hash = htab[h]; + htab[h] = dp; + dp->next = head; + head = dp; + + return dp; } static int newsymbol(Symbol *sym, void *data) { - Name *np; + Symdef *np; - if (!isupper(sym->type)) + if (!isupper(sym->type) || sym->type == 'N') return 1; if ((np = lookup(sym->name)) == NULL) { @@ -117,13 +116,16 @@ newsymbol(Symbol *sym, void *data) } static int -newmember(FILE *fp, char *name, void *data) +newmember(FILE *fp, char *nam, void *data) { int t, ret = 0; Obj *obj; - membname = name; + if (artype == -1 && (!strcmp(nam, "/") || !strcmp(nam, "__.SYMDEF"))) + return 1; + + membname = nam; offset = ftell(fp); if (offset == EOF) { @@ -132,8 +134,7 @@ newmember(FILE *fp, char *name, void *data) } t = objtype(fp, NULL); - - if(t == -1 || artype != -1 && artype != t) { + if (t == -1 || artype != -1 && artype != t) { nolib = 1; return 0; } @@ -162,11 +163,11 @@ error: } static void -freenames(void) +freehash(void) { - Name **npp, *next, *np; + Symdef **npp, *next, *np; - for (npp = htab; npp < &htab[NR_NAMES]; npp++) + for (npp = htab; npp < &htab[NR_SYMDEF]; npp++) *npp = NULL; for (np = head; np; np = next) { @@ -179,97 +180,154 @@ freenames(void) } static int -readsyms(char *fname) +readsyms(FILE *fp) { - FILE *fp; - - if ((fp = fopen(fname, "rb")) == NULL) { - error(errstr()); - goto error; - } - + /* TODO: Change archive to returns -1 */ if (!archive(fp)) { error("file format not recognized"); - goto error; + return 0; } - if (!artraverse(fp, newmember, NULL)) { + if (artraverse(fp, newmember, NULL) < 0) { error("while traversing archive"); - goto error; - } - - if (fclose(fp)) { - error(errstr()); return 0; } - return 1; -error: - fclose(fp); - return 0; + return 1; } static int -writeidx(char *fname) +merge(FILE *to, struct fprop *prop, FILE *lib, FILE *idx) { - int r; - FILE *fp; - Name *np; + int c; + char mtime[13]; + struct ar_hdr first; + + rewind(lib); + rewind(idx); + fseek(lib, SARMAG, SEEK_SET); - if ((fp = fopen(fname, "wb")) == NULL) { - error("index file: %s", errstr()); + if (fread(&first, sizeof(first), 1, lib) != 1) return 0; - } - for (np = head; np; np = np->next) { - /* TODO: write out */ + if (!strncmp(first.ar_name, "/", SARNAM) || + !strncmp(first.ar_name, "__.SYMDEF", SARNAM)) { + fseek(lib, atol(first.ar_size), SEEK_CUR); } - fflush(fp); - r = ferror(fp); - fclose(fp); - if (!r) - return 1; + fwrite(ARMAG, SARMAG, 1, to); + + strftime(mtime, sizeof(mtime), "%s", gmtime(&prop->time)); + fprintf(to, + "%-16.16s%-12s%-6u%-6u%-8lo%-10ld`\n", + "/", + mtime, + prop->uid, + prop->gid, + prop->mode, + prop->size); + + while ((c = getc(idx)) != EOF) + putc(c, to); + + while ((c = getc(lib)) != EOF) + putc(c, to); + + fflush(to); - error("index file: %s", errstr()); - return 0; + if (ferror(to) || ferror(lib) || ferror(idx)) + return 0; + + return 1; } static int -insertidx(char *archive, char *idx) +copy(FILE *from, char *fname) { - return 0; + 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) { - static char symdef[] = "__.SYMDEF"; + int c; + FILE *fp, *idx, *out; + long siz; + struct fprop prop; + errno = 0; nolib = 0; artype = -1; + nsymbols = 0; filename = fname; - freenames(); + freehash(); + + fp = fopen(fname, "rb"); + idx = tmpfile(); + out = tmpfile(); + if (!fp || !idx || !out) + goto error; - if (!readsyms(fname)) - return; + if (!readsyms(fp)) + goto error; if (nolib) - return; + goto error; + + /* TODO: Change arindex to returns -1 */ + siz = arindex(artype, nsymbols, head, idx); + if (siz <= 0) + goto error; + + if (getstat(fname, &prop) < 0) + goto error; + prop.size = siz; + prop.time = time(NULL); + + if (!merge(out, &prop, fp, idx)) + goto error; + + fclose(fp); + fclose(idx); + fp = idx = NULL; - if (!writeidx(symdef)) - return; + if (!copy(out, fname)) + goto error; - if (!insertidx(fname, symdef)) - remove(symdef); + fclose(out); return; + +error: + if (errno) + error(errstr()); + if (idx) + fclose(idx); + if (out) + fclose(out); + if (fp) + fclose(fp); } static void usage(void) { - fputs("usage: ranlib [-t] [file...]\n", stderr); + fputs("usage: ranlib [-t] file...\n", stderr); exit(EXIT_FAILURE); } @@ -278,18 +336,16 @@ main(int argc, char *argv[]) { ARGBEGIN { case 't': - tflag = 1; /* TODO */ break; default: usage(); } ARGEND - if (argc == 0) { - ranlib("a.out"); - } else { - for (; *argv; ++argv) - ranlib(*argv); - } + if (argc == 0) + usage(); + + for (; *argv; ++argv) + ranlib(*argv); return status; } diff --git a/src/cmd/scc/posix/.gitignore b/src/cmd/scc/posix/.gitignore @@ -0,0 +1 @@ +config.h diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -11,6 +11,7 @@ OBJS = object.o \ armember.o \ objfmt.o \ coff32.o \ + coffelf32.o \ all: $(TARGET) diff --git a/src/libmach/artraverse.c b/src/libmach/artraverse.c @@ -17,7 +17,7 @@ artraverse(FILE *fp, int (*fn)(FILE *, char *, void *), void *data) if ((off = armember(fp, name)) <= 0) return off; r = (*fn)(fp, name, data); - if (!r) + if (r <= 0) return r; fsetpos(fp, &pos); diff --git a/src/libmach/coff32.c b/src/libmach/coff32.c @@ -165,7 +165,7 @@ typeof(Coff32 *coff, SYMENT *ent) } static int -mkindex(Obj *obj) +loadsyms(Obj *obj) { int t; long i; @@ -310,6 +310,37 @@ readhdr(Obj *obj, FILE *fp) } static int +loadsections(Obj *obj, FILE *fp) +{ + size_t len; + int i; + FILHDR *hdr; + struct coff32 *coff; + SCNHDR *scn; + Section *p; + + coff = obj->data; + hdr = &coff->hdr; + scn = coff->scns; + for (i = 0; i < hdr->f_nscns; i++) { + if ((p = malloc(sizeof(*p))) == NULL) + return 0; + len = strlen(scn->s_name) + 1; + if ((p->name = malloc(len)) == NULL) { + free(p); + return 0; + } + memcpy(p->name, scn->s_name, len); + p->fp = fp; + p->offset = scn->s_scnptr; + p->size = scn->s_size; + p->next = obj->sections; + obj->sections = p->next; + } + return 1; +} + +static int read(Obj *obj, FILE *fp) { if (fgetpos(fp, &obj->pos)) @@ -322,7 +353,9 @@ read(Obj *obj, FILE *fp) goto error; if (!readstr(obj, fp)) goto error; - if (!mkindex(obj)) + if (!loadsyms(obj)) + goto error; + if (!loadsections(obj, fp)) goto error; return 0; @@ -413,6 +446,12 @@ size(Obj *obj, return 0; } +static long +mkindex(int type, long nsymbols, Symdef *head, FILE *fp) +{ + return coff32idx(BIG_ENDIAN, nsymbols, head, fp); +} + struct format objcoff32 = { .probe = probe, .new = new, @@ -421,4 +460,5 @@ struct format objcoff32 = { .write = write, .strip = strip, .size = size, + .index = mkindex, }; diff --git a/src/libmach/coffelf32.c b/src/libmach/coffelf32.c @@ -0,0 +1,33 @@ +#include <stdio.h> +#include <string.h> + +#include <scc/mach.h> + +#include "libmach.h" + +long +coff32idx(int order, long nsyms, Symdef *head, FILE *fp) +{ + long i, n; + size_t len; + Symdef *def; + unsigned char buff[4]; + + pack(order, buff, "l", nsyms); + fwrite(buff, 4, 1, fp); + n = 4; + + for (def = head; def; def = def->next) { + pack(order, buff, "l", (long) def->offset); + fwrite(buff, 4, 1, fp); + n += 4; + } + + for (def = head; def; def = def->next) { + len = strlen(def->name); + fwrite(def->name, len+1, 1, fp); + n += len; + } + + return fflush(fp) == EOF ? -1 : n; +} diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -37,11 +37,15 @@ struct format { unsigned long long *, unsigned long long *, unsigned long long *); + long (*index)(int type, long nsyms, Symdef *def, FILE *fp); }; extern int pack(int order, unsigned char *dst, char *fmt, ...); extern int unpack(int order, unsigned char *src, char *fmt, ...); +/* idx functions */ +extern long coff32idx(int order, long nsyms, Symdef *def, FILE *fp); + /* globals */ extern struct format *objfmt[]; diff --git a/src/libmach/object.c b/src/libmach/object.c @@ -121,6 +121,7 @@ objnew(int type) obj->type = type; obj->head = NULL; + obj->sections = NULL; memset(obj->htab, 0, sizeof(obj->htab)); op = objfmt[fmt]; @@ -213,6 +214,19 @@ objsize(Obj *obj, return (*op->size)(obj, text, data, bss); } +long +arindex(int type, long nsyms, Symdef *head, FILE *fp) +{ + int fmt; + struct format *op; + + fmt = FORMAT(type); + if (fmt >= NFORMATS) + return -1; + op = objfmt[fmt]; + return (*op->index)(type, nsyms, head, fp); +} + int addr2line(Obj *obj, unsigned long long addr, char *fname, int *line) {