shithub: scc

Download patch

ref: c75d39d84fcaf779903f1e76c1ffebccac2de3cc
parent: 3aa27c3da9cf49c6f8082f09a295b7cf241c9a65
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Feb 8 02:47:13 EST 2019

[libmach/coff32] Add all the missed parts in coff32write

--- a/include/scc/scc/coff32/syms.h
+++ b/include/scc/scc/coff32/syms.h
@@ -1,10 +1,10 @@
 /* This file is inspired in the book "Understanding and using COFF" */
 
-#define E_SYMNMLEN   8
+#define SYMNMLEN   8
 
 struct syment {
 	union {
-		char _n_name[8];          /* symbol name */
+		char _n_name[SYMNMLEN];  /* symbol name */
 		struct {
 			long _n_zeroes;  /* if _n_name[0-3] == 0 */
 			long _n_offset;  /* offset into string table */
--- a/src/libmach/coff32/coff32read.c
+++ b/src/libmach/coff32/coff32read.c
@@ -244,7 +244,8 @@
 static int
 readreloc(Obj *obj, FILE *fp)
 {
-	int i, j;
+	int i;
+	long j;
 	RELOC **rels, *rp;
 	SCNHDR *scn;
 	FILHDR *hdr;
@@ -414,8 +415,7 @@
 			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;
--- a/src/libmach/coff32/coff32write.c
+++ b/src/libmach/coff32/coff32write.c
@@ -1,4 +1,5 @@
 #include <assert.h>
+#include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -60,11 +61,11 @@
 	         buf,
 	         "'8lsscc",
 	         ent->n_name,
-	         &ent->n_value,
-	         &ent->n_scnum,
-	         &ent->n_type,
-	         &ent->n_sclass,
-	         &ent->n_numaux);
+	         ent->n_value,
+	         ent->n_scnum,
+	         ent->n_type,
+	         ent->n_sclass,
+	         ent->n_numaux);
 	assert(n == SYMESZ);
 }
 
@@ -73,17 +74,17 @@
 {
 	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);
+	n = pack(order,
+	         buf,
+	         "ssllllll",
+	         aout->magic,
+	         aout->vstamp,
+	         aout->tsize,
+	         aout->dsize,
+	         aout->bsize,
+	         aout->entry,
+	         aout->text_start,
+	         aout->data_start);
 	assert(n == AOUTSZ);
 }
 
@@ -135,33 +136,172 @@
 static int
 writescns(Obj *obj, FILE *fp)
 {
-	/* TODO */
+	int i;
+	SCNHDR *scn;
+	FILHDR *hdr;
+	struct coff32 *coff;
+	unsigned char buf[SCNHSZ];
+
+	coff  = obj->data;
+	hdr = &coff->hdr;
+
+	for (i = 0; i < hdr->f_nscns; i++) {
+		scn = &coff->scns[i];
+		pack_scn(ORDER(obj->type), buf, scn);
+		if (fwrite(buf, SCNHSZ, 1, fp) != 1)
+			return 0;
+	}
+
+	return 1;
 }
 
 static int
 writeents(Obj *obj, FILE *fp)
 {
-	/* TODO */
+	long i, len, strsiz;
+	char *strtbl, *s;
+	FILHDR *hdr;
+	struct coff32 *coff;
+	unsigned char buf[SYMESZ];
+
+	coff  = obj->data;
+	hdr = &coff->hdr;
+	strtbl = NULL;
+	strsiz = 0;
+
+	for (i = 0; i < hdr->f_nsyms; i++) {
+		SYMENT *ent = &coff->ents[i];
+
+		len = strlen(ent->n_name) + 1;
+		if (len > strsiz - LONG_MAX)
+			goto err;
+		s = realloc(strtbl, strsiz + len);
+		if (!s)
+			goto err;
+		memcpy(s + strsiz, ent->n_name, len);
+		strtbl = s;
+		strsiz += len;
+
+		pack_ent(ORDER(obj->type), buf, ent);
+		if (fwrite(buf, SYMESZ, 1, fp) != 1)
+			return 0;
+	}
+
+	free(coff->strtbl);
+	coff->strtbl = strtbl;
+	coff->strsiz = strsiz;
+
+	return 1;
+
+err:
+	free(strtbl);
+	return 0;
 }
 
 static int
 writestr(Obj *obj, FILE *fp)
 {
-	/* TODO */
+	struct coff32 *coff;
+	unsigned char buf[4];
+
+	coff = obj->data;
+	if ((coff->strsiz & 0xffff) != coff->strsiz)
+		return 0;
+
+	pack(ORDER(obj->type), buf, "l", coff->strsiz);
+	fwrite(buf, 4, 1, fp);
+	fwrite(coff->strtbl, coff->strsiz, 1, fp);
+
+	return ferror(fp);
 }
 
-int
-coff32write(Obj *obj, FILE *fp)
+static int
+writeaout(Obj *obj, FILE *fp)
 {
+	FILHDR *hdr;
 	struct coff32 *coff;
+	unsigned char buf[AOUTSZ];
 
 	coff  = obj->data;
-	coff->strsiz = 0;
-	free(coff->strtbl);
+	hdr = &coff->hdr;
 
+	if (hdr->f_opthdr == 0)
+		return 1;
+	pack_aout(ORDER(obj->type), buf, coff->aout);
+
+	return fread(buf, AOUTSZ, 1, fp) != 1;
+}
+
+static int
+writereloc(Obj *obj, FILE *fp)
+{
+	int i, j;
+	RELOC *rp;
+	SCNHDR *scn;
+	FILHDR *hdr;
+	struct coff32 *coff;
+	unsigned char buf[RELSZ];
+
+	coff  = obj->data;
+	hdr = &coff->hdr;
+
+	for (i = 0; i < hdr->f_nscns; i++) {
+		rp = coff->rels[i];
+		if (!rp)
+			continue;
+		scn = &coff->scns[i];
+
+		for (j = 0; j < scn->s_nrelloc; j++) {
+			pack_reloc(ORDER(obj->type), buf, &rp[i]);
+			if (fwrite(buf, RELSZ, 1, fp) != 1)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int
+writelines(Obj *obj, FILE *fp)
+{
+	int i;
+	long j;
+	FILHDR *hdr;
+	LINENO *lp;
+	SCNHDR *scn;
+	struct coff32 *coff;
+	unsigned char buf[LINESZ];
+
+	coff  = obj->data;
+	hdr = &coff->hdr;
+
+        for (i = 0; i < hdr->f_nscns; i++) {
+		lp = coff->lines[i];
+		if (!lp)
+			continue;
+		scn = &coff->scns[i];
+		for (j = 0; j < scn->s_nlnno; j++) {
+			pack_line(ORDER(obj->type), buf, &lp[j]);
+			if (fwrite(buf, LINESZ, 1, fp) == 1)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+int
+coff32write(Obj *obj, FILE *fp)
+{
 	if (!writehdr(obj, fp))
 		return -1;
+	if (!writeaout(obj, fp))
+		return -1;
 	if (!writescns(obj, fp))
+		return -1;
+	if (!writereloc(obj, fp))
+		return -1;
+	if (!writelines(obj, fp))
 		return -1;
 	if (!writeents(obj, fp))
 		return -1;