shithub: scc

Download patch

ref: 2594990a8e264e1f0b8dece2fc59e3af67dbfa43
parent: b5f8e196aa5692b1ed355de2c772b88816d89d44
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jan 31 05:19:29 EST 2019

[libmach] Rework objsize()

This version is now independent of the object format.

--- a/include/scc/scc/coff32/scnhdr.h
+++ b/include/scc/scc/coff32/scnhdr.h
@@ -30,6 +30,3 @@
 #define STYP_INFO        (1 << 9)
 #define STYP_OVER        (1 << 11)
 #define STYP_LIB         (1 << 12)
-#define STYP_MERGE       (1 << 13)
-#define STYP_REVERSE_PAD (1 << 14)
-#define STYP_LIT	 0x8020
--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -9,19 +9,20 @@
 	SREAD   = 1 << 0,
 	SWRITE  = 1 << 1,
 	SEXEC   = 1 << 2,
-	SNOLOAD = 1 << 3,
-	SFILE   = 1 << 4,
-	SABS    = 1 << 5,
-	SBLOB   = 1 << 6,
+	SLOAD   = 1 << 3,
+	SALLOC  = 1 << 4,
+	SRELOC  = 1 << 5,
+	SABS    = 1 << 6,
+	SSHARED = 1 << 7,
 };
 
 struct section {
 	char *name;
+	int type;
 	unsigned flags;
 	FILE *fp;
 	long offset;
 	unsigned long long size;
-	Section *next;
 };
 
 struct symbol {
@@ -45,6 +46,7 @@
 	Symbol *htab[NR_SYMHASH];
 	Symbol *head;
 	fpos_t pos;
+	int nsecs;
 	Section *sections;
 	void *data;
 };
--- a/src/libmach/coff32.c
+++ b/src/libmach/coff32.c
@@ -313,29 +313,68 @@
 loadsections(Obj *obj, FILE *fp)
 {
 	size_t len;
-	int i;
+	unsigned sflags, type;
+	unsigned long flags;
 	FILHDR *hdr;
 	struct coff32 *coff;
 	SCNHDR *scn;
-	Section *p;
+	Section *secs, *sp;
 
 	coff  = obj->data;
 	hdr = &coff->hdr;
 	scn = coff->scns;
-	for (i = 0; i < hdr->f_nscns; i++) {
-		if ((p = malloc(sizeof(*p))) == NULL)
-			return 0;
+
+	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 ((p->name = malloc(len)) == NULL) {
-			free(p);
+		if ((sp->name = malloc(len)) == NULL)
 			return 0;
-		}
-		memcpy(p->name, scn->s_name, len);
-		p->fp = fp;
-		p->offset = scn->s_scnptr;
-		p->size = scn->s_size;
-		p->next = obj->sections;
-		obj->sections = p->next;
+
+		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;
 }
@@ -343,6 +382,7 @@
 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))
@@ -408,44 +448,6 @@
 	hdr->f_symptr = 0;
 }
 
-static int
-size(Obj *obj,
-     unsigned long long *text,
-     unsigned long long *data,
-     unsigned long long *bss)
-{
-	int i;
-	long flags;
-	FILHDR *hdr;
-	struct coff32 *coff;
-	SCNHDR *scn, *lim;
-	unsigned long long *p;
-
-	*text = 0;
-	*data = 0;
-	*bss = 0;
-
-	coff  = obj->data;
-	hdr = &coff->hdr;
-
-	lim = &coff->scns[hdr->f_nscns];
-	for (scn = coff->scns; scn < lim; scn++) {
-		flags = scn->s_flags;
-		if (flags & STYP_TEXT)
-			p = text;
-		else if (flags & STYP_DATA)
-			p = data;
-		else if (flags & STYP_BSS)
-			p = bss;
-		else
-			continue;
-		if (*p > ULONG_MAX - scn->s_size)
-			return -1;
-		*p += scn->s_size;
-	}
-	return 0;
-}
-
 static long
 mkindex(int type, long nsymbols, Symdef *head, FILE *fp)
 {
@@ -459,6 +461,5 @@
 	.read = read,
 	.write = write,
 	.strip = strip,
-	.size = size,
 	.index = mkindex,
 };
--- a/src/libmach/libmach.h
+++ b/src/libmach/libmach.h
@@ -33,10 +33,6 @@
 	int (*read)(Obj *obj, FILE *fp);
 	int (*write)(Obj *obj, FILE *fp);
 	void (*del)(Obj *obj);
-	int (*size)(Obj *obj,
-                unsigned long long *,
-                unsigned long long *,
-                unsigned long long *);
 	long (*index)(int type, long nsyms, Symdef *def, FILE *fp);
 };
 
--- a/src/libmach/object.c
+++ b/src/libmach/object.c
@@ -1,5 +1,6 @@
 static char sccsid[] = "@(#) ./libmach/object.c";
 
+#include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -160,6 +161,17 @@
 	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)
 {
@@ -172,6 +184,7 @@
 	op = objfmt[fmt];
 	(*op->del)(obj);
 	delsyms(obj);
+	delsecs(obj);
 	return 0;
 }
 
@@ -204,14 +217,32 @@
         unsigned long long *data,
         unsigned long long *bss)
 {
-	int fmt;
-	struct format *op;
+	Section *sp, *secs = obj->sections;
+	unsigned long long *p;
 
-	fmt = FORMAT(obj->type);
-	if (fmt >= NFORMATS)
-		return -1;
-	op = objfmt[fmt];
-	return (*op->size)(obj, text, data, bss);
+	*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