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