scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit d9c993f20437064f0b29a09789b364d2ac489b00
parent 405c21e1ee69f42a6b29efde8403dac3e02aa674
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 31 Jan 2019 10:19:29 +0000

[libmach] Rework objsize()

This version is now independent of the object format.

Diffstat:
Minclude/scc/scc/coff32/scnhdr.h | 3---
Minclude/scc/scc/mach.h | 12+++++++-----
Msrc/libmach/coff32.c | 107++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/libmach/libmach.h | 4----
Msrc/libmach/object.c | 45++++++++++++++++++++++++++++++++++++++-------
5 files changed, 99 insertions(+), 72 deletions(-)

diff --git a/include/scc/scc/coff32/scnhdr.h b/include/scc/scc/coff32/scnhdr.h @@ -30,6 +30,3 @@ struct scnhdr { #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 diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -9,19 +9,20 @@ enum sectype { 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 @@ struct object { Symbol *htab[NR_SYMHASH]; Symbol *head; fpos_t pos; + int nsecs; Section *sections; void *data; }; diff --git a/src/libmach/coff32.c b/src/libmach/coff32.c @@ -313,29 +313,68 @@ static int 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 @@ loadsections(Obj *obj, FILE *fp) 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 @@ strip(Obj *obj) 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 @@ struct format objcoff32 = { .read = read, .write = write, .strip = strip, - .size = size, .index = mkindex, }; diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h @@ -33,10 +33,6 @@ struct format { 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); }; diff --git 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 @@ delsyms(Obj *obj) 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 @@ objreset(Obj *obj) op = objfmt[fmt]; (*op->del)(obj); delsyms(obj); + delsecs(obj); return 0; } @@ -204,14 +217,32 @@ objsize(Obj *obj, unsigned long long *data, unsigned long long *bss) { - int fmt; - struct format *op; + Section *sp, *secs = obj->sections; + unsigned long long *p; + + *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; + } - fmt = FORMAT(obj->type); - if (fmt >= NFORMATS) - return -1; - op = objfmt[fmt]; - return (*op->size)(obj, text, data, bss); + if (*p > ULLONG_MAX - sp->size) + return -1; + *p += sp->size; + } + return 0; } long