scc

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

commit 7e122c00108551cc8fd259faacdcfcc8712c1e65
parent 1134ca637716476ffb3f5fb26105733e6d7e7f09
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  6 Feb 2019 08:04:15 +0000

[libmach] Split object.c and coff32.c

Diffstat:
Msrc/libc/Makefile | 2+-
Asrc/libmach/.gitignore | 8++++++++
Msrc/libmach/Makefile | 60+++++++++++++++++++++++++++++++++++++++++++++++++++---------
Asrc/libmach/Makefile.mach | 11+++++++++++
Asrc/libmach/addr2line.c | 10++++++++++
Asrc/libmach/arindex.c | 20++++++++++++++++++++
Dsrc/libmach/coff32.c | 784-------------------------------------------------------------------------------
Asrc/libmach/coff32/Makefile | 13+++++++++++++
Asrc/libmach/coff32/coff-help.h | 576+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/coff32/coff32.h | 25+++++++++++++++++++++++++
Asrc/libmach/coff32/coff32del.c | 21+++++++++++++++++++++
Asrc/libmach/coff32/coff32index.c | 12++++++++++++
Asrc/libmach/coff32/coff32new.c | 18++++++++++++++++++
Asrc/libmach/coff32/coff32probe.c | 27+++++++++++++++++++++++++++
Asrc/libmach/coff32/coff32read.c | 522+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/coff32/coff32strip.c | 20++++++++++++++++++++
Asrc/libmach/coff32/coff32write.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/formats.lst | 1+
Msrc/libmach/libmach.h | 34+++++++++++++++++++++-------------
Asrc/libmach/mklst | 9+++++++++
Asrc/libmach/mktbl | 35+++++++++++++++++++++++++++++++++++
Asrc/libmach/objdel.c | 14++++++++++++++
Dsrc/libmach/object.c | 276-------------------------------------------------------------------------------
Dsrc/libmach/objfmt.c | 11-----------
Asrc/libmach/objfree.c | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/objlookup.c | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/objnew.c | 37+++++++++++++++++++++++++++++++++++++
Asrc/libmach/objpos.c | 15+++++++++++++++
Asrc/libmach/objread.c | 23+++++++++++++++++++++++
Asrc/libmach/objreset.c | 22++++++++++++++++++++++
Asrc/libmach/objsize.c | 40++++++++++++++++++++++++++++++++++++++++
Asrc/libmach/objstrip.c | 38++++++++++++++++++++++++++++++++++++++
Asrc/libmach/objtraverse.c | 17+++++++++++++++++
Asrc/libmach/objtype.c | 32++++++++++++++++++++++++++++++++
Asrc/libmach/objwrite.c | 22++++++++++++++++++++++
35 files changed, 1917 insertions(+), 1094 deletions(-)

diff --git a/src/libc/Makefile b/src/libc/Makefile @@ -18,7 +18,7 @@ all: $(DIRS) objlst.mk $(DIRS): FORCE +@cd $@ && $(MAKE) -objlst.mk: FORCE +objlst.mk: $(DIRS) FORCE mklst $@ clean: diff --git a/src/libmach/.gitignore b/src/libmach/.gitignore @@ -0,0 +1,8 @@ +objlst.mk +del.c +index.c +new.c +probe.c +read.c +strip.c +write.c diff --git a/src/libmach/Makefile b/src/libmach/Makefile @@ -3,17 +3,59 @@ PROJECTDIR =../.. 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 \ + + +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 $@ -all: $(TARGET) +objlst.mk: $(OBJS) $(DIRS) + mklst $@ -$(TARGET): $(OBJS) - mklib -o $@ $? +clean: + $(FORALL) + rm -f $(TBLS) objlst.mk diff --git a/src/libmach/Makefile.mach b/src/libmach/Makefile.mach @@ -0,0 +1,11 @@ +.POSIX: +PROJECTDIR =../.. +include $(PROJECTDIR)/scripts/rules.mk +include objlst.mk + +TARGET = $(LIBDIR)/libmach.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + mklib -o $@ $? diff --git a/src/libmach/addr2line.c b/src/libmach/addr2line.c @@ -0,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; +} diff --git a/src/libmach/arindex.c b/src/libmach/arindex.c @@ -0,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); +} diff --git a/src/libmach/coff32.c b/src/libmach/coff32.c @@ -1,784 +0,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, -}; diff --git a/src/libmach/coff32/Makefile b/src/libmach/coff32/Makefile @@ -0,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) diff --git a/src/libmach/coff32/coff-help.h b/src/libmach/coff32/coff-help.h @@ -0,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&amp;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&amp;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 &amp; 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&amp;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 &amp; 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> diff --git a/src/libmach/coff32/coff32.h b/src/libmach/coff32/coff32.h @@ -0,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; +}; diff --git a/src/libmach/coff32/coff32del.c b/src/libmach/coff32/coff32del.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32index.c b/src/libmach/coff32/coff32index.c @@ -0,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); +} diff --git a/src/libmach/coff32/coff32new.c b/src/libmach/coff32/coff32new.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32probe.c b/src/libmach/coff32/coff32probe.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32read.c b/src/libmach/coff32/coff32read.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32strip.c b/src/libmach/coff32/coff32strip.c @@ -0,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; +} diff --git a/src/libmach/coff32/coff32write.c b/src/libmach/coff32/coff32write.c @@ -0,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; +} diff --git a/src/libmach/formats.lst b/src/libmach/formats.lst @@ -0,0 +1 @@ +coff32 diff --git 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 @@ enum order { 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); diff --git a/src/libmach/mklst b/src/libmach/mklst @@ -0,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 diff --git a/src/libmach/mktbl b/src/libmach/mktbl @@ -0,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 diff --git a/src/libmach/objdel.c b/src/libmach/objdel.c @@ -0,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); +} diff --git a/src/libmach/object.c b/src/libmach/object.c @@ -1,276 +0,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; -} diff --git a/src/libmach/objfmt.c b/src/libmach/objfmt.c @@ -1,11 +0,0 @@ -#include <stdio.h> - -#include <scc/mach.h> -#include "libmach.h" - -extern struct format objcoff32; - -struct format *objfmt[] = { - [COFF32] = &objcoff32, - [NFORMATS] = NULL, -}; diff --git a/src/libmach/objfree.c b/src/libmach/objfree.c @@ -0,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); +} diff --git a/src/libmach/objlookup.c b/src/libmach/objlookup.c @@ -0,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; +} diff --git a/src/libmach/objnew.c b/src/libmach/objnew.c @@ -0,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; +} diff --git a/src/libmach/objpos.c b/src/libmach/objpos.c @@ -0,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; +} diff --git a/src/libmach/objread.c b/src/libmach/objread.c @@ -0,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; +} diff --git a/src/libmach/objreset.c b/src/libmach/objreset.c @@ -0,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; +} diff --git a/src/libmach/objsize.c b/src/libmach/objsize.c @@ -0,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; +} diff --git a/src/libmach/objstrip.c b/src/libmach/objstrip.c @@ -0,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; +} diff --git a/src/libmach/objtraverse.c b/src/libmach/objtraverse.c @@ -0,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; +} diff --git a/src/libmach/objtype.c b/src/libmach/objtype.c @@ -0,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; +} diff --git a/src/libmach/objwrite.c b/src/libmach/objwrite.c @@ -0,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; +}