ref: ebf23256dfed83fa0018d4bf36b710351053af22
parent: 2594990a8e264e1f0b8dece2fc59e3af67dbfa43
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jan 31 13:01:31 EST 2019
[libmach] Read relocations and line numbers for coff32
--- a/include/scc/scc/coff32/coff32.h
+++ /dev/null
@@ -1,21 +1,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
--- 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) */
--- 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 coff32 {
FILHDR hdr;
+ AOUTHDR *aout;
SCNHDR *scns;
SYMENT *ents;
+ RELOC **rels;
+ LINENO **lines;
char *strtbl;
unsigned long strsiz;
};
@@ -36,6 +42,24 @@
};
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 @@
}
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,6 +120,26 @@
}
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;
@@ -81,7 +146,7 @@
char *s;
n = unpack(order,
- buf,
+ buf,
"'8lsscc",
ent->n_name,
&ent->n_value,
@@ -96,6 +161,100 @@
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,10 +402,8 @@
return 0;
coff->ents = ent;
- if (fsetpos(fp, &obj->pos))
+ if (!objpos(obj, fp, hdr->f_symptr))
return 0;
- if (fseek(fp, hdr->f_symptr, SEEK_CUR) < 0)
- return 0;
for (i = 0; i < hdr->f_nsyms; i++) {
if (fread(buf, SYMESZ, 1, fp) != 1)
return 0;
@@ -257,6 +414,87 @@
}
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 @@
}
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,6 +650,8 @@
goto error;
if (!readhdr(obj, fp))
goto error;
+ if (!readaout(obj, fp))
+ goto error;
if (!readscns(obj, fp))
goto error;
if (!readents(obj, fp))
@@ -393,6 +658,10 @@
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 @@
}
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
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -38,6 +38,7 @@
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);
--- a/src/libmach/object.c
+++ b/src/libmach/object.c
@@ -39,6 +39,16 @@
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)
{