scc

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

commit d443bc257b580cd6f28c7346ceea502833bf8c6f
parent 87b10cc5100a97c249086a0f7bde655c73f9cb73
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 26 Feb 2019 17:52:28 +0000

[ld] Add 3rd pass

This pass updates the base address of every section that is going
to be linked.

Diffstat:
Minclude/scc/scc/mach.h | 10++++++----
Msrc/cmd/Makefile | 1-
Msrc/cmd/ld/pass1.c | 18+++++++++---------
Msrc/cmd/ld/pass3.c | 53+++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/libmach/coff32/coff32getsect.c | 3++-
Msrc/libmach/coff32/coff32getsyms.c | 1+
6 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -18,17 +18,19 @@ enum sectype { struct objsect { char *name; + int id; int type; - unsigned flags; - long offset; int align; - unsigned long long size; + unsigned flags; + long seek; + unsigned long long size, base; Objsect *next; }; struct objsym { - char type; char *name; + int type; + int sect; unsigned long long size; unsigned long long value; Objsym *next, *hash; diff --git a/src/cmd/Makefile b/src/cmd/Makefile @@ -7,7 +7,6 @@ TARGET = $(BINDIR)/nm \ $(BINDIR)/strip \ $(BINDIR)/size \ $(BINDIR)/ar \ - $(BINDIR)/ld \ $(BINDIR)/ranlib \ $(BINDIR)/objdump \ $(BINDIR)/objcopy \ diff --git a/src/cmd/ld/pass1.c b/src/cmd/ld/pass1.c @@ -13,7 +13,7 @@ static int bintype = -1; Objlst *objhead, *objlast; static void -loadobj(Obj *obj, FILE *fp) +addobj(Obj *obj, FILE *fp) { int n; Objlst *lst; @@ -70,7 +70,7 @@ newobject(FILE *fp, int type, int inlib) * some symbol needed. */ if (!inlib || defasym(obj)) { - loadobj(obj, fp); + addobj(obj, fp); return; } @@ -80,9 +80,9 @@ newobject(FILE *fp, int type, int inlib) } static void -loadlib(FILE *fp) +addlib(FILE *fp) { - int t, loaded; + int t, added; long n; Objsymdef *def, *dp; Symbol *sym; @@ -92,9 +92,9 @@ loadlib(FILE *fp) return; } - loaded = 1; - while (moreundef() && loaded) { - loaded = 0; + added = 1; + while (moreundef() && added) { + added = 0; for (dp = def; dp; dp = dp->next) { sym = lookup(dp->name, NOINSTALL); if (!sym || sym->def) @@ -116,7 +116,7 @@ loadlib(FILE *fp) } newobject(fp, t, OUTLIB); - loaded = 1; + added = 1; } } clean: @@ -137,7 +137,7 @@ newmember(FILE *fp, char *name, void *data) if (*nmemb++ == 0) { if (!strncmp(name, "/", SARNAM) || !strncmp(name, "__.SYMDEF", SARNAM)) { - loadlib(fp); + addlib(fp); return 0; } } diff --git a/src/cmd/ld/pass3.c b/src/cmd/ld/pass3.c @@ -1,3 +1,4 @@ +#include <ctype.h> #include <stdio.h> #include <stdlib.h> @@ -5,8 +6,35 @@ #include "ld.h" +static void +rebase(Obj *obj) +{ + Symbol *aux; + Objsym *sym; + + for (sym = obj->syms; sym; sym = sym->next) { + switch (toupper(sym->type)) { + case 'T': + case 'D': + case 'B': + aux = lookup(sym->name, NOINSTALL); + aux->value += obj->secs[sym->sect].base; + case 't': + case 'd': + case 'b': + sym->value += obj->secs[sym->sect].base; + case 'N': + case 'U': + case '?': + break; + default: + abort(); + } + } +} + /* - * relocate the sections + * rebase all the sections */ void pass3(int argc, char *argv[]) @@ -14,21 +42,34 @@ pass3(int argc, char *argv[]) Obj *obj; Objlst *lst; Objsect *sp; - unsigned long long text, data, bss; + unsigned long long *base, text, data, bss; - textbase = text = 0; - database = data = textsiz+3 & ~3; - bssbase = bss = data+datasiz+3 & ~3; + /* + * TODO: deal with page aligment + */ + textbase = text = 0x100; + database = data = textsiz; + bssbase = bss = data+datasiz; for (lst = objhead; lst; lst = lst->next) { - for (sp = lst->obj->secs; sp; sp = sp->next) { + obj = lst->obj; + for (sp = obj->secs; sp; sp = sp->next) { switch (sp->type) { case 'T': + base = &text; + break; case 'D': + base = &data; + break; case 'B': + base = &bss; + break; default: abort(); } + sp->base = *base; + *base += sp->size; } + rebase(obj); } } diff --git a/src/libmach/coff32/coff32getsect.c b/src/libmach/coff32/coff32getsect.c @@ -64,7 +64,8 @@ coff32getsect(Obj *obj) sflags &= ~SLOAD; sp->name = scn->s_name; - sp->offset = scn->s_scnptr; + sp->id = i; + sp->seek = scn->s_scnptr; sp->size = scn->s_size; sp->type = type; sp->flags = sflags; diff --git a/src/libmach/coff32/coff32getsyms.c b/src/libmach/coff32/coff32getsyms.c @@ -84,6 +84,7 @@ coff32getsyms(Obj *obj) sym->type = t; sym->value = ent->n_value; sym->size = (sym->type == 'C') ? ent->n_value : 0; + sym->sect = ent->n_scnum-1; } return i;