ref: 1d08a435776de0dd4f776cca9f2643570972809e
parent: 90f952cb3dee893681a64e5f08844785e6b30ea8
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Feb 6 03:04:15 EST 2019
[libmach] Split object.c and coff32.c
--- a/src/libc/Makefile
+++ b/src/libc/Makefile
@@ -18,7 +18,7 @@
$(DIRS): FORCE
+@cd $@ && $(MAKE)
-objlst.mk: FORCE
+objlst.mk: $(DIRS) FORCE
mklst $@
clean:
--- /dev/null
+++ b/src/libmach/.gitignore
@@ -1,0 +1,8 @@
+objlst.mk
+del.c
+index.c
+new.c
+probe.c
+read.c
+strip.c
+write.c
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -3,17 +3,59 @@
include $(PROJECTDIR)/scripts/rules.mk
TARGET = $(LIBDIR)/libmach.a
-OBJS = object.o \
+
+OBJS = addr2line.o \
archive.o \
- pack.o \
- unpack.o \
- artraverse.o \
+ arindex.o \
armember.o \
- objfmt.o \
- coff32.o \
+ artraverse.o \
coffelf32.o \
+ objdel.o \
+ objlookup.o \
+ objnew.o \
+ objpos.o \
+ objread.o \
+ objreset.o \
+ objsize.o \
+ objstrip.o \
+ objtraverse.o \
+ objtype.o \
+ objwrite.o \
+ objfree.o \
+ pack.o \
+ unpack.o \
+ index.o \
+ new.o \
+ read.o \
+ del.o \
+ strip.o \
+ probe.o \
+ write.o \
-all: $(TARGET)
-$(TARGET): $(OBJS)
- mklib -o $@ $?
+DIRS = coff32
+
+TBLS = index.c \
+ new.c \
+ read.c \
+ del.c \
+ strip.c \
+ probe.c \
+ write.c \
+
+
+all: $(OBJS) $(DIRS) objlst.mk
+ +@$(MAKE) -f Makefile.mach
+
+$(DIRS): FORCE
+ +@cd $@ && $(MAKE)
+
+$(TBLS): formats.lst
+ mktbl -t `echo $@ | sed 's/\.c//'` -o $@
+
+objlst.mk: $(OBJS) $(DIRS)
+ mklst $@
+
+clean:
+ $(FORALL)
+ rm -f $(TBLS) objlst.mk
--- /dev/null
+++ b/src/libmach/Makefile.mach
@@ -1,0 +1,11 @@
+.POSIX:
+PROJECTDIR =../..
+include $(PROJECTDIR)/scripts/rules.mk
+include objlst.mk
+
+TARGET = $(LIBDIR)/libmach.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ mklib -o $@ $?
--- /dev/null
+++ b/src/libmach/addr2line.c
@@ -1,0 +1,10 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+int
+addr2line(Obj *obj, unsigned long long addr, char *fname, int *line)
+{
+ /* TODO */
+ return -1;
+}
--- /dev/null
+++ b/src/libmach/arindex.c
@@ -1,0 +1,20 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern indexfun_t indexv[];
+
+long
+arindex(int type, long nsyms, Symdef *head, FILE *fp)
+{
+ int fmt;
+ indexfun_t fn;
+
+ fmt = FORMAT(type);
+ if (fmt >= NFORMATS)
+ return -1;
+ fn = indexv[fmt];
+ return (*fn)(type, nsyms, head, fp);
+}
--- a/src/libmach/coff32.c
+++ /dev/null
@@ -1,784 +1,0 @@
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/coff32/filehdr.h>
-#include <scc/coff32/aouthdr.h>
-#include <scc/coff32/scnhdr.h>
-#include <scc/coff32/syms.h>
-#include <scc/coff32/reloc.h>
-#include <scc/coff32/linenum.h>
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-typedef struct coff32 Coff32;
-
-struct arch {
- char *name;
- unsigned char magic[2];
- int type;
-};
-
-struct coff32 {
- FILHDR hdr;
- AOUTHDR *aout;
- SCNHDR *scns;
- SYMENT *ents;
- RELOC **rels;
- LINENO **lines;
- char *strtbl;
- unsigned long strsiz;
-};
-
-static struct arch archs[] = {
- "coff32-i386", "\x4c\x01", OBJ(COFF32, ARCH386, LITTLE_ENDIAN),
- "coff32-z80", "\x5a\x80", OBJ(COFF32, ARCHZ80, LITTLE_ENDIAN),
- NULL,
-};
-
-static void
-pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
-{
- int n;
-
- n = pack(order,
- buf,
- "sslllss",
- hdr->f_magic,
- hdr->f_nscns,
- hdr->f_timdat,
- hdr->f_symptr,
- hdr->f_nsyms,
- hdr->f_opthdr,
- hdr->f_flags);
- assert(n == FILHSZ);
-}
-
-static void
-unpack_hdr(int order, unsigned char *buf, FILHDR *hdr)
-{
- int n;
-
- n = unpack(order,
- buf,
- "sslllss",
- &hdr->f_magic,
- &hdr->f_nscns,
- &hdr->f_timdat,
- &hdr->f_symptr,
- &hdr->f_nsyms,
- &hdr->f_opthdr,
- &hdr->f_flags);
- assert(n == FILHSZ);
-}
-
-static void
-pack_scn(int order, unsigned char *buf, SCNHDR *scn)
-{
- int n;
-
- n = pack(order,
- buf,
- "'8llllllssl",
- scn->s_name,
- scn->s_paddr,
- scn->s_vaddr,
- scn->s_size,
- scn->s_scnptr,
- scn->s_relptr,
- scn->s_lnnoptr,
- scn->s_nrelloc,
- scn->s_nlnno,
- scn->s_flags);
- assert(n == SCNHSZ);
-}
-
-static void
-unpack_scn(int order, unsigned char *buf, SCNHDR *scn)
-{
- int n;
-
- n = unpack(order,
- buf,
- "'8llllllssl",
- scn->s_name,
- &scn->s_paddr,
- &scn->s_vaddr,
- &scn->s_size,
- &scn->s_scnptr,
- &scn->s_relptr,
- &scn->s_lnnoptr,
- &scn->s_nrelloc,
- &scn->s_nlnno,
- &scn->s_flags);
- assert(n == SCNHSZ);
-}
-
-static void
-pack_ent(int order, unsigned char *buf, SYMENT *ent)
-{
- int n;
- char *s;
-
- /* TODO: What happens with the union? */
-
- n = pack(order,
- buf,
- "'8lsscc",
- ent->n_name,
- &ent->n_value,
- &ent->n_scnum,
- &ent->n_type,
- &ent->n_sclass,
- &ent->n_numaux);
- assert(n == SYMESZ);
-}
-
-static void
-unpack_ent(int order, unsigned char *buf, SYMENT *ent)
-{
- int n;
- char *s;
-
- n = unpack(order,
- buf,
- "'8lsscc",
- ent->n_name,
- &ent->n_value,
- &ent->n_scnum,
- &ent->n_type,
- &ent->n_sclass,
- &ent->n_numaux);
- assert(n == SYMESZ);
-
- s = ent->n_name;
- if (!s[0] && !s[1] && !s[2] && !s[3])
- unpack(order, "ll", buf, &ent->n_zeroes, &ent->n_offset);
-}
-
-static void
-pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
-{
- int n;
-
- n = unpack(order,
- buf,
- "ssllllll",
- aout->magic,
- aout->vstamp,
- aout->tsize,
- aout->dsize,
- aout->bsize,
- aout->entry,
- aout->text_start,
- aout->data_start);
- assert(n == AOUTSZ);
-}
-
-static void
-unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)
-{
- int n;
-
- n = unpack(order,
- buf,
- "ssllllll",
- &aout->magic,
- &aout->vstamp,
- &aout->tsize,
- &aout->dsize,
- &aout->bsize,
- &aout->entry,
- &aout->text_start,
- &aout->data_start);
- assert(n == AOUTSZ);
-}
-
-static void
-unpack_reloc(int order, unsigned char *buf, RELOC *rel)
-{
- int n;
-
- n = unpack(order,
- buf,
- "lls",
- &rel->r_vaddr,
- &rel->r_symndx,
- &rel->r_type);
- assert(n == RELSZ);
-}
-
-static void
-pack_reloc(int order, unsigned char *buf, RELOC *rel)
-{
- int n;
-
- n = pack(order,
- buf,
- "lls",
- rel->r_vaddr,
- rel->r_symndx,
- rel->r_type);
- assert(n == RELSZ);
-}
-
-static void
-unpack_line(int order, unsigned char *buf, LINENO *lp)
-{
- int n;
-
- n = unpack(order,
- buf,
- "lls",
- &lp->l_symndx,
- &lp->l_paddr,
- &lp->l_lnno);
- assert(n == LINESZ);
-}
-
-static void
-pack_line(int order, unsigned char *buf, LINENO *lp)
-{
- int n;
-
- n = pack(order,
- buf,
- "lls",
- lp->l_symndx,
- lp->l_paddr,
- lp->l_lnno);
- assert(n == LINESZ);
-}
-
-static int
-probe(unsigned char *buf, char **name)
-{
- struct arch *ap;
-
- for (ap = archs; ap->name; ap++) {
- if (ap->magic[0] == buf[0] && ap->magic[1] == buf[1]) {
- if (name)
- *name = ap->name;
- return ap->type;
- }
- }
- return -1;
-}
-
-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
-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)
- 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 int
-loadsyms(Obj *obj)
-{
- int t;
- long i;
- char *s;
- Symbol *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 0;
-
- if ((s = symname(coff, ent)) == NULL)
- return 0;
-
- if ((sym = objlookup(obj, s)) == NULL)
- return 0;
-
- sym->type = t;
- sym->value = ent->n_value;
- sym->size = (sym->type == 'C') ? ent->n_value : 0;
- }
-
- return 1;
-}
-
-static int
-readscns(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- SCNHDR *scn;
- long i;
- unsigned char buf[SCNHSZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- if (hdr->f_nscns > 0) {
- scn = calloc(hdr->f_nscns, sizeof(*scn));
- if (!scn)
- return 0;
- coff->scns = scn;
- }
- if (fseek(fp, hdr->f_opthdr, SEEK_CUR) < 0)
- return 0;
- for (i = 0; i < hdr->f_nscns; i++) {
- if (fread(buf, SCNHSZ, 1, fp) < 0)
- return 0;
- unpack_scn(ORDER(obj->type), buf, &scn[i]);
- }
-
- return 1;
-}
-
-static int
-readents(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- SYMENT *ent;
- long i;
- unsigned char buf[SYMESZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- if (hdr->f_nsyms == 0)
- return 1;
-
- ent = calloc(hdr->f_nsyms, sizeof(*ent));
- if (!ent)
- return 0;
- coff->ents = ent;
-
- if (!objpos(obj, fp, hdr->f_symptr))
- return 0;
- for (i = 0; i < hdr->f_nsyms; i++) {
- if (fread(buf, SYMESZ, 1, fp) != 1)
- return 0;
- unpack_ent(ORDER(obj->type), buf, &ent[i]);
- }
-
- return 1;
-}
-
-static int
-readreloc(Obj *obj, FILE *fp)
-{
- int i, j;
- RELOC **rels, *rp;
- SCNHDR *scn;
- FILHDR *hdr;
- struct coff32 *coff;
- unsigned char buf[RELSZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- rels = calloc(obj->nsecs, sizeof(*rels));
- if (!rels)
- return 0;
- coff->rels = rels;
-
- for (i = 0; i < hdr->f_nscns; i++) {
- scn = &coff->scns[i];
- if (scn->s_nlnno == 0)
- continue;
-
- if (!objpos(obj, fp, scn->s_relptr))
- return 0;
-
- rp = calloc(scn->s_nrelloc, sizeof(RELOC));
- if (!rp)
- return 0;
- rels[i] = rp;
-
- for (j = 0; j < scn->s_nrelloc; j++) {
- if (fread(buf, RELSZ, 1, fp) != 1)
- return 0;
- unpack_reloc(ORDER(obj->type), buf, &rp[i]);
- }
- }
-
- return 1;
-}
-
-static int
-readlines(Obj *obj, FILE *fp)
-{
- int i,j;
- LINENO **lines, *lp;
- FILHDR *hdr;
- SCNHDR *scn;
- struct coff32 *coff;
- unsigned char buf[LINESZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- lines = calloc(sizeof(lp), hdr->f_nscns);
- if (!lines)
- return 0;
- coff->lines = lines;
-
- for (i = 0; i < hdr->f_nscns; i++) {
- scn = &coff->scns[i];
- if (scn->s_nlnno == 0)
- continue;
-
- lp = calloc(sizeof(*lp), scn->s_nlnno);
- if (!lp)
- return 0;
- lines[i] = lp;
-
- for (j = 0; j < scn->s_nlnno; j++) {
- if (!objpos(obj, fp, scn->s_lnnoptr))
- return 0;
- if (fread(buf, LINESZ, 1, fp) == 1)
- return 0;
- unpack_line(ORDER(obj->type), buf, &lp[j]);
- }
- }
-
- return 1;
-}
-
-static int
-readstr(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- long siz;
- char *str;
- unsigned char buf[10];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- if (hdr->f_nsyms == 0)
- return 1;
-
- if (fread(buf, 4, 1, fp) != 1)
- return 0;
- unpack(ORDER(obj->type), buf, "l", &siz);
- siz -= 4;
- if (siz < 0)
- return 0;
- if (siz > 0) {
- if (siz > SIZE_MAX)
- return 0;
- str = malloc(siz);
- if (!str)
- return 0;
- coff->strtbl = str;
- coff->strsiz = siz;
-
- if (fread(str, siz, 1, fp) != 1)
- return 0;
- }
- return 1;
-}
-
-static int
-readhdr(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- unsigned char buf[FILHSZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- if (fread(buf, FILHSZ, 1, fp) != 1)
- return 0;
- unpack_hdr(ORDER(obj->type), buf, hdr);
-
- return 1;
-}
-
-static int
-loadsections(Obj *obj, FILE *fp)
-{
- size_t len;
- unsigned sflags, type;
- unsigned long flags;
- FILHDR *hdr;
- struct coff32 *coff;
- SCNHDR *scn;
- Section *secs, *sp;
-
- coff = obj->data;
- hdr = &coff->hdr;
- scn = coff->scns;
-
- secs = malloc(sizeof(Section) * hdr->f_nscns);
- if (!secs)
- return 0;
- obj->sections = secs;
-
- for (sp = secs; sp < &secs[hdr->f_nscns]; sp++) {
- 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;
-
- len = strlen(scn->s_name) + 1;
- if ((sp->name = malloc(len)) == NULL)
- return 0;
-
- memcpy(sp->name, scn->s_name, len);
- sp->fp = fp;
- sp->offset = scn->s_scnptr;
- sp->size = scn->s_size;
- sp->type = type;
- obj->nsecs++;
- }
- return 1;
-}
-
-static int
-readaout(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- unsigned char buf[AOUTSZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- if (hdr->f_opthdr == 0)
- return 1;
-
- 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);
-
- return 1;
-}
-
-static int
-read(Obj *obj, FILE *fp)
-{
- /* TODO: Add validation of the different fields */
- if (fgetpos(fp, &obj->pos))
- goto error;
- if (!readhdr(obj, fp))
- goto error;
- if (!readaout(obj, fp))
- goto error;
- if (!readscns(obj, fp))
- goto error;
- if (!readents(obj, fp))
- goto error;
- if (!readstr(obj, fp))
- goto error;
- if (!readreloc(obj, fp))
- goto error;
- if (!readlines(obj, fp))
- goto error;
- if (!loadsyms(obj))
- goto error;
- if (!loadsections(obj, fp))
- goto error;
- return 0;
-
-error:
- objreset(obj);
- return -1;
-}
-
-static int
-writehdr(Obj *obj, FILE *fp)
-{
- FILHDR *hdr;
- struct coff32 *coff;
- unsigned char buf[FILHSZ];
-
- coff = obj->data;
- hdr = &coff->hdr;
-
- pack_hdr(ORDER(obj->type), buf, hdr);
- if (fwrite(buf, FILHSZ, 1, fp) != 1)
- return 0;
-
- return 1;
-}
-
-static int
-writescns(Obj *obj, FILE *fp)
-{
- /* TODO */
-}
-
-static int
-writeents(Obj *obj, FILE *fp)
-{
- /* TODO */
-}
-
-static int
-writestr(Obj *obj, FILE *fp)
-{
- /* TODO */
-}
-
-static int
-write(Obj *obj, FILE *fp)
-{
- struct coff32 *coff;
-
- coff = obj->data;
- coff->strsiz = 0;
- free(coff->strtbl);
-
- if (!writehdr(obj, fp))
- return -1;
- if (!writescns(obj, fp))
- return -1;
- if (!writeents(obj, fp))
- return -1;
- if (!writestr(obj, fp))
- return -1;
-
- return 0;
-}
-
-static void
-del(Obj *obj)
-{
- struct coff32 *coff = obj->data;
-
- if (coff) {
- free(coff->scns);
- free(coff->ents);
- free(coff->strtbl);
- }
- free(obj->data);
- obj->data = NULL;
-}
-
-static int
-new(Obj *obj)
-{
- struct coff32 *coff;
-
- if ((coff = calloc(1, sizeof(*coff))) == NULL)
- return -1;
- obj->data = coff;
- return 0;
-}
-
-static void
-strip(Obj *obj)
-{
- struct coff32 *coff = obj->data;
- FILHDR *hdr;
-
- hdr = &coff->hdr;
- free(coff->ents);
- coff->ents = NULL;
- hdr->f_nsyms = 0;
- hdr->f_symptr = 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,
- .del = del,
- .read = read,
- .write = write,
- .strip = strip,
- .index = mkindex,
-};
--- /dev/null
+++ b/src/libmach/coff32/Makefile
@@ -1,0 +1,13 @@
+.POSIX:
+PROJECTDIR =../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = coff32del.o \
+ coff32index.o \
+ coff32new.o \
+ coff32probe.o \
+ coff32read.o \
+ coff32strip.o \
+ coff32write.o \
+
+all: $(OBJS)
--- /dev/null
+++ b/src/libmach/coff32/coff-help.h
@@ -1,0 +1,576 @@
+/*
+******************************************************************
+** 29K COFF Declarations **
+** **
+** **
+** This file contains the declarations required to define **
+** the COFF format as proposed for use by AMD for the 29K **
+** family of RISC microprocessors. **
+** **
+** No attempt is made here to describe in detail those portions **
+** of COFF which have not been modified or extended. Pertinent **
+** #define's and struct's are included for completeness. Those **
+** declarations are distributed in several System V headers. **
+** **
+** For a better and more complete description of COFF with **
+** general and 29K Family specific clarifications, see the **
+** AMD's "Programmer's Guide to the Common Object File Format **
+** (COFF) for the Am29000" Application Note, order number 11963.**
+** **
+** For non-29K-Family specific COFF information, consult AT&T **
+** UNIX System V Release 3, Programmer's Guide, Chapter 11 **
+** (Manual 307-225, Issue 1). **
+** **
+** **
+** Revision history: **
+** **
+** 0.01 JG - first published **
+** 0.02 JG - added relocation type R_IFAR and renumbered **
+** 0.03 RC - COFF spec now compiles without error **
+** 0.04 RC - removed R_IPAIR and R_IFAR and renumbered **
+** 0.05 RC - added R_HWORD relocation type **
+** 0.06 RC - section types **
+** changed value of STYP_BSSREG **
+** replaced STYP_RDATA and STYP_IDATA **
+** with STYP_LIT, STYP_ABS, and STYP_ENVIR **
+** - relocation types **
+** added R_IABS **
+** replaced R_IBYTE with R_BYTE and renumbered **
+** - changed comments and removed comments **
+** 0.07 RC - relocation types **
+** Added R_IHCONST to support relocation offsets **
+** for CONSTH instruction. Added commentary, **
+** and renumbered to make room for R_IHCONST, **
+** putting the (as yet unused) global reloc **
+** types at the end. **
+** - bug fix (typo) **
+** Added slash to terminate comment field on **
+** C_EXT so now C_STAT is defined. **
+** 0.08 RC - official magic numbers assigned by AT&T. **
+** 0.09 RC - support multiple address spaces by adding magic **
+** a.out header numbers SASMAGIC and MASMAGIC. **
+** 0.10 RC - No changes. Just added the comments below and **
+** corrected comments on tsize, dsize, and bsize. **
+** - All portions of the COFF file described as C **
+** structs must use Host Endian byte ordering. **
+** Files created on a machine with a byte **
+** ordering different from the host may be **
+** converted using the UNIX conv(1) command. **
+** - Assemblers and compilers must create section **
+** headers for .text, .data, and .bss (in that **
+** order) even if they are 0 length. **
+** - tsize, dsize, and bsize are the size of .text, **
+** .data, and .bss respectively. Other sections **
+** of type STYP_TEXT, STYP_DATA, and STYP_BSS **
+** are not included in the byte count. **
+** - Assemblers and compilers must create output **
+** sections to the exact byte length (and not **
+** round them up). The linker will take care **
+** of rounding. **
+** 2.1.01 - Added C_STARTOF storage class for support of **
+** assembler $startof(sect_name) and **
+** $sizeof(sect_name) operators. **
+** 2.1.02 - Added a few more defines for completeness. **
+** 2.1.03 - Added more magic numbers for completeness. **
+******************************************************************
+*/
+
+/*
+** Overall structure of a COFF file
+*/
+
+/*
+ *--------------------------------*
+ | File Header |
+ ----------------------------------
+ | Optional Information |
+ ----------------------------------
+ | Section 1 Header |
+ ----------------------------------
+ | ... |
+ ----------------------------------
+ | Section n Header |
+ ----------------------------------
+ | Raw Data for Section 1 |
+ ----------------------------------
+ | ... |
+ ----------------------------------
+ | Raw Data for Section n |
+ ----------------------------------
+ | Relocation Info for Section 1 |
+ ----------------------------------
+ | ... |
+ ----------------------------------
+ | Relocation Info for Section n |
+ ----------------------------------
+ | Line Numbers for Section 1 |
+ ----------------------------------
+ | ... |
+ ----------------------------------
+ | Line Numbers for Section n |
+ ----------------------------------
+ | Symbol Table |
+ ----------------------------------
+ | String Table |
+ *--------------------------------*
+*/
+
+/****************************************************************/
+
+
+/*
+** File Header and related definitions
+*/
+
+struct filehdr
+{
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ long f_symptr; /* file pointer to symtab */
+ long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+};
+
+#define FILHDR struct filehdr
+#define FILHSZ sizeof (FILHDR)
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Magic numbers currently known to us,
+** Plus 29K magic numbers assigned by AT&T.
+*/
+
+#define M68MAGIC 0210
+#define M68TVMAGIC 0211
+#define B16MAGIC 0502
+#define BTVMAGIC 0503
+#define IAPX16 0504
+#define IAPX16TV 0505
+#define IAPX20 0506
+#define IAPX20TV 0507
+#define X86MAGIC 0510
+#define XTVMAGIC 0511
+#define I286SMAGIC 0512
+#define I386MAGIC 0514
+#define MC68MAGIC 0520
+#define MC68KWRMAGIC 0520 /* 68K writeable text sections */
+#define MC68TVMAGIC 0521
+#define MC68KPGMAGIC 0522 /* 68K demand paged text (shared with i286) */
+#define I286LMAGIC 0522 /* i286 (shared with 68K) */
+/* 0524 * reserved for NSC */
+/* 0525 * reserved for NSC */
+/* 0544 * reserved for Zilog */
+/* 0545 * reserved for Zilog */
+#define N3BMAGIC 0550 /* 3B20S executable, no TV */
+#define NTVMAGIC 0551 /* 3B20 executable with TV */
+#define FBOMAGIC 0560 /* WE*-32 (Forward Byte Ordering) */
+#define WE32MAGIC 0560 /* WE 32000, no TV */
+#define MTVMAGIC 0561 /* WE 32000 with TV */
+#define RBOMAGIC 0562 /* WE-32 (Reverse Byte Ordering) */
+#define VAXWRMAGIC 0570 /* VAX-11/750 and VAX-11/780 */
+ /* (writable text sections) */
+#define VAXROMAGIC 0575 /* VAX-11/750 and VAX-11780 */
+ /* (read-only text sections) */
+#define U370WRMAGIC 0530 /* IBM 370 (writable text sections) */
+#define AMDWRMAGIC 0531 /* Amdahl 470/580 writable text sections */
+#define AMDROMAGIC 0534 /* Amdahl 470/580 read only sharable text */
+#define U370ROMAGIC 0535 /* IBM 370 (read-only sharable text sections) */
+
+#define SIPFBOMAGIC 0572 /* 29K Family (Byte 0 is MSB - Big Endian) */
+#define SIPRBOMAGIC 0573 /* 29K Family (Byte 0 is LSB - Little Endian) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** File header flags currently known to us.
+**
+** Am29000 will use the F_AR32WR and F_AR32W flags to indicate
+** the byte ordering in the file.
+*/
+
+#define F_RELFLG 00001 /* Relocation information stripped */
+ /* from the file. */
+#define F_EXEC 00002 /* File is executable (i.e. no */
+ /* unresolved external references). */
+#define F_LNNO 00004 /* Line numbers stripped from */
+ /* the file. */
+#define F_LSYMS 00010 /* Local symbols stripped from */
+ /* the file. */
+#define F_MINMAL 00020 /* Not used by UNIX. */
+#define F_UPDATE 00040 /* Not used by UNIX. */
+#define F_SWABD 00100 /* Not used by UNIX. */
+#define F_AR16WR 00200 /* File has the byte ordering used */
+ /* by the PDP*-11/70 processor. */
+#define F_AR32WR 00400 /* File has 32 bits per word, */
+ /* least significant byte first. */
+#define F_AR32W 01000 /* File has 32 bits per word, */
+ /* most significant byte first. */
+#define F_PATCH 02000 /* Not used by UNIX. */
+#define F_BM32BRST 0010000 /* 32100 required; has RESTORE work-around. */
+#define F_BM32B 0020000 /* 32100 required. */
+#define F_BM32MAU 0040000 /* MAU required. */
+#define F_BM32ID 0160000 /* WE 32000 processor ID field. */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Optional (a.out) header
+*/
+
+typedef struct aouthdr
+{
+ short magic; /* magic number */
+ short vstamp; /* version stamp */
+ long tsize; /* size of .text in bytes */
+ long dsize; /* size of .data (initialized data) */
+ long bsize; /* size of .bss (uninitialized data) */
+ long entry; /* entry point */
+ long text_start; /* base of text used for this file */
+ long data_start; /* base of data used for this file */
+} AOUTHDR;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Magic a.out header numbers for cross development (non-UNIX),
+** support of separate I and D address spaces.
+*/
+
+#define SASMAGIC 010000 /* Single Address Space */
+#define MASMAGIC 020000 /* Multiple (separate I & D) Address Spaces */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Section header and related definitions
+*/
+
+struct scnhdr
+{
+ char s_name[8]; /* section name */
+ long s_paddr; /* physical address */
+ long s_vaddr; /* virtual address */
+ long s_size; /* section size */
+ long s_scnptr; /* file ptr to raw data for section */
+ long s_relptr; /* file ptr to relocation */
+ long s_lnnoptr; /* file ptr to line numbers */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of line number entries */
+ long s_flags; /* flags */
+};
+
+#define SCNHDR struct scnhdr
+#define SCNHSZ sizeof (SCNHDR)
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Section types - with additional section type for global
+** registers which will be relocatable for the Am29000.
+**
+** In instances where it is necessary for a linker to produce an
+** output file which contains text or data not based at virtual
+** address 0, e.g. for a ROM, then the linker should accept
+** address base information as command input and use PAD sections
+** to skip over unused addresses.
+*/
+
+#define STYP_REG 0x00 /* Regular section (allocated, */
+ /* relocated, loaded) */
+#define STYP_DSECT 0x01 /* Dummy section (not allocated, */
+ /* relocated, not loaded) */
+#define STYP_NOLOAD 0x02 /* Noload section (allocated, */
+ /* relocated, not loaded) */
+#define STYP_GROUP 0x04 /* Grouped section (formed from */
+ /* input sections) */
+#define STYP_PAD 0x08 /* Padded section (not allocated, */
+ /* not relocated, loaded) */
+#define STYP_COPY 0x10 /* Copy section (for a decision */
+ /* function used in updating fields; */
+ /* not allocated, not relocated, */
+ /* loaded, relocation and line */
+ /* number entries processed */
+ /* normally) */
+#define STYP_TEXT 0x20 /* Section contains executable text */
+#define STYP_DATA 0x40 /* Section contains initialized data */
+#define STYP_BSS 0x80 /* Section contains only uninitialized data */
+#define STYP_INFO 0x200 /* Comment section (not allocated, */
+ /* not relocated, not loaded) */
+#define STYP_OVER 0x400 /* Overlay section (relocated, */
+ /* not allocated, not loaded) */
+#define STYP_LIB 0x800 /* For .lib section (like STYP_INFO) */
+
+#define STYP_BSSREG 0x1200 /* Global register area (like STYP_INFO) */
+#define STYP_ENVIR 0x2200 /* Environment (like STYP_INFO) */
+#define STYP_ABS 0x4000 /* Absolute (allocated, not reloc, loaded) */
+#define STYP_LIT 0x8020 /* Literal data (like STYP_TEXT) */
+
+/*
+NOTE: The use of STYP_BSSREG for relocation is not yet defined.
+*/
+
+/*--------------------------------------------------------------*/
+
+/*
+** Relocation information declaration and related definitions
+*/
+
+struct reloc
+{
+ long r_vaddr; /* (virtual) address of reference */
+ long r_symndx; /* index into symbol table */
+ unsigned short r_type; /* relocation type */
+};
+
+#define RELOC struct reloc
+#define RELSZ 10 /* sizeof (RELOC) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Relocation types for the Am29000
+*/
+
+#define R_ABS 0 /* reference is absolute */
+
+#define R_IREL 030 /* instruction relative (jmp/call) */
+#define R_IABS 031 /* instruction absolute (jmp/call) */
+#define R_ILOHALF 032 /* instruction low half (const) */
+#define R_IHIHALF 033 /* instruction high half (consth) part 1 */
+#define R_IHCONST 034 /* instruction high half (consth) part 2 */
+ /* constant offset of R_IHIHALF relocation */
+#define R_BYTE 035 /* relocatable byte value */
+#define R_HWORD 036 /* relocatable halfword value */
+#define R_WORD 037 /* relocatable word value */
+
+#define R_IGLBLRC 040 /* instruction global register RC */
+#define R_IGLBLRA 041 /* instruction global register RA */
+#define R_IGLBLRB 042 /* instruction global register RB */
+
+/*
+NOTE:
+All the "I" forms refer to Am29000 instruction formats. The linker is
+expected to know how the numeric information is split and/or aligned
+within the instruction word(s). R_BYTE works for instructions, too.
+
+If the parameter to a CONSTH instruction is a relocatable type, two
+relocation records are written. The first has an r_type of R_IHIHALF
+(33 octal) and a normal r_vaddr and r_symndx. The second relocation
+record has an r_type of R_IHCONST (34 octal), a normal r_vaddr (which
+is redundant), and an r_symndx containing the 32-bit constant offset
+to the relocation instead of the actual symbol table index. This
+second record is always written, even if the constant offset is zero.
+The constant fields of the instruction are set to zero.
+*/
+
+/*--------------------------------------------------------------*/
+
+/*
+** Line number entry declaration and related definitions
+*/
+
+struct lineno
+{
+ union
+ {
+ long l_symndx; /* sym table index of function name */
+ long l_paddr; /* (physical) address of line number */
+ } l_addr;
+ unsigned short l_lnno; /* line number */
+};
+
+#define LINENO struct lineno
+#define LINESZ 6 /* sizeof (LINENO) */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Symbol entry declaration and related definitions
+*/
+
+#define SYMNMLEN 8 /* Number of characters in a symbol name */
+
+struct syment
+{
+ union
+ {
+ char _n_name [SYMNMLEN]; /* symbol name */
+ struct
+ {
+ long _n_zeroes; /* symbol name */
+ long _n_offset; /* offset into string table */
+ } _n_n;
+ char *_n_nptr[2]; /* allows for overlaying */
+ } _n;
+#ifndef pdp11
+ unsigned
+#endif
+ long n_value; /* value of symbol */
+ short n_scnum; /* section number */
+ unsigned short n_type; /* type and derived type */
+ char n_sclass; /* storage class */
+ char n_numaux; /* number of aux entries */
+};
+
+#define n_name _n._n_name
+#define n_nptr _n._n_nptr[1]
+#define n_zeroes _n._n_n._n_zeroes
+#define n_offset _n._n_n._n_offset
+
+#define SYMENT struct syment
+#define SYMESZ 18
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Storage class definitions - new classes for global registers.
+*/
+
+#define C_EFCN -1 /* physical end of a function */
+#define C_NULL 0 /* - */
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* (local) register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_UNSTATIC 14 /* uninitialized static */
+#define C_USTATIC 14 /* uninitialized static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+
+#define C_GLBLREG 19 /* global register */
+#define C_EXTREG 20 /* external global register */
+#define C_DEFREG 21 /* ext. def. of global register */
+#define C_STARTOF 22 /* as29 $SIZEOF and $STARTOF symbols */
+
+
+#define C_BLOCK 100 /* beginning and end of block */
+#define C_FCN 101 /* beginning and end of function */
+#define C_EOS 102 /* end of structure */
+#define C_FILE 103 /* file name */
+#define C_LINE 104 /* used only by utility programs */
+#define C_ALIAS 105 /* duplicated tag */
+#define C_HIDDEN 106 /* like static, used to avoid name */
+ /* conflicts */
+#define C_SHADOW 107 /* shadow symbol */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Special section number definitions used in symbol entries.
+** (Section numbers 1-65535 are used to indicate the section
+** where the symbol was defined.)
+*/
+
+#define N_DEBUG -2 /* special symbolic debugging symbol */
+#define N_ABS -1 /* absolute symbol */
+#define N_UNDEF 0 /* undefined external symbol */
+#define N_SCNUM 1-65535 /* section num where symbol defined */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Fundamental symbol types.
+*/
+
+#define T_NULL 0 /* type not assigned */
+#define T_VOID 1 /* void */
+#define T_CHAR 2 /* character */
+#define T_SHORT 3 /* short integer */
+#define T_INT 4 /* integer */
+#define T_LONG 5 /* long integer */
+#define T_FLOAT 6 /* floating point */
+#define T_DOUBLE 7 /* double word */
+#define T_STRUCT 8 /* structure */
+#define T_UNION 9 /* union */
+#define T_ENUM 10 /* enumeration */
+#define T_MOE 11 /* member of enumeration */
+#define T_UCHAR 12 /* unsigned character */
+#define T_USHORT 13 /* unsigned short */
+#define T_UINT 14 /* unsigned integer */
+#define T_ULONG 15 /* unsigned long */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Derived symbol types.
+*/
+
+#define DT_NON 0 /* no derived type */
+#define DT_PTR 1 /* pointer */
+#define DT_FCN 2 /* function */
+#define DT_ARY 3 /* array */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Auxiliary symbol table entry declaration and related
+** definitions.
+*/
+
+#define FILNMLEN 14 /* Number of characters in a file name */
+#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */
+
+union auxent
+{
+ struct
+ {
+ long x_tagndx; /* str, un, or enum tag indx */
+ union
+ {
+ struct
+ {
+ unsigned short x_lnno; /* declaration line number */
+ unsigned short x_size; /* str, union, array size */
+ } x_lnsz;
+ long x_size; /* size of functions */
+ } x_misc;
+ union
+ {
+ struct /* if ISFCN, tag, or .bb */
+ {
+ long x_lnnoptr; /* ptr to fcn line # */
+ long x_endndx; /* entry ndx past block end */
+ } x_fcn;
+ struct /* if ISARY, up to 4 dimen */
+ {
+ unsigned short x_dimen[DIMNUM];
+ } x_ary;
+ } x_fcnary;
+ unsigned short x_tvndx; /* tv index */
+ } x_sym;
+ struct
+ {
+ char x_fname[FILNMLEN];
+ } x_file;
+ struct
+ {
+ long x_scnlen; /* section length */
+ unsigned short x_nreloc; /* number of relocation entries */
+ unsigned short x_nlinno; /* number of line numbers */
+ } x_scn;
+ struct
+ {
+ long x_tvfill; /* tv fill value */
+ unsigned short x_tvlen; /* length of tv */
+ unsigned short x_tvrna[2]; /* tv range */
+ } x_tv; /* info about tv section (in auxent of symbol tv)) */
+};
+
+#define AUXENT union auxent
+#define AUXESZ 18 /* sizeof(AUXENT) */
+
+</pre></div></body></html>
--- /dev/null
+++ b/src/libmach/coff32/coff32.h
@@ -1,0 +1,25 @@
+#include <scc/coff32/filehdr.h>
+#include <scc/coff32/aouthdr.h>
+#include <scc/coff32/scnhdr.h>
+#include <scc/coff32/syms.h>
+#include <scc/coff32/reloc.h>
+#include <scc/coff32/linenum.h>
+
+typedef struct coff32 Coff32;
+
+struct arch {
+ char *name;
+ unsigned char magic[2];
+ int type;
+};
+
+struct coff32 {
+ FILHDR hdr;
+ AOUTHDR *aout;
+ SCNHDR *scns;
+ SYMENT *ents;
+ RELOC **rels;
+ LINENO **lines;
+ char *strtbl;
+ unsigned long strsiz;
+};
--- /dev/null
+++ b/src/libmach/coff32/coff32del.c
@@ -1,0 +1,21 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+void
+coff32del(Obj *obj)
+{
+ struct coff32 *coff = obj->data;
+
+ if (coff) {
+ free(coff->scns);
+ free(coff->ents);
+ free(coff->strtbl);
+ }
+ free(obj->data);
+ obj->data = NULL;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32index.c
@@ -1,0 +1,12 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+long
+coff32index(int type, long nsymbols, Symdef *head, FILE *fp)
+{
+ return coff32idx(BIG_ENDIAN, nsymbols, head, fp);
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32new.c
@@ -1,0 +1,18 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+int
+coff32new(Obj *obj)
+{
+ struct coff32 *coff;
+
+ if ((coff = calloc(1, sizeof(*coff))) == NULL)
+ return -1;
+ obj->data = coff;
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32probe.c
@@ -1,0 +1,27 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+static struct arch archs[] = {
+ "coff32-i386", "\x4c\x01", OBJ(COFF32, ARCH386, LITTLE_ENDIAN),
+ "coff32-z80", "\x5a\x80", OBJ(COFF32, ARCHZ80, LITTLE_ENDIAN),
+ NULL,
+};
+
+int
+coff32probe(unsigned char *buf, char **name)
+{
+ struct arch *ap;
+
+ for (ap = archs; ap->name; ap++) {
+ if (ap->magic[0] == buf[0] && ap->magic[1] == buf[1]) {
+ if (name)
+ *name = ap->name;
+ return ap->type;
+ }
+ }
+ return -1;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32read.c
@@ -1,0 +1,522 @@
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+static void
+unpack_hdr(int order, unsigned char *buf, FILHDR *hdr)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "sslllss",
+ &hdr->f_magic,
+ &hdr->f_nscns,
+ &hdr->f_timdat,
+ &hdr->f_symptr,
+ &hdr->f_nsyms,
+ &hdr->f_opthdr,
+ &hdr->f_flags);
+ assert(n == FILHSZ);
+}
+
+static void
+unpack_line(int order, unsigned char *buf, LINENO *lp)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "lls",
+ &lp->l_symndx,
+ &lp->l_paddr,
+ &lp->l_lnno);
+ assert(n == LINESZ);
+}
+
+static void
+unpack_scn(int order, unsigned char *buf, SCNHDR *scn)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "'8llllllssl",
+ scn->s_name,
+ &scn->s_paddr,
+ &scn->s_vaddr,
+ &scn->s_size,
+ &scn->s_scnptr,
+ &scn->s_relptr,
+ &scn->s_lnnoptr,
+ &scn->s_nrelloc,
+ &scn->s_nlnno,
+ &scn->s_flags);
+ assert(n == SCNHSZ);
+}
+
+static void
+unpack_ent(int order, unsigned char *buf, SYMENT *ent)
+{
+ int n;
+ char *s;
+
+ n = unpack(order,
+ buf,
+ "'8lsscc",
+ ent->n_name,
+ &ent->n_value,
+ &ent->n_scnum,
+ &ent->n_type,
+ &ent->n_sclass,
+ &ent->n_numaux);
+ assert(n == SYMESZ);
+
+ s = ent->n_name;
+ if (!s[0] && !s[1] && !s[2] && !s[3])
+ unpack(order, "ll", buf, &ent->n_zeroes, &ent->n_offset);
+}
+
+static void
+unpack_reloc(int order, unsigned char *buf, RELOC *rel)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "lls",
+ &rel->r_vaddr,
+ &rel->r_symndx,
+ &rel->r_type);
+ assert(n == RELSZ);
+}
+
+static void
+unpack_aout(int order, unsigned char *buf, AOUTHDR *aout)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "ssllllll",
+ &aout->magic,
+ &aout->vstamp,
+ &aout->tsize,
+ &aout->dsize,
+ &aout->bsize,
+ &aout->entry,
+ &aout->text_start,
+ &aout->data_start);
+ assert(n == AOUTSZ);
+}
+
+static int
+readhdr(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ unsigned char buf[FILHSZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ if (fread(buf, FILHSZ, 1, fp) != 1)
+ return 0;
+ unpack_hdr(ORDER(obj->type), buf, hdr);
+
+ return 1;
+}
+
+static int
+loadsections(Obj *obj, FILE *fp)
+{
+ size_t len;
+ unsigned sflags, type;
+ unsigned long flags;
+ FILHDR *hdr;
+ struct coff32 *coff;
+ SCNHDR *scn;
+ Section *secs, *sp;
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+ scn = coff->scns;
+
+ secs = malloc(sizeof(Section) * hdr->f_nscns);
+ if (!secs)
+ return 0;
+ obj->sections = secs;
+
+ for (sp = secs; sp < &secs[hdr->f_nscns]; sp++) {
+ 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;
+
+ len = strlen(scn->s_name) + 1;
+ if ((sp->name = malloc(len)) == NULL)
+ return 0;
+
+ memcpy(sp->name, scn->s_name, len);
+ sp->fp = fp;
+ sp->offset = scn->s_scnptr;
+ sp->size = scn->s_size;
+ sp->type = type;
+ obj->nsecs++;
+ }
+ return 1;
+}
+
+static int
+readstr(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ long siz;
+ char *str;
+ unsigned char buf[10];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ if (hdr->f_nsyms == 0)
+ return 1;
+
+ if (fread(buf, 4, 1, fp) != 1)
+ return 0;
+ unpack(ORDER(obj->type), buf, "l", &siz);
+ siz -= 4;
+ if (siz < 0)
+ return 0;
+ if (siz > 0) {
+ if (siz > SIZE_MAX)
+ return 0;
+ str = malloc(siz);
+ if (!str)
+ return 0;
+ coff->strtbl = str;
+ coff->strsiz = siz;
+
+ if (fread(str, siz, 1, fp) != 1)
+ return 0;
+ }
+ return 1;
+}
+
+static int
+readreloc(Obj *obj, FILE *fp)
+{
+ int i, j;
+ RELOC **rels, *rp;
+ SCNHDR *scn;
+ FILHDR *hdr;
+ struct coff32 *coff;
+ unsigned char buf[RELSZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ rels = calloc(obj->nsecs, sizeof(*rels));
+ if (!rels)
+ return 0;
+ coff->rels = rels;
+
+ for (i = 0; i < hdr->f_nscns; i++) {
+ scn = &coff->scns[i];
+ if (scn->s_nlnno == 0)
+ continue;
+
+ if (!objpos(obj, fp, scn->s_relptr))
+ return 0;
+
+ rp = calloc(scn->s_nrelloc, sizeof(RELOC));
+ if (!rp)
+ return 0;
+ rels[i] = rp;
+
+ for (j = 0; j < scn->s_nrelloc; j++) {
+ if (fread(buf, RELSZ, 1, fp) != 1)
+ return 0;
+ unpack_reloc(ORDER(obj->type), buf, &rp[i]);
+ }
+ }
+
+ return 1;
+}
+
+static int
+readents(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ SYMENT *ent;
+ long i;
+ unsigned char buf[SYMESZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ if (hdr->f_nsyms == 0)
+ return 1;
+
+ ent = calloc(hdr->f_nsyms, sizeof(*ent));
+ if (!ent)
+ return 0;
+ coff->ents = ent;
+
+ if (!objpos(obj, fp, hdr->f_symptr))
+ return 0;
+ for (i = 0; i < hdr->f_nsyms; i++) {
+ if (fread(buf, SYMESZ, 1, fp) != 1)
+ return 0;
+ unpack_ent(ORDER(obj->type), buf, &ent[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)
+ 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
+loadsyms(Obj *obj)
+{
+ int t;
+ long i;
+ char *s;
+ Symbol *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 0;
+
+ if ((s = symname(coff, ent)) == NULL)
+ return 0;
+
+ if ((sym = objlookup(obj, s)) == NULL)
+ return 0;
+
+ sym->type = t;
+ sym->value = ent->n_value;
+ sym->size = (sym->type == 'C') ? ent->n_value : 0;
+ }
+
+ return 1;
+}
+
+static int
+readscns(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ SCNHDR *scn;
+ long i;
+ unsigned char buf[SCNHSZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ if (hdr->f_nscns > 0) {
+ scn = calloc(hdr->f_nscns, sizeof(*scn));
+ if (!scn)
+ return 0;
+ coff->scns = scn;
+ }
+ if (fseek(fp, hdr->f_opthdr, SEEK_CUR) < 0)
+ return 0;
+ for (i = 0; i < hdr->f_nscns; i++) {
+ if (fread(buf, SCNHSZ, 1, fp) < 0)
+ return 0;
+ unpack_scn(ORDER(obj->type), buf, &scn[i]);
+ }
+
+ return 1;
+}
+
+static int
+readlines(Obj *obj, FILE *fp)
+{
+ int i,j;
+ LINENO **lines, *lp;
+ FILHDR *hdr;
+ SCNHDR *scn;
+ struct coff32 *coff;
+ unsigned char buf[LINESZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ lines = calloc(sizeof(lp), hdr->f_nscns);
+ if (!lines)
+ return 0;
+ coff->lines = lines;
+
+ for (i = 0; i < hdr->f_nscns; i++) {
+ scn = &coff->scns[i];
+ if (scn->s_nlnno == 0)
+ continue;
+
+ lp = calloc(sizeof(*lp), scn->s_nlnno);
+ if (!lp)
+ return 0;
+ lines[i] = lp;
+
+ for (j = 0; j < scn->s_nlnno; j++) {
+ if (!objpos(obj, fp, scn->s_lnnoptr))
+ return 0;
+ if (fread(buf, LINESZ, 1, fp) == 1)
+ return 0;
+ unpack_line(ORDER(obj->type), buf, &lp[j]);
+ }
+ }
+
+ return 1;
+}
+
+static int
+readaout(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ unsigned char buf[AOUTSZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ if (hdr->f_opthdr == 0)
+ return 1;
+
+ 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);
+
+ return 1;
+}
+
+int
+coff32read(Obj *obj, FILE *fp)
+{
+ /* TODO: Add validation of the different fields */
+ if (fgetpos(fp, &obj->pos))
+ goto error;
+ if (!readhdr(obj, fp))
+ goto error;
+ if (!readaout(obj, fp))
+ goto error;
+ if (!readscns(obj, fp))
+ goto error;
+ if (!readents(obj, fp))
+ goto error;
+ if (!readstr(obj, fp))
+ goto error;
+ if (!readreloc(obj, fp))
+ goto error;
+ if (!readlines(obj, fp))
+ goto error;
+ if (!loadsyms(obj))
+ goto error;
+ if (!loadsections(obj, fp))
+ goto error;
+ return 0;
+
+error:
+ objreset(obj);
+ return -1;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32strip.c
@@ -1,0 +1,20 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+void
+coff32strip(Obj *obj)
+{
+ struct coff32 *coff = obj->data;
+ FILHDR *hdr;
+
+ hdr = &coff->hdr;
+ free(coff->ents);
+ coff->ents = NULL;
+ hdr->f_nsyms = 0;
+ hdr->f_symptr = 0;
+}
--- /dev/null
+++ b/src/libmach/coff32/coff32write.c
@@ -1,0 +1,172 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "../libmach.h"
+#include "coff32.h"
+
+static void
+pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
+{
+ int n;
+
+ n = pack(order,
+ buf,
+ "sslllss",
+ hdr->f_magic,
+ hdr->f_nscns,
+ hdr->f_timdat,
+ hdr->f_symptr,
+ hdr->f_nsyms,
+ hdr->f_opthdr,
+ hdr->f_flags);
+ assert(n == FILHSZ);
+}
+
+static void
+pack_scn(int order, unsigned char *buf, SCNHDR *scn)
+{
+ int n;
+
+ n = pack(order,
+ buf,
+ "'8llllllssl",
+ scn->s_name,
+ scn->s_paddr,
+ scn->s_vaddr,
+ scn->s_size,
+ scn->s_scnptr,
+ scn->s_relptr,
+ scn->s_lnnoptr,
+ scn->s_nrelloc,
+ scn->s_nlnno,
+ scn->s_flags);
+ assert(n == SCNHSZ);
+}
+
+static void
+pack_ent(int order, unsigned char *buf, SYMENT *ent)
+{
+ int n;
+ char *s;
+
+ /* TODO: What happens with the union? */
+
+ n = pack(order,
+ buf,
+ "'8lsscc",
+ ent->n_name,
+ &ent->n_value,
+ &ent->n_scnum,
+ &ent->n_type,
+ &ent->n_sclass,
+ &ent->n_numaux);
+ assert(n == SYMESZ);
+}
+
+static void
+pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
+{
+ int n;
+
+ n = unpack(order,
+ buf,
+ "ssllllll",
+ aout->magic,
+ aout->vstamp,
+ aout->tsize,
+ aout->dsize,
+ aout->bsize,
+ aout->entry,
+ aout->text_start,
+ aout->data_start);
+ assert(n == AOUTSZ);
+}
+
+static void
+pack_reloc(int order, unsigned char *buf, RELOC *rel)
+{
+ int n;
+
+ n = pack(order,
+ buf,
+ "lls",
+ rel->r_vaddr,
+ rel->r_symndx,
+ rel->r_type);
+ assert(n == RELSZ);
+}
+
+static void
+pack_line(int order, unsigned char *buf, LINENO *lp)
+{
+ int n;
+
+ n = pack(order,
+ buf,
+ "lls",
+ lp->l_symndx,
+ lp->l_paddr,
+ lp->l_lnno);
+ assert(n == LINESZ);
+}
+
+static int
+writehdr(Obj *obj, FILE *fp)
+{
+ FILHDR *hdr;
+ struct coff32 *coff;
+ unsigned char buf[FILHSZ];
+
+ coff = obj->data;
+ hdr = &coff->hdr;
+
+ pack_hdr(ORDER(obj->type), buf, hdr);
+ if (fwrite(buf, FILHSZ, 1, fp) != 1)
+ return 0;
+
+ return 1;
+}
+
+static int
+writescns(Obj *obj, FILE *fp)
+{
+ /* TODO */
+}
+
+static int
+writeents(Obj *obj, FILE *fp)
+{
+ /* TODO */
+}
+
+static int
+writestr(Obj *obj, FILE *fp)
+{
+ /* TODO */
+}
+
+int
+coff32write(Obj *obj, FILE *fp)
+{
+ struct coff32 *coff;
+
+ coff = obj->data;
+ coff->strsiz = 0;
+ free(coff->strtbl);
+
+ if (!writehdr(obj, fp))
+ return -1;
+ if (!writescns(obj, fp))
+ return -1;
+ if (!writeents(obj, fp))
+ return -1;
+ if (!writestr(obj, fp))
+ return -1;
+
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/formats.lst
@@ -1,0 +1,1 @@
+coff32
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -5,10 +5,7 @@
#define ORDER(t) (((t) >> 10) & 0x1f)
enum objformat {
- COFF16,
COFF32,
- ELF32,
- ELF64,
NFORMATS,
};
@@ -26,23 +23,34 @@
BIG_ENDIAN,
};
-struct format {
- int (*probe)(unsigned char *buf, char **name);
- void (*strip)(Obj *obj);
- int (*new)(Obj *obj);
- int (*read)(Obj *obj, FILE *fp);
- int (*write)(Obj *obj, FILE *fp);
- void (*del)(Obj *obj);
- long (*index)(int type, long nsyms, Symdef *def, FILE *fp);
+enum freeflags {
+ FREESYM,
+ FREESECT,
};
+typedef long (*indexfun_t)(int, long, Symdef *, FILE *);
+typedef int (*newfun_t)(Obj *obj);
+typedef int (*readfun_t)(Obj *obj, FILE *fp);
+typedef void (*delfun_t)(Obj *new);
+typedef void (*stripfun_t)(Obj *obj);
+typedef int (*probefun_t)(unsigned char *buf, char **name);
+typedef int (*writefun_t)(Obj *obj, FILE *fp);
+
+/* common functions */
extern int pack(int order, unsigned char *dst, char *fmt, ...);
extern int unpack(int order, unsigned char *src, char *fmt, ...);
extern int objpos(Obj *obj, FILE *fp, long pos);
+extern void objfree(Obj *obj, int what);
/* idx functions */
extern long coff32idx(int order, long nsyms, Symdef *def, FILE *fp);
-/* globals */
-extern struct format *objfmt[];
+/* coff32 functions */
+extern long coff32index(int type, long nsyms, Symdef *head, FILE *fp);
+extern int coff32new(Obj *obj);
+extern void coff32del(Obj *obj);
+extern int coff32read(Obj *obj, FILE *fp);
+extern int coff32write(Obj *obj, FILE *fp);
+extern void coff32strip(Obj *obj);
+extern int coff32probe(unsigned char *buf, char **name);
--- /dev/null
+++ b/src/libmach/mklst
@@ -1,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+rm -f $1
+trap 'r=$?;rm -f $$.tmp;exit $r' HUP EXIT QUIT TERM
+
+(echo OBJS=\\
+ find . -name '*.o' | sed 's/$/\\/') > $$.tmp && mv $$.tmp $1
--- /dev/null
+++ b/src/libmach/mktbl
@@ -1,0 +1,35 @@
+#!/bin/sh
+
+for i
+do
+ case "$1" in
+ -t)
+ target=$2
+ shift 2
+ ;;
+ -o)
+ out=$2
+ shift 2
+ ;;
+ -*)
+ echo mktbl [-t target][-o file] >&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+cat < formats.lst > $out <<EOF
+#include <stdio.h>
+#include <scc/mach.h>
+#include "libmach.h"
+
+${target}fun_t ${target}v[] = {
+`while read i
+ do
+ printf "\t%s," ${i}${target}
+ done`
+};
+EOF
--- /dev/null
+++ b/src/libmach/objdel.c
@@ -1,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+int
+objdel(Obj *obj)
+{
+ if (objreset(obj) < 0)
+ return -1;
+ free(obj);
+}
--- a/src/libmach/object.c
+++ /dev/null
@@ -1,276 +1,0 @@
-static char sccsid[] = "@(#) ./libmach/object.c";
-
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-int
-objtype(FILE *fp, char **name)
-{
- int n, i;
- int (*fn)(unsigned char *, char **);
- struct format **bp, *op;
- fpos_t pos;
- unsigned char buf[NBYTES];
-
- fgetpos(fp, &pos);
- n = fread(buf, NBYTES, 1, fp);
- fsetpos(fp, &pos);
-
- if (n != 1 || ferror(fp))
- return -1;
-
- for (bp = objfmt; bp < &objfmt[NFORMATS]; ++bp) {
- op = *bp;
- if (!op || !op->probe)
- continue;
- n = (*op->probe)(buf, name);
- if (n == -1)
- continue;
- return n;
- }
-
- return -1;
-}
-
-int
-objpos(Obj *obj, FILE *fp, long pos)
-{
- if (fsetpos(fp, &obj->pos))
- return 0;
- if (fseek(fp, pos, SEEK_CUR) < 0)
- return 0;
- return 1;
-}
-
-Symbol *
-objlookup(Obj *obj, char *name)
-{
- unsigned h;
- size_t len;
- char *s;
- Symbol *sym;
-
- h = 0;
- for (s = name; *s; s++)
- h += *s;
- h %= NR_SYMHASH;
-
- for (sym = obj->htab[h]; sym; sym = sym->hash) {
- if (!strcmp(name, sym->name))
- return sym;
- }
-
- if ((sym = malloc(sizeof(*sym))) == NULL)
- return NULL;
- len = strlen(name) + 1;
- if ((s = malloc(len)) == NULL) {
- free(sym);
- return NULL;
- }
- sym->name = memcpy(s, name, len);
- sym->type = 'U';
- sym->size = 0;
- sym->value = 0;
- sym->hash = obj->htab[h];
- obj->htab[h] = sym;
- sym->next = obj->head;
- obj->head = sym;
-
- return sym;
-}
-
-int
-objwrite(Obj *obj, FILE *fp)
-{
- int fmt;
- struct format *op;
-
- fmt = FORMAT(obj->type);
- if (fmt >= NFORMATS)
- return -1;
- op = objfmt[fmt];
- if ((*op->write)(obj, fp) < 0)
- return -1;
- return 0;
-}
-
-int
-objread(Obj *obj, FILE *fp)
-{
- int fmt;
- struct format *op;
-
- fmt = FORMAT(obj->type);
- if (fmt >= NFORMATS)
- return -1;
- op = objfmt[fmt];
- if ((*op->read)(obj, fp) < 0)
- return -1;
- return 0;
-}
-
-Obj *
-objnew(int type)
-{
- Obj *obj;
- int fmt;
- struct format *op;
-
- fmt = FORMAT(type);
- if (fmt >= NFORMATS)
- return NULL;
-
- if ((obj = malloc(sizeof(*obj))) == NULL)
- return NULL;
-
- obj->type = type;
- obj->head = NULL;
- obj->sections = NULL;
- memset(obj->htab, 0, sizeof(obj->htab));
-
- op = objfmt[fmt];
- if ((*op->new)(obj) < 0) {
- free(obj);
- return NULL;
- }
-
- return obj;
-}
-
-int
-objtraverse(Obj *obj, int (*fn)(Symbol *, void *), void *data)
-{
- Symbol *sym;
-
- for (sym = obj->head; sym; sym = sym->next) {
- if (!(*fn)(sym, data))
- return 0;
- }
- return 1;
-}
-
-static void
-delsyms(Obj *obj)
-{
- Symbol *sym, *next;
-
- for (sym = obj->head; sym; sym = next) {
- next = sym->next;
- free(sym->name);
- free(sym);
- }
-
- obj->head = NULL;
- memset(obj->htab, 0, sizeof(obj->htab));
-}
-
-static void
-delsecs(Obj *obj)
-{
- int i;
-
- for (i = 0; i < obj->nsecs; i++)
- free(obj->sections[i].name);
- free(obj->sections);
- obj->sections = NULL;
-}
-
-int
-objreset(Obj *obj)
-{
- int fmt;
- struct format *op;
-
- fmt = FORMAT(obj->type);
- if (fmt < NFORMATS)
- return -1;
- op = objfmt[fmt];
- (*op->del)(obj);
- delsyms(obj);
- delsecs(obj);
- return 0;
-}
-
-int
-objdel(Obj *obj)
-{
- if (objreset(obj) < 0)
- return -1;
- free(obj);
-}
-
-int
-objstrip(Obj *obj)
-{
- int fmt;
- struct format *op;
-
- fmt = FORMAT(obj->type);
- if (fmt >= NFORMATS)
- return -1;
- op = objfmt[fmt];
- (*op->strip)(obj);
- delsyms(obj);
- return 0;
-}
-
-int
-objsize(Obj *obj,
- unsigned long long *text,
- unsigned long long *data,
- unsigned long long *bss)
-{
- Section *sp, *secs = obj->sections;
- unsigned long long *p;
-
- *text = 0;
- *data = 0;
- *bss = 0;
- for (sp =secs; sp < &secs[obj->nsecs]; sp++) {
- switch (sp->type) {
- case 'T':
- p = text;
- break;
- case 'D':
- p = data;
- break;
- case 'B':
- p = bss;
- break;
- default:
- continue;
- }
-
- if (*p > ULLONG_MAX - sp->size)
- return -1;
- *p += sp->size;
- }
- return 0;
-}
-
-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)
-{
- /* TODO */
- return -1;
-}
--- a/src/libmach/objfmt.c
+++ /dev/null
@@ -1,11 +1,0 @@
-#include <stdio.h>
-
-#include <scc/mach.h>
-#include "libmach.h"
-
-extern struct format objcoff32;
-
-struct format *objfmt[] = {
- [COFF32] = &objcoff32,
- [NFORMATS] = NULL,
-};
--- /dev/null
+++ b/src/libmach/objfree.c
@@ -1,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+static void
+delsyms(Obj *obj)
+{
+ Symbol *sym, *next;
+
+ for (sym = obj->head; sym; sym = next) {
+ next = sym->next;
+ free(sym->name);
+ free(sym);
+ }
+
+ obj->head = NULL;
+ memset(obj->htab, 0, sizeof(obj->htab));
+}
+
+static void
+delsecs(Obj *obj)
+{
+ int i;
+
+ for (i = 0; i < obj->nsecs; i++)
+ free(obj->sections[i].name);
+ free(obj->sections);
+ obj->sections = NULL;
+}
+
+void
+objfree(Obj *obj, int what)
+{
+ if (what & FREESYM)
+ delsyms(obj);
+ if (what & FREESECT)
+ delsecs(obj);
+}
--- /dev/null
+++ b/src/libmach/objlookup.c
@@ -1,0 +1,42 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+Symbol *
+objlookup(Obj *obj, char *name)
+{
+ unsigned h;
+ size_t len;
+ char *s;
+ Symbol *sym;
+
+ h = 0;
+ for (s = name; *s; s++)
+ h += *s;
+ h %= NR_SYMHASH;
+
+ for (sym = obj->htab[h]; sym; sym = sym->hash) {
+ if (!strcmp(name, sym->name))
+ return sym;
+ }
+
+ if ((sym = malloc(sizeof(*sym))) == NULL)
+ return NULL;
+ len = strlen(name) + 1;
+ if ((s = malloc(len)) == NULL) {
+ free(sym);
+ return NULL;
+ }
+ sym->name = memcpy(s, name, len);
+ sym->type = 'U';
+ sym->size = 0;
+ sym->value = 0;
+ sym->hash = obj->htab[h];
+ obj->htab[h] = sym;
+ sym->next = obj->head;
+ obj->head = sym;
+
+ return sym;
+}
--- /dev/null
+++ b/src/libmach/objnew.c
@@ -1,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern newfun_t newv[];
+
+Obj *
+objnew(int type)
+{
+ Obj *obj;
+ int fmt;
+ newfun_t fn;
+
+ fmt = FORMAT(type);
+ if (fmt >= NFORMATS)
+ return NULL;
+
+ if ((obj = malloc(sizeof(*obj))) == NULL)
+ return NULL;
+
+ obj->type = type;
+ obj->head = NULL;
+ obj->sections = NULL;
+ memset(obj->htab, 0, sizeof(obj->htab));
+
+ fn = newv[fmt];
+ if ((*fn)(obj) < 0) {
+ free(obj);
+ return NULL;
+ }
+
+ return obj;
+}
--- /dev/null
+++ b/src/libmach/objpos.c
@@ -1,0 +1,15 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+int
+objpos(Obj *obj, FILE *fp, long pos)
+{
+ if (fsetpos(fp, &obj->pos))
+ return 0;
+ if (fseek(fp, pos, SEEK_CUR) < 0)
+ return 0;
+ return 1;
+}
--- /dev/null
+++ b/src/libmach/objread.c
@@ -1,0 +1,23 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern readfun_t readv[];
+
+int
+objread(Obj *obj, FILE *fp)
+{
+ int fmt;
+ readfun_t fn;
+
+ fmt = FORMAT(obj->type);
+ if (fmt >= NFORMATS)
+ return -1;
+
+ fn = readv[fmt];
+ if ((*fn)(obj, fp) < 0)
+ return -1;
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/objreset.c
@@ -1,0 +1,22 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern delfun_t delv[];
+
+int
+objreset(Obj *obj)
+{
+ int fmt;
+ delfun_t fn;
+
+ fmt = FORMAT(obj->type);
+ if (fmt < NFORMATS)
+ return -1;
+ fn = delv[fmt];
+ (*fn)(obj);
+ objfree(obj, FREESYM | FREESECT);
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/objsize.c
@@ -1,0 +1,40 @@
+#include <limits.h>
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+int
+objsize(Obj *obj,
+ unsigned long long *text,
+ unsigned long long *data,
+ unsigned long long *bss)
+{
+ Section *sp, *secs = obj->sections;
+ unsigned long long *p;
+
+ *text = 0;
+ *data = 0;
+ *bss = 0;
+ for (sp =secs; sp < &secs[obj->nsecs]; sp++) {
+ switch (sp->type) {
+ case 'T':
+ p = text;
+ break;
+ case 'D':
+ p = data;
+ break;
+ case 'B':
+ p = bss;
+ break;
+ default:
+ continue;
+ }
+
+ if (*p > ULLONG_MAX - sp->size)
+ return -1;
+ *p += sp->size;
+ }
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/objstrip.c
@@ -1,0 +1,38 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern stripfun_t stripv[];
+
+/* TODO: It is better to move this to a common place */
+static void
+delsyms(Obj *obj)
+{
+ Symbol *sym, *next;
+
+ for (sym = obj->head; sym; sym = next) {
+ next = sym->next;
+ free(sym->name);
+ free(sym);
+ }
+
+ obj->head = NULL;
+ memset(obj->htab, 0, sizeof(obj->htab));
+}
+
+int
+objstrip(Obj *obj)
+{
+ int fmt;
+ stripfun_t fn;
+
+ fmt = FORMAT(obj->type);
+ if (fmt >= NFORMATS)
+ return -1;
+ fn = stripv[fmt];
+ (*fn)(obj);
+ delsyms(obj);
+ return 0;
+}
--- /dev/null
+++ b/src/libmach/objtraverse.c
@@ -1,0 +1,17 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+int
+objtraverse(Obj *obj, int (*fn)(Symbol *, void *), void *data)
+{
+ Symbol *sym;
+
+ for (sym = obj->head; sym; sym = sym->next) {
+ if (!(*fn)(sym, data))
+ return 0;
+ }
+ return 1;
+}
--- /dev/null
+++ b/src/libmach/objtype.c
@@ -1,0 +1,32 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern probefun_t probev[];
+
+int
+objtype(FILE *fp, char **name)
+{
+ int n, i;
+ probefun_t *fn;
+ fpos_t pos;
+ unsigned char buf[NBYTES];
+
+ fgetpos(fp, &pos);
+ n = fread(buf, NBYTES, 1, fp);
+ fsetpos(fp, &pos);
+
+ if (n != 1 || ferror(fp))
+ return -1;
+
+ for (fn = probev; fn < &probev[NFORMATS]; ++fn) {
+ n = (*fn)(buf, name);
+ if (n == -1)
+ continue;
+ return n;
+ }
+
+ return -1;
+}
--- /dev/null
+++ b/src/libmach/objwrite.c
@@ -1,0 +1,22 @@
+#include <stdio.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+extern writefun_t writev[];
+
+int
+objwrite(Obj *obj, FILE *fp)
+{
+ int fmt;
+ writefun_t fn;
+
+ fmt = FORMAT(obj->type);
+ if (fmt >= NFORMATS)
+ return -1;
+ fn = writev[fmt];
+ if ((*fn)(obj, fp) < 0)
+ return -1;
+ return 0;
+}