shithub: scc

Download patch

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)
 {