scc

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

commit 0dfafb2f0ad3b9ad4559060c0b0dd9aec46840b0
parent d9c993f20437064f0b29a09789b364d2ac489b00
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 31 Jan 2019 18:01:31 +0000

[libmach] Read relocations and line numbers for coff32

Diffstat:
Dinclude/scc/scc/coff32/coff32.h | 21---------------------
Minclude/scc/scc/coff32/reloc.h | 5++++-
Msrc/libmach/coff32.c | 329+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/libmach/libmach.h | 1+
Msrc/libmach/object.c | 10++++++++++
5 files changed, 339 insertions(+), 27 deletions(-)

diff --git a/include/scc/scc/coff32/coff32.h b/include/scc/scc/coff32/coff32.h @@ -1,21 +0,0 @@ -typedef int (*packfun)(unsigned char *, char *, ...); - -#ifdef AOUTHDR -extern void coff32_pack_aout(packfun fun, unsigned char *buff, AOUTHDR *aout); -extern void coff32_unpack_aout(packfun fun, unsigned char *buff, AOUTHDR *ent); -#endif - -#ifdef SYMENT -extern void coff32_pack_ent(packfun fun, unsigned char *buff, SYMENT *ent); -extern void coff32_unpack_ent(packfun fun, unsigned char *buff, SYMENT *ent); -#endif - -#ifdef FILHDR -extern void coff32_pack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr); -extern void coff32_unpack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr); -#endif - -#ifdef SCNHDR -extern void coff32_pack_scn(packfun fun, unsigned char *buff, SCNHDR *scn); -extern void coff32_unpack_scn(packfun fun, unsigned char *buff, SCNHDR *scn); -#endif diff --git a/include/scc/scc/coff32/reloc.h b/include/scc/scc/coff32/reloc.h @@ -3,5 +3,8 @@ struct reloc { long r_vaddr; /* address of reference */ long r_symndx; /* index into symbol table */ - unsignedd short r_type; /* relocation type */ + unsigned short r_type; /* relocation type */ }; + +#define RELOC struct reloc +#define RELSZ 10 /* sizeof (RELOC) */ diff --git a/src/libmach/coff32.c b/src/libmach/coff32.c @@ -7,8 +7,11 @@ #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" @@ -23,8 +26,11 @@ struct arch { struct coff32 { FILHDR hdr; + AOUTHDR *aout; SCNHDR *scns; SYMENT *ents; + RELOC **rels; + LINENO **lines; char *strtbl; unsigned long strsiz; }; @@ -36,6 +42,24 @@ static struct arch archs[] = { }; 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; @@ -54,6 +78,27 @@ unpack_hdr(int order, unsigned char *buf, FILHDR *hdr) } 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; @@ -75,13 +120,33 @@ unpack_scn(int order, unsigned char *buf, SCNHDR *scn) } 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, + buf, "'8lsscc", ent->n_name, &ent->n_value, @@ -96,6 +161,100 @@ unpack_ent(int order, unsigned char *buf, SYMENT *ent) 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) { @@ -243,9 +402,7 @@ readents(Obj *obj, FILE *fp) return 0; coff->ents = ent; - if (fsetpos(fp, &obj->pos)) - return 0; - if (fseek(fp, hdr->f_symptr, SEEK_CUR) < 0) + if (!objpos(obj, fp, hdr->f_symptr)) return 0; for (i = 0; i < hdr->f_nsyms; i++) { if (fread(buf, SYMESZ, 1, fp) != 1) @@ -257,6 +414,87 @@ readents(Obj *obj, FILE *fp) } 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; @@ -380,6 +618,31 @@ loadsections(Obj *obj, FILE *fp) } 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 */ @@ -387,12 +650,18 @@ read(Obj *obj, FILE *fp) 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)) @@ -405,9 +674,59 @@ error: } 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) { - return -1; + 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 diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -38,6 +38,7 @@ struct format { 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); /* idx functions */ extern long coff32idx(int order, long nsyms, Symdef *def, FILE *fp); diff --git a/src/libmach/object.c b/src/libmach/object.c @@ -39,6 +39,16 @@ objtype(FILE *fp, char **name) 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) {