ref: 454313e5735b42a3c6d464bbb78be1dcc82a0034
parent: d31f41ad68c39eb244316ae777bcddfb98beca17
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Aug 28 10:51:43 EDT 2019
[libmach] Add getindex() and setindex()
--- 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 @@
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 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 *);
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -7,8 +7,8 @@
$(BINDIR)/ar \
$(BINDIR)/strip \
$(BINDIR)/size \
+ $(BINDIR)/ranlib \
-# $(BINDIR)/ranlib \
# $(BINDIR)/objdump \
# $(BINDIR)/objcopy \
# $(BINDIR)/addr2line \
--- a/src/cmd/ranlib.c
+++ b/src/cmd/ranlib.c
@@ -28,18 +28,11 @@
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 @@
}
static int
-newsymbol(Objsym *sym)
+newsymbol(Symbol *sym)
{
Symdef *np;
@@ -102,7 +95,7 @@
return 1;
if ((np = lookup(sym->name)) == NULL) {
- error("out of memory");
+ error(strerror(errno));
return 0;
}
@@ -142,17 +135,17 @@
}
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,20 +156,19 @@
}
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;
}
@@ -183,7 +175,7 @@
ret = 1;
error:
- (ops->del)(obj);
+ delobj(obj);
return ret;
}
@@ -190,36 +182,52 @@
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 @@
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,67 +267,39 @@
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 ((idx = tmpfile()) == NULL) {
+ error(strerror(errno));
+ goto err2;
+ }
- if (nolib || nsymbols == 0)
- goto error;
-
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;
@@ -326,44 +306,52 @@
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;
+ merge(out, &prop, fp, idx);
+ if (ferror(out) || ferror(fp) || ferror(idx)) {
+ error(strerror(errno));
+ fclose(out);
+ goto err4;
+ }
+
fclose(out);
+ if (rename(tmpname, fname) == EOF) {
+ error(strerror(errno));
+ goto err4;
+ }
- return;
-
-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
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -18,6 +18,8 @@
strip.o \
pack.o \
unpack.o \
+ setindex.o \
+ getindex.o \
DIRS = coff32
--- 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,
@@ -42,14 +41,6 @@
int (*setidx)(long nsyms, char *names[], long offset[], FILE *fp);
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 */