scc

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

commit 7e83e0d7e754524182a18311e4f41444b90f985a
parent 546ffbebb56d57c920421134ff54efcdc0631530
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 10 May 2018 20:42:38 +0100

[ld/coff32] Load sections and symbols in pass1

This is other step in having a linker working for coff32.

Diffstat:
Mld/coff32.c | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mld/ld.h | 12++++++++----
Mld/main.c | 8+++++++-
Mld/obj.c | 17++++++++++-------
4 files changed, 144 insertions(+), 44 deletions(-)

diff --git a/ld/coff32.c b/ld/coff32.c @@ -14,7 +14,6 @@ static char sccsid[] = "@(#) ./ld/coff32.c"; #include "ld.h" static int (*unpack)(unsigned char *, char *, ...); -static long strtbl, symtbl, sectbl; static FILHDR * getfhdr(unsigned char *buff, FILHDR *hdr) @@ -22,59 +21,147 @@ getfhdr(unsigned char *buff, FILHDR *hdr) int n; n = (*unpack)(buff, - "sslllss", - &hdr->f_magic, - &hdr->f_nscns, - &hdr->f_timdat, - &hdr->f_symptr, - &hdr->f_nsyms, - &hdr->f_opthdr, - &hdr->f_flags); + "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); return hdr; } +static int +readstr(Obj *obj, long off) +{ + unsigned char buff[4]; + char *str; + size_t siz; + + if (fseek(obj->fp, off, SEEK_SET) == EOF) + return -1; + + if (fread(buff, 4, 1, obj->fp) != 1) + return -1; + + (*unpack)(buff, "l", &siz); + + if (siz > SIZE_MAX || (str = malloc(siz)) == NULL) + outmem(); + + if (fread(str, siz, 1, obj->fp) != 1) + return -1; + + obj->strtbl = str; + return 0; +} + +static SCNHDR * +getscn(unsigned char *buff, SCNHDR *scn) +{ + int n; + + n = (*unpack)(buff, + "'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); + return scn; +} + +static int +readsects(Obj *obj, long off) +{ + unsigned i; + unsigned char buff[SCNHSZ]; + SCNHDR scn; + FILHDR *hdr; + + if (fseek(obj->fp, off, SEEK_SET) == EOF) + return -1; + + hdr = obj->filhdr; + for (i = 0; i < hdr->f_nscns; i++) { + if (fread(buff, SCNHSZ, 1, obj->fp) != 1) + return -1; + getscn(buff, &scn); + } +} + +static void +getsym(unsigned char *buff, SYMENT *ent) +{ + int n; + + n = (*unpack)(buff, + "'8lsscc", + &ent->n_name, + &ent->n_value, + &ent->n_scnum, + &ent->n_type, + &ent->n_sclass, + &ent->n_numaux); + assert(n == SYMESZ); +} + +static int +loadobj(Obj *obj, long off) +{ + unsigned i; + unsigned char buff[SYMESZ]; + SYMENT sym; + FILHDR *hdr; + + for (i = 0; i < hdr->f_nsyms; i++) { + if (fread(buff, SYMESZ, 1, obj->fp) != 1) + return -1; + getsym(buff, &sym); + } +} + static void pass1(char *fname, char *member, FILE *fp) { unsigned char buff[FILHSZ]; FILHDR *hdr; Obj *obj; - long siz, pos = ftell(fp); - char *str; + char *strtbl; + long symoff, secoff, stroff, pos; + + obj = newobj(fname, member); + obj->fp = fp; + pos = ftell(fp); if (fread(buff, FILHSZ, 1, fp) != 1) goto bad_file; if ((hdr = malloc(sizeof(*hdr))) == NULL) - goto out_of_memory; - - obj = newobj(fname); - obj->hdr = getfhdr(buff, hdr); + outmem(); + getfhdr(buff, hdr); + obj->filhdr = hdr; /* TODO: Check overflow */ - strtbl = pos + hdr->f_symptr + hdr->f_nsyms* SYMESZ; - symtbl = pos + hdr->f_symptr; - sectbl = pos + FILHSZ + hdr->f_opthdr; + stroff = pos + hdr->f_symptr + hdr->f_nsyms*SYMESZ; + symoff = pos + hdr->f_symptr; + secoff = pos + FILHSZ + hdr->f_opthdr; - if (fseek(fp, strtbl, SEEK_SET) == EOF) + if (readstr(obj, stroff) < 0) goto bad_file; - - if (fread(buff, 4, 1, fp) != 1) + if (loadobj(obj, symoff) < 0) goto bad_file; - - (*unpack)(buff, "l", &siz); - - if (siz > SIZE_MAX || (str = malloc(siz)) == NULL) - goto out_of_memory; - - if (fread(str, siz, 1, fp) != 1) + if (readsects(obj, secoff) < 0) goto bad_file; - obj->strtbl = str; - -out_of_memory: - die("ld: out of memory"); bad_file: if (ferror(fp)) die("ld: %s: %s", fname, strerror(errno)); diff --git a/ld/ld.h b/ld/ld.h @@ -4,7 +4,10 @@ typedef struct symbol Symbol; struct obj { char *fname; - void *hdr; + char *member; + FILE *fp; + void *filhdr; + void *sechdr; char *strtbl; struct obj *next; }; @@ -13,14 +16,15 @@ struct symbol { char *name; }; -#ifdef stdin struct objfile { int (*probe)(char *fname, char *member, FILE *fp); void (*pass1)(char *fname, char *member, FILE *fp); void (*pass2)(char *fname, char *member, FILE *fp); }; -#endif /* obj.c */ -extern Obj *newobj(char *fname); +extern Obj *newobj(char *fname, char *member); extern Symbol *lookup(char *name); + +/* main.c */ +extern void outmem(void); diff --git a/ld/main.c b/ld/main.c @@ -12,11 +12,17 @@ static char sccsid[] = "@(#) ./ld/main.c"; #include "../inc/syslibs.h" #include "ld.h" -char *argv0; char *output = "a.out", *entry, *datasiz; int pass; int sflag, xflag, Xflag, rflag, dflag; +void +outmem(void) +{ + fputs("ld: out of memory\n", stderr); + exit(EXIT_FAILURE); +} + static int object(char *fname, char *member, FILE *fp) { diff --git a/ld/obj.c b/ld/obj.c @@ -1,5 +1,6 @@ static char sccsid[] = "@(#) ./ld/obj.c"; +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -10,18 +11,20 @@ Obj *objlst; static Obj *tail; Obj * -newobj(char *fname) +newobj(char *fname, char *member) { Obj *obj; - char *s; - size_t len = strlen(fname); + char *s, *t; + size_t l1 = strlen(member), l2 = strlen(fname); obj = malloc(sizeof(*obj)); - s = malloc(len+1); - if (!obj || !s) - die("ld: out of memory"); + s = malloc(l1+1); + t = malloc(l2+1); + if (!obj || !s || !t) + outmem(); - obj->fname = memcpy(s, fname, len); + obj->fname = memcpy(s, fname, l1); + obj->member = memcpy(t, member, l2); obj->next = NULL; if (!objlst)