ref: 845a4d450d705c86e557494e4661abddf4f157be
parent: d4f9d2c95f2fcc650b00fc39e6690df9ed953c89
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Aug 27 08:10:33 EDT 2019
[libmach] Big rework of libmach (Symbol) Libmach had a lot of different problems and one of them was the definition of Objsym, that forced every tool to mess with object symbol datatypes and specific types.
--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -1,7 +1,7 @@
#define NR_SYMHASH 32
typedef struct objsec Objsec;
-typedef struct objsym Objsym;
+typedef struct symbol Symbol;
typedef struct objseg Objseg;
typedef struct objops Objops;
typedef struct obj Obj;
@@ -28,7 +28,7 @@
Objsec *next;
};
-struct objsym {
+struct symbol {
char *name;
unsigned long long size;
unsigned long long value;
@@ -36,8 +36,6 @@
int index;
char class;
char type;
-
- Objsym *next, *hash;
};
struct objseg {
@@ -51,23 +49,18 @@
void (*del)(Obj *obj);
int (*read)(Obj *obj, FILE *fp);
int (*write)(Obj *obj, FILE *fp);
- int (*addseg)(Obj *obj, void *seg);
int (*strip)(Obj *obj);
int (*addr2line)(Obj *, unsigned long long , char *, int *);
+ int (*getsym)(Obj *obj, long *index, Symbol *sym);
int (*setidx)(long nsyms, char *names[], long offset[], FILE *fp);
int (*getidx)(long *nsyms, char ***names, long **offset, FILE *fp);
};
struct obj {
- int type;
- Objops *ops;
char *index;
- Objsym *htab[NR_SYMHASH];
- Objsym *syms;
- Objsec *secs;
+ Objops *ops;
+ int type;
long pos;
- int nsecs;
- int nsyms;
void *data;
};
@@ -76,5 +69,5 @@
extern int objtype(FILE *fp, char **name);
extern Obj *objnew(int type);
-extern Objsym *objlookup(Obj *obj, char *name, int install);
-extern int objpos(Obj *obj, FILE *fp, long pos);
+extern int readobj(Obj *obj, FILE *fp);
+extern int getsym(Obj *obj, long *index, Symbol *sym);
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -4,13 +4,14 @@
include $(PROJECTDIR)/scripts/rules.mk
TARGET = $(BINDIR)/nm \
- $(BINDIR)/strip \
- $(BINDIR)/size \
$(BINDIR)/ar \
- $(BINDIR)/ranlib \
- $(BINDIR)/objdump \
- $(BINDIR)/objcopy \
- $(BINDIR)/addr2line \
+
+# $(BINDIR)/strip \
+# $(BINDIR)/size \
+# $(BINDIR)/ranlib \
+# $(BINDIR)/objdump \
+# $(BINDIR)/objcopy \
+# $(BINDIR)/addr2line \
DIRS = as scc
--- a/src/cmd/nm.c
+++ b/src/cmd/nm.c
@@ -12,7 +12,7 @@
struct symtbl {
- Objsym **buf;
+ Symbol **buf;
size_t nsyms;
};
@@ -45,8 +45,8 @@
static int
cmp(const void *p1, const void *p2)
{
- Objsym **s1 = (Objsym **) p1, **s2 = (Objsym **) p2;
- Objsym *sym1 = *s1, *sym2 = *s2;
+ Symbol **s1 = (Symbol **) p1, **s2 = (Symbol **) p2;
+ Symbol *sym1 = *s1, *sym2 = *s2;
if (vflag) {
if (sym1->value > sym2->value)
@@ -66,17 +66,19 @@
}
static void
-printsyms(Objsym **syms, size_t nsym)
+printsyms(Symbol **syms, size_t nsym)
{
size_t i;
qsort(syms, nsym, sizeof(syms), cmp);
- if (multi)
- printf("%s:\n", (membname) ? membname : filename);
+ if (!Aflag) {
+ if (multi || membname)
+ printf("%s:\n", (membname) ? membname : filename);
+ }
for (i = 0; i < nsym; i++) {
- Objsym *sym = syms[i];
+ Symbol *sym = syms[i];
int type = sym->type;
char *fmt;
@@ -113,9 +115,9 @@
}
static int
-newsym(Objsym *sym, struct symtbl *tbl)
+newsym(Symbol *sym, struct symtbl *tbl)
{
- Objsym **p;
+ Symbol **p, *s;
size_t n, size;
int type = sym->type;
@@ -133,10 +135,16 @@
return 0;
size = n *sizeof(*p);
- if ((p = realloc(tbl->buf, size)) == NULL)
- return 0;
+ p = realloc(tbl->buf, size);
+ s = malloc(sizeof(*s));
+ if (!p || !s) {
+ error("out of memory");
+ exit(EXIT_FAILURE);
+ }
+
+ *s = *sym;
tbl->buf = p;
- p[tbl->nsyms++] = sym;
+ p[tbl->nsyms++] = s;
return 1;
}
@@ -145,20 +153,21 @@
newobject(FILE *fp, int type)
{
int err = 1;
+ long i;
Obj *obj;
- Objsym *sym;
+ Symbol sym;
struct symtbl tbl = {NULL, 0};
if ((obj = objnew(type)) == NULL) {
error("out of memory");
- return;
+ exit(EXIT_FAILURE);
}
- if ((*obj->ops->read)(obj, fp) < 0)
+ if (readobj(obj, fp) < 0)
goto error;
- for (sym = obj->syms; sym; sym = sym->next)
- newsym(sym, &tbl);
+ for (i = 0; getsym(obj, &i, &sym); i++)
+ newsym(&sym, &tbl);
printsyms(tbl.buf, tbl.nsyms);
err = 0;
@@ -174,17 +183,29 @@
newlib(FILE *fp)
{
int t;
- long r;
+ long off, cur;
char memb[SARNAM+1];
- while ((r = armember(fp, memb)) > 0) {
- membname = memb;
- if ((t = objtype(fp, NULL)) != -1)
- newobject(fp, t);
- membname = NULL;
+ while (!feof(fp)) {
+ cur = ftell(fp);
+ off = armember(fp, memb);
+ switch (off) {
+ case -1:
+ error("library corrupted");
+ case 0:
+ return;
+ default:
+ membname = memb;
+ if ((t = objtype(fp, NULL)) != -1)
+ newobject(fp, t);
+ membname = NULL;
+ fseek(fp, cur, SEEK_SET);
+ fseek(fp, off, SEEK_CUR);
+ break;
+ }
}
- if (r < 0)
- error("library corrupted");
+
+ error("library corrupted:%s", strerror(errno));
}
static void
@@ -267,7 +288,9 @@
}
if (fflush(stdout)) {
- fprintf(stderr, "nm: error writing in output");
+ fprintf(stderr,
+ "nm: error writing in output:%s\n",
+ strerror(errno));
status = 1;
}
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -7,17 +7,11 @@
OBJS = mach.o \
objnew.o \
objpos.o \
- objfree.o \
- objstrip.o \
- objdel.o \
- objaddseg.o \
- objsync.o \
- addr2line.o \
archive.o \
armember.o \
- objlookup.o \
objtype.o \
- objwrite.o \
+ readobj.o \
+ getsym.o \
pack.o \
unpack.o \
--- a/src/libmach/coff32/Makefile
+++ b/src/libmach/coff32/Makefile
@@ -16,6 +16,7 @@
coff32setidx.o \
coff32getidx.o \
coff32addr2line.o \
+ coff32getsym.o \
all: $(OBJS)
--- a/src/libmach/coff32/coff32.c
+++ b/src/libmach/coff32/coff32.c
@@ -6,6 +6,7 @@
#include "coff32.h"
Objops coff32 = {
+ .probe = coff32probe,
.new = coff32new,
.read = coff32read,
.getidx = coff32getidx,
@@ -14,4 +15,5 @@
.strip = coff32strip,
.del = coff32del,
.write = coff32write,
+ .getsym = coff32getsym,
};
--- a/src/libmach/coff32/coff32.h
+++ b/src/libmach/coff32/coff32.h
@@ -15,7 +15,7 @@
struct coff32 {
FILHDR hdr;
- AOUTHDR *aout;
+ AOUTHDR aout;
SCNHDR *scns;
SYMENT *ents;
RELOC **rels;
@@ -38,3 +38,5 @@
long nsymbols, char *names[], long offs[], FILE *fp);
extern int coff32xgetidx(int order,
long *nsyms, char ***namep, long **offsp, FILE *fp);
+
+extern int coff32getsym(Obj *obj, long *idx, Symbol *sym);
\ No newline at end of file
--- a/src/libmach/coff32/coff32del.c
+++ b/src/libmach/coff32/coff32del.c
@@ -19,6 +19,5 @@
free(obj->data);
obj->data = NULL;
- objdel(obj);
free(obj);
}
--- /dev/null
+++ b/src/libmach/coff32/coff32getsym.c
@@ -1,0 +1,74 @@
+#include <ctype.h>
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+static int
+typeof(Coff32 *coff, SYMENT *ent)
+{
+ int c;
+ SCNHDR *scn;
+ long flags;
+
+ switch (ent->n_scnum) {
+ case N_DEBUG:
+ c = 'N';
+ break;
+ case N_ABS:
+ c = 'a';
+ break;
+ case N_UNDEF:
+ c = (ent->n_value != 0) ? 'C' : 'U';
+ break;
+ default:
+ scn = &coff->scns[ent->n_scnum-1];
+ flags = scn->s_flags;
+ if (flags & STYP_TEXT)
+ c = 't';
+ else if (flags & STYP_DATA)
+ c = 'd';
+ else if (flags & STYP_BSS)
+ c = 'b';
+ else
+ c = '?';
+ break;
+ }
+
+ if (ent->n_sclass == C_EXT)
+ c = toupper(c);
+
+ return c;
+}
+
+static char *
+symname(Coff32 *coff, SYMENT *ent)
+{
+ if (ent->n_zeroes != 0)
+ return ent->n_name;
+
+ return &coff->strtbl[ent->n_offset];
+}
+
+int
+coff32getsym(Obj *obj, long *idx, Symbol *sym)
+{
+ long n = *idx;
+ SYMENT *ent;
+ Coff32 *coff = obj->data;
+
+ if (*idx >= coff->hdr.f_nsyms)
+ return 0;
+
+ ent = &coff->ents[n];
+ sym->name = symname(coff, ent);
+ sym->type = typeof(coff, ent);
+ sym->value = ent->n_value;
+ sym->size = (sym->type == 'C') ? ent->n_value : 0;
+ sym->index = n;
+ *idx += ent->n_numaux;
+
+ return 1;
+}
--- a/src/libmach/coff32/coff32read.c
+++ b/src/libmach/coff32/coff32read.c
@@ -82,7 +82,7 @@
s = ent->n_name;
if (!s[0] && !s[1] && !s[2] && !s[3])
- unpack(order, "ll", buf, &ent->n_zeroes, &ent->n_offset);
+ unpack(order, buf, "ll", &ent->n_zeroes, &ent->n_offset);
}
static void
@@ -153,10 +153,9 @@
if (fread(buf, 4, 1, fp) != 1)
return 0;
unpack(ORDER(obj->type), buf, "l", &siz);
- siz -= 4;
- if (siz < 0)
+ if (siz == 4)
return 0;
- if (siz > 0) {
+ if (siz > 4) {
if (siz > SIZE_MAX)
return 0;
str = malloc(siz);
@@ -165,7 +164,7 @@
coff->strtbl = str;
coff->strsiz = siz;
- if (fread(str, siz, 1, fp) != 1)
+ if (fread(str+4, siz-4, 1, fp) != 1)
return 0;
}
return 1;
@@ -185,7 +184,7 @@
coff = obj->data;
hdr = &coff->hdr;
- rels = calloc(obj->nsecs, sizeof(*rels));
+ rels = calloc(hdr->f_nscns, sizeof(*rels));
if (!rels)
return 0;
coff->rels = rels;
@@ -207,6 +206,8 @@
if (fread(buf, RELSZ, 1, fp) != 1)
return 0;
unpack_reloc(ORDER(obj->type), buf, &rp[i]);
+ if (rp[i].r_symndx >= hdr->f_nsyms)
+ return 0;
}
}
@@ -239,6 +240,8 @@
if (fread(buf, SYMESZ, 1, fp) != 1)
return 0;
unpack_ent(ORDER(obj->type), buf, &ent[i]);
+ if (ent->n_scnum > hdr->f_nscns)
+ return 0;
}
return 1;
@@ -306,6 +309,8 @@
if (fread(buf, LINESZ, 1, fp) == 1)
return 0;
unpack_line(ORDER(obj->type), buf, &lp[j]);
+ if (lp[i].l_symndx >= hdr->f_nsyms)
+ return 0;
}
}
@@ -315,13 +320,10 @@
static int
readaout(Obj *obj, FILE *fp)
{
- FILHDR *hdr;
- struct coff32 *coff;
+ struct coff32 *coff = obj->data;
+ FILHDR *hdr = &coff->hdr;
unsigned char buf[AOUTSZ];
- coff = obj->data;
- hdr = &coff->hdr;
-
if (hdr->f_opthdr == 0)
return 1;
@@ -328,25 +330,18 @@
if (fread(buf, AOUTSZ, 1, fp) != 1)
return 0;
- coff->aout = malloc(sizeof(AOUTHDR));
- if (!coff->aout)
- return 0;
+ unpack_aout(ORDER(obj->type), buf, &coff->aout);
- unpack_aout(ORDER(obj->type), buf, coff->aout);
-
return 1;
}
-static int
-readfile(Obj *obj, FILE *fp)
+int
+coff32read(Obj *obj, FILE *fp)
{
- long off;
+ long i;
+ struct coff32 *coff = obj->data;
+ FILHDR *hdr = &coff->hdr;
- /* TODO: Add validation of the different fields */
- if ((off = ftell(fp)) == EOF)
- return -1;
- obj->pos = off;
-
if (!readhdr(obj, fp))
return -1;
if (!readaout(obj, fp))
@@ -361,172 +356,12 @@
return -1;
if (!readlines(obj, fp))
return -1;
- return 0;
-}
-static int
-convsecs(Obj *obj)
-{
- int i;
- unsigned sflags, type;
- unsigned long flags;
- FILHDR *hdr;
- struct coff32 *coff;
- SCNHDR *scn;
- Objsec *secs, *sp;
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- secs = malloc(sizeof(Objsec) * hdr->f_nscns);
- if (!secs)
- return -1;
-
- for (i = 0; i < hdr->f_nscns; i++) {
- sp = &secs[i];
- sp->next = (i < hdr->f_nscns-1) ? &secs[i+1] : NULL;
- scn = &coff->scns[i];
- flags = scn->s_flags;
-
- if (flags & STYP_TEXT) {
- type = 'T';
- sflags = SALLOC | SRELOC | SLOAD | SEXEC | SREAD;
- if (flags & STYP_NOLOAD)
- sflags |= SSHARED;
- } else if (flags & STYP_DATA) {
- type = 'D';
- sflags = SALLOC | SRELOC | SLOAD | SWRITE | SREAD;
- if (flags & STYP_NOLOAD)
- sflags |= SSHARED;
- } else if (flags & STYP_BSS) {
- type = 'B';
- sflags = SALLOC | SREAD | SWRITE;
- } else if (flags & STYP_INFO) {
- type = 'N';
- sflags = 0;
- } else if (flags & STYP_LIB) {
- type = 'T';
- sflags = SRELOC;
- } else if (flags & STYP_DSECT) {
- type = 'D';
- sflags = SRELOC;
- } else if (flags & STYP_PAD) {
- type = 'D';
- sflags = SLOAD;
- } else {
- type = 'D'; /* We assume that STYP_REG is data */
- sflags = SALLOC | SRELOC | SLOAD | SWRITE | SREAD;
- }
-
- if (flags & STYP_NOLOAD)
- sflags &= ~SLOAD;
-
- sp->name = scn->s_name;
- sp->id = i;
- sp->seek = scn->s_scnptr;
- sp->size = scn->s_size;
- sp->type = type;
- sp->flags = sflags;
- sp->align = 4; /* TODO: Check how align is defined in coff */
- }
- obj->secs = secs;
- obj->nsecs = i;
-
- return 1;
-}
-
-static int
-typeof(Coff32 *coff, SYMENT *ent)
-{
- int c;
- SCNHDR *scn;
- long flags;
-
- switch (ent->n_scnum) {
- case N_DEBUG:
- c = 'N';
- break;
- case N_ABS:
- c = 'a';
- break;
- case N_UNDEF:
- c = (ent->n_value != 0) ? 'C' : 'U';
- break;
- default:
- if (ent->n_scnum > coff->hdr.f_nscns)
+ for (i = 0; i < hdr->f_nsyms; i++) {
+ SYMENT *ent = &coff->ents[i];
+ if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz)
return -1;
- scn = &coff->scns[ent->n_scnum-1];
- flags = scn->s_flags;
- if (flags & STYP_TEXT)
- c = 't';
- else if (flags & STYP_DATA)
- c = 'd';
- else if (flags & STYP_BSS)
- c = 'b';
- else
- c = '?';
- break;
}
- if (ent->n_sclass == C_EXT)
- c = toupper(c);
-
- return c;
-}
-
-static char *
-symname(Coff32 *coff, SYMENT *ent)
-{
- long off;
-
- if (ent->n_zeroes != 0)
- return ent->n_name;
-
- off = ent->n_offset;
- if (off >= coff->strsiz)
- return NULL;
- return &coff->strtbl[off];
-}
-
-static int
-convsyms(Obj *obj)
-{
- int t;
- long i;
- char *s;
- Objsym *sym;
- SYMENT *ent;
- Coff32 *coff = obj->data;
-
- for (i = 0; i < coff->hdr.f_nsyms; i += ent->n_numaux + 1) {
- ent = &coff->ents[i];
-
- if ((t = typeof(coff, ent)) < 0)
- return -1;
-
- if ((s = symname(coff, ent)) == NULL)
- return -1;
-
- if ((sym = objlookup(obj, s, 1)) == NULL)
- return -1;
-
- sym->type = t;
- sym->value = ent->n_value;
- sym->size = (sym->type == 'C') ? ent->n_value : 0;
- sym->index = ent->n_scnum-1;
- }
-
- return i;
-}
-
-int
-coff32read(Obj *obj, FILE *fp)
-{
- if (readfile(obj, fp) < 0)
- return -1;
- if (convsecs(obj) < 0)
- return -1;
- if (convsyms(obj) < 0)
- return -1;
return 0;
}
--- a/src/libmach/coff32/coff32strip.c
+++ b/src/libmach/coff32/coff32strip.c
@@ -34,7 +34,6 @@
coff->ents = NULL;
coff->rels = NULL;
coff->lines = NULL;
- objdel(obj);
return 0;
}
--- a/src/libmach/coff32/coff32write.c
+++ b/src/libmach/coff32/coff32write.c
@@ -231,7 +231,7 @@
if (hdr->f_opthdr == 0)
return 1;
- pack_aout(ORDER(obj->type), buf, coff->aout);
+ pack_aout(ORDER(obj->type), buf, &coff->aout);
return fread(buf, AOUTSZ, 1, fp) != 1;
}
--- /dev/null
+++ b/src/libmach/getsym.c
@@ -1,0 +1,9 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+int
+getsym(Obj *obj, long *index, Symbol *sym)
+{
+ return (*obj->ops->getsym)(obj, index, sym);
+}
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -26,7 +26,7 @@
/* common functions */
extern int pack(int order, unsigned char *dst, char *fmt, ...);
extern int unpack(int order, unsigned char *src, char *fmt, ...);
-extern void objdel(Obj *obj);
+extern int objpos(Obj *obj, FILE *fp, long pos);
/* globals */
extern Objops *objops[];
--- a/src/libmach/objaddseg.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-
-int
-objaddseg(Obj *obj, void *seg)
-{
- return 0;
-}
--- a/src/libmach/objdel.c
+++ /dev/null
@@ -1,18 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-void
-objdel(Obj *obj)
-{
- free(obj->secs);
- free(obj->syms);
-
- obj->syms = NULL;
- obj->secs = NULL;
- memset(obj->htab, 0, sizeof(obj->htab));
-}
--- a/src/libmach/objlookup.c
+++ /dev/null
@@ -1,35 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/mach.h>
-#include <scc/scc.h>
-
-Objsym *
-objlookup(Obj *obj, char *name, int install)
-{
- unsigned h;
- Objsym *sym;
-
- h = genhash(name) % NR_SYMHASH;
- for (sym = obj->htab[h]; sym; sym = sym->hash) {
- if (!strcmp(name, sym->name))
- return sym;
- }
- if (!install)
- return NULL;
-
- if ((sym = malloc(sizeof(*sym))) == NULL)
- return NULL;
-
- sym->name = name;
- sym->type = 'U';
- sym->size = 0;
- sym->value = 0;
- sym->hash = obj->htab[h];
- obj->htab[h] = sym;
- sym->next = obj->syms;
- obj->syms = sym;
-
- return sym;
-}
--- a/src/libmach/objnew.c
+++ b/src/libmach/objnew.c
@@ -21,12 +21,6 @@
return NULL;
obj->type = type;
- obj->syms = NULL;
- obj->secs = NULL;
- obj->nsyms = 0;
- obj->nsecs = 0;
- memset(obj->htab, 0, sizeof(obj->htab));
-
ops = objops[fmt];
obj->ops = ops;
--- a/src/libmach/objtype.c
+++ b/src/libmach/objtype.c
@@ -22,7 +22,7 @@
for (opsp = objops; ops = *opsp; ++opsp) {
if ((*ops->probe)(buf, name) < 0)
continue;
- return n;
+ return opsp - objops;
}
return -1;
--- /dev/null
+++ b/src/libmach/readobj.c
@@ -1,0 +1,15 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+int
+readobj(Obj *obj, FILE *fp)
+{
+ long off;
+
+ if ((off = ftell(fp)) == EOF)
+ return -1;
+ obj->pos = off;
+
+ return (*obj->ops->read)(obj, fp);
+}
--- a/tests/nm/execute/Makefile
+++ b/tests/nm/execute/Makefile
@@ -1,13 +1,12 @@
.POSIX:
+ROOT=../../..
-ROOT=$(PROJECTDIR)/root
-
OUT = z80.out
all: tests
tests: $(OUT)
- @PATH=$(ROOT)/bin:$$PATH chktest.sh
+ @PATH=$(ROOT)/bin:$$PATH:. chktest.sh
z80.out: master.s
z80-unknown-coff-as -o $@ master.s