Commit 0e25c1dc authored by Russ Cox's avatar Russ Cox

linker work

 * remove now-unused D_SBIG (was for typestrings)
 * rename elf64.[ch] to elf.[ch]
 * pull in elf headers from FreeBSD instead of writing our own
 * emit non-header ELF data in data section
 * stub out a few more ELF sections needed for dynamic loading

R=r
DELTA=1928  (1237 added, 635 deleted, 56 changed)
OCL=33642
CL=33658
parent ef45e64a
...@@ -822,7 +822,7 @@ enum ...@@ -822,7 +822,7 @@ enum
D_INDIR, /* additive */ D_INDIR, /* additive */
D_SBIG = D_INDIR + D_INDIR, D_SIZE = D_INDIR + D_INDIR, /* 6l internal */
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
......
...@@ -10,7 +10,7 @@ TARG=\ ...@@ -10,7 +10,7 @@ TARG=\
OFILES=\ OFILES=\
asm.$O\ asm.$O\
compat.$O\ compat.$O\
elf64.$O\ elf.$O\
enam.$O\ enam.$O\
go.$O\ go.$O\
list.$O\ list.$O\
...@@ -22,7 +22,7 @@ OFILES=\ ...@@ -22,7 +22,7 @@ OFILES=\
HFILES=\ HFILES=\
l.h\ l.h\
../6l/6.out.h\ ../6l/6.out.h\
../ld/elf64.h\ ../ld/elf.h\
../6l/compat.h\ ../6l/compat.h\
...@@ -42,4 +42,4 @@ install: $(TARG) ...@@ -42,4 +42,4 @@ install: $(TARG)
go.o: ../ld/go.c go.o: ../ld/go.c
elf64.o: ../ld/elf64.c elf.o: ../ld/elf.c
This diff is collapsed.
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "l.h" #include "l.h"
#include "../ld/elf64.c" #include "../ld/elf.c"
...@@ -120,6 +120,7 @@ struct Sym ...@@ -120,6 +120,7 @@ struct Sym
uchar dupok; uchar dupok;
uchar reachable; uchar reachable;
vlong value; vlong value;
vlong size;
int32 sig; int32 sig;
Sym* link; Sym* link;
Prog* text; Prog* text;
...@@ -358,6 +359,7 @@ EXTERN char* EXPTAB; ...@@ -358,6 +359,7 @@ EXTERN char* EXPTAB;
EXTERN Prog undefp; EXTERN Prog undefp;
EXTERN vlong textstksiz; EXTERN vlong textstksiz;
EXTERN vlong textarg; EXTERN vlong textarg;
extern char thechar;
#define UP (&undefp) #define UP (&undefp)
...@@ -373,6 +375,11 @@ int Sconv(Fmt*); ...@@ -373,6 +375,11 @@ int Sconv(Fmt*);
void addhist(int32, int); void addhist(int32, int);
void addstackmark(void); void addstackmark(void);
Prog* appendp(Prog*); Prog* appendp(Prog*);
vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*);
vlong addsize(Sym*, Sym*);
void asmb(void); void asmb(void);
void asmdyn(void); void asmdyn(void);
void asmins(Prog*); void asmins(Prog*);
...@@ -392,6 +399,7 @@ void deadcode(void); ...@@ -392,6 +399,7 @@ void deadcode(void);
void diag(char*, ...); void diag(char*, ...);
void dobss(void); void dobss(void);
void dodata(void); void dodata(void);
void doelf(void);
void doinit(void); void doinit(void);
void doprof1(void); void doprof1(void);
void doprof2(void); void doprof2(void);
...@@ -438,6 +446,7 @@ void strnput(char*, int); ...@@ -438,6 +446,7 @@ void strnput(char*, int);
void undef(void); void undef(void);
void undefsym(Sym*); void undefsym(Sym*);
vlong vaddr(Adr*); vlong vaddr(Adr*);
vlong symaddr(Sym*);
void vputl(uint64); void vputl(uint64);
void wputb(uint16); void wputb(uint16);
void wputl(uint16); void wputl(uint16);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/elf64.h" #include "../ld/elf.h"
#include <ar.h> #include <ar.h>
char *noname = "<none>"; char *noname = "<none>";
...@@ -197,7 +197,8 @@ main(int argc, char *argv[]) ...@@ -197,7 +197,8 @@ main(int argc, char *argv[])
INITRND = 4096; INITRND = 4096;
break; break;
case 7: /* elf64 executable */ case 7: /* elf64 executable */
HEADR = ELF64RESERVE; elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = (1<<22)+HEADR; INITTEXT = (1<<22)+HEADR;
if(INITDAT == -1) if(INITDAT == -1)
...@@ -389,6 +390,7 @@ main(int argc, char *argv[]) ...@@ -389,6 +390,7 @@ main(int argc, char *argv[])
patch(); patch();
follow(); follow();
doelf();
dodata(); dodata();
dobss(); dobss();
dostkoff(); dostkoff();
...@@ -438,7 +440,6 @@ loop: ...@@ -438,7 +440,6 @@ loop:
void void
errorexit(void) errorexit(void)
{ {
if(nerrors) { if(nerrors) {
if(cout >= 0) if(cout >= 0)
remove(outfile); remove(outfile);
......
...@@ -73,7 +73,7 @@ dodata(void) ...@@ -73,7 +73,7 @@ dodata(void)
if(s->type != SBSS) if(s->type != SBSS)
continue; continue;
t = s->value; t = s->value;
if(t == 0) { if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name); diag("%s: no size", s->name);
t = 1; t = 1;
} }
...@@ -83,6 +83,7 @@ dodata(void) ...@@ -83,6 +83,7 @@ dodata(void)
continue; continue;
if(t >= 8) if(t >= 8)
datsize = rnd(datsize, 8); datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize; s->value = datsize;
datsize += t; datsize += t;
s->type = SDATA1; s->type = SDATA1;
...@@ -101,6 +102,7 @@ dodata(void) ...@@ -101,6 +102,7 @@ dodata(void)
t = s->value; t = s->value;
if(t >= 8) if(t >= 8)
datsize = rnd(datsize, 8); datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize; s->value = datsize;
datsize += t; datsize += t;
} }
...@@ -124,6 +126,7 @@ dodata(void) ...@@ -124,6 +126,7 @@ dodata(void)
if(t > u) if(t > u)
continue; continue;
u -= t; u -= t;
s->size = t;
s->value = datsize; s->value = datsize;
s->type = SDATA; s->type = SDATA;
datsize += t; datsize += t;
...@@ -148,6 +151,7 @@ dobss(void) ...@@ -148,6 +151,7 @@ dobss(void)
if(s->type != SBSS) if(s->type != SBSS)
continue; continue;
t = s->value; t = s->value;
s->size = t;
if(t >= 8) if(t >= 8)
bsssize = rnd(bsssize, 8); bsssize = rnd(bsssize, 8);
s->value = bsssize + datsize; s->value = bsssize + datsize;
......
...@@ -185,7 +185,7 @@ putsymb(char *s, int t, vlong v, int ver, Sym *go) ...@@ -185,7 +185,7 @@ putsymb(char *s, int t, vlong v, int ver, Sym *go)
gv = 0; gv = 0;
if(go) { if(go) {
if(!go->reachable) if(!go->reachable)
sysfatal("unreachable type %s", go->name); diag("unreachable type %s", go->name);
gv = go->value+INITDAT; gv = go->value+INITDAT;
} }
if(l == 8) if(l == 8)
...@@ -268,7 +268,6 @@ asmsym(void) ...@@ -268,7 +268,6 @@ asmsym(void)
/* frame, auto and param after */ /* frame, auto and param after */
putsymb(".frame", 'm', p->to.offset+8, 0, 0); putsymb(".frame", 'm', p->to.offset+8, 0, 0);
/* TODO(rsc): Add types for D_AUTO and D_PARAM */
for(a=p->to.autom; a; a=a->link) for(a=p->to.autom; a; a=a->link)
if(a->type == D_AUTO) if(a->type == D_AUTO)
putsymb(a->asym->name, 'a', -a->aoffset, 0, a->gotype); putsymb(a->asym->name, 'a', -a->aoffset, 0, a->gotype);
...@@ -673,6 +672,18 @@ put8(vlong v) ...@@ -673,6 +672,18 @@ put8(vlong v)
andptr += 8; andptr += 8;
} }
vlong
symaddr(Sym *s)
{
Adr a;
a.type = D_ADDR;
a.index = D_EXTERN;
a.offset = 0;
a.sym = s;
return vaddr(&a);
}
vlong vlong
vaddr(Adr *a) vaddr(Adr *a)
{ {
...@@ -697,14 +708,14 @@ vaddr(Adr *a) ...@@ -697,14 +708,14 @@ vaddr(Adr *a)
case STEXT: case STEXT:
case SCONST: case SCONST:
if(!s->reachable) if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name); diag("unreachable symbol in vaddr - %s", s->name);
if((uvlong)s->value < (uvlong)INITTEXT) if((uvlong)s->value < (uvlong)INITTEXT)
v += INITTEXT; /* TO DO */ v += INITTEXT; /* TO DO */
v += s->value; v += s->value;
break; break;
default: default:
if(!s->reachable) if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name); diag("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value; v += INITDAT + s->value;
} }
} }
......
...@@ -449,8 +449,7 @@ enum ...@@ -449,8 +449,7 @@ enum
D_INDIR, /* additive */ D_INDIR, /* additive */
D_SBIG = D_INDIR + D_INDIR, D_CONST2 = D_INDIR+D_INDIR,
D_CONST2,
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
......
...@@ -700,7 +700,7 @@ datblk(int32 s, int32 n) ...@@ -700,7 +700,7 @@ datblk(int32 s, int32 n)
for(p = datap; p != P; p = p->link) { for(p = datap; p != P; p = p->link) {
curp = p; curp = p;
if(!p->from.sym->reachable) if(!p->from.sym->reachable)
sysfatal("unreachable symbol in datblk - %s", p->from.sym->name); diag("unreachable symbol in datblk - %s", p->from.sym->name);
l = p->from.sym->value + p->from.offset - s; l = p->from.sym->value + p->from.offset - s;
c = p->from.scale; c = p->from.scale;
i = 0; i = 0;
...@@ -769,19 +769,6 @@ datblk(int32 s, int32 n) ...@@ -769,19 +769,6 @@ datblk(int32 s, int32 n)
} }
break; break;
case D_SBIG:
if(debug['a'] && i == 0) {
Bprint(&bso, pcstr, l+s+INITDAT);
for(j=0; j<c; j++)
Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
Bprint(&bso, "\t%P\n", curp);
}
for(; i<c; i++) {
buf.dbuf[l] = p->to.sbig[i];
l++;
}
break;
default: default:
fl = p->to.offset; fl = p->to.offset;
if(p->to.type == D_ADDR) { if(p->to.type == D_ADDR) {
......
...@@ -2,35 +2,52 @@ ...@@ -2,35 +2,52 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Support for 64-bit Elf binaries #include "../ld/elf.h"
#include "../ld/elf64.h"
/*
* We use the 64-bit data structures on both 32- and 64-bit machines
* in order to write the code just once. The 64-bit data structure is
* written in the 32-bit format on the 32-bit machines.
*/
#define NSECT 16 #define NSECT 16
static int numstr;
static int stroffset; static int elf64;
static Elf64Hdr hdr; static Elf64_Ehdr hdr;
static Elf64PHdr *phdr[NSECT]; static Elf64_Phdr *phdr[NSECT];
static Elf64SHdr *shdr[NSECT]; static Elf64_Shdr *shdr[NSECT];
static char *sname[NSECT]; static char *sname[NSECT];
static char *str[20];
/* /*
Initialize the global variable that describes the ELF header. It will be updated as Initialize the global variable that describes the ELF header. It will be updated as
we write section and prog headers. we write section and prog headers.
*/ */
void void
elf64init(void) elfinit(void)
{ {
hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */ switch(thechar) {
hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */ // 64-bit architectures
hdr.ehsize = ELF64HDRSIZE; /* Must be ELF64HDRSIZE */ case '6':
hdr.phentsize = ELF64PHDRSIZE; /* Must be ELF64PHDRSIZE */ elf64 = 1;
hdr.shentsize = ELF64SHDRSIZE; /* Must be ELF64SHDRSIZE */ hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */
hdr.ehsize = ELF64HDRSIZE; /* Must be ELF64HDRSIZE */
hdr.phentsize = ELF64PHDRSIZE; /* Must be ELF64PHDRSIZE */
hdr.shentsize = ELF64SHDRSIZE; /* Must be ELF64SHDRSIZE */
break;
// 32-bit architectures
default:
hdr.phoff = ELF32HDRSIZE; /* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
hdr.shoff = ELF32HDRSIZE; /* Will move as we add PHeaders */
hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */
hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */
hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */
}
} }
void void
elf64phdr(Elf64PHdr *e) elf64phdr(Elf64_Phdr *e)
{ {
LPUT(e->type); LPUT(e->type);
LPUT(e->flags); LPUT(e->flags);
...@@ -43,7 +60,7 @@ elf64phdr(Elf64PHdr *e) ...@@ -43,7 +60,7 @@ elf64phdr(Elf64PHdr *e)
} }
void void
elf64shdr(char *name, Elf64SHdr *e) elf64shdr(char *name, Elf64_Shdr *e)
{ {
LPUT(e->name); LPUT(e->name);
LPUT(e->type); LPUT(e->type);
...@@ -57,44 +74,6 @@ elf64shdr(char *name, Elf64SHdr *e) ...@@ -57,44 +74,6 @@ elf64shdr(char *name, Elf64SHdr *e)
VPUT(e->entsize); VPUT(e->entsize);
} }
int
putelf64strtab(char* name)
{
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
void
elf64writestrtable(void)
{
int i;
uint32 size;
size = 0;
for (i = 0; i < numstr; i++)
size += putelf64strtab(str[i]);
if (size > STRTABSIZE)
diag("elf64 string table overflow");
}
uint32
elf64addstr(char *name)
{
int r;
if (numstr >= nelem(str)) {
diag("too many elf strings");
return 0;
}
str[numstr++] = strdup(name);
r = stroffset;
stroffset += strlen(name)+1;
return r;
}
uint32 uint32
elf64writeshdrs(void) elf64writeshdrs(void)
{ {
...@@ -115,10 +94,10 @@ elf64writephdrs(void) ...@@ -115,10 +94,10 @@ elf64writephdrs(void)
return hdr.phnum * ELF64PHDRSIZE; return hdr.phnum * ELF64PHDRSIZE;
} }
Elf64PHdr* Elf64_Phdr*
newElf64PHdr(void) newElf64_Phdr(void)
{ {
Elf64PHdr *e; Elf64_Phdr *e;
e = malloc(sizeof *e); e = malloc(sizeof *e);
memset(e, 0, sizeof *e); memset(e, 0, sizeof *e);
...@@ -130,16 +109,21 @@ newElf64PHdr(void) ...@@ -130,16 +109,21 @@ newElf64PHdr(void)
return e; return e;
} }
Elf64SHdr* Elf64_Shdr*
newElf64SHdr(char *name) newElf64_Shstrtab(vlong name)
{ {
Elf64SHdr *e; hdr.shstrndx = hdr.shnum;
return newElf64_Shdr(name);
}
Elf64_Shdr*
newElf64_Shdr(vlong name)
{
Elf64_Shdr *e;
if (strcmp(name, ".shstrtab") == 0)
hdr.shstrndx = hdr.shnum;
e = malloc(sizeof *e); e = malloc(sizeof *e);
memset(e, 0, sizeof *e); memset(e, 0, sizeof *e);
e->name = elf64addstr(name); e->name = name;
if (hdr.shnum >= NSECT) { if (hdr.shnum >= NSECT) {
diag("too many shdrs"); diag("too many shdrs");
} else { } else {
...@@ -148,8 +132,8 @@ newElf64SHdr(char *name) ...@@ -148,8 +132,8 @@ newElf64SHdr(char *name)
return e; return e;
} }
Elf64Hdr* Elf64_Ehdr*
getElf64Hdr(void) getElf64_Ehdr(void)
{ {
return &hdr; return &hdr;
} }
...@@ -192,41 +176,33 @@ elf64_hash(uchar *name) ...@@ -192,41 +176,33 @@ elf64_hash(uchar *name)
} }
void void
elf64writedynent(int tag, uint64 val) elfwritedynent(Sym *s, int tag, uint64 val)
{ {
VPUT(tag); if(elf64) {
VPUT(val); adduint64(s, tag);
adduint64(s, val);
} else {
adduint32(s, tag);
adduint32(s, val);
}
} }
/* Where to write the next piece of data attached to an SHeader */ void
uint64 elfaddr = ELF64FULLHDRSIZE; elfwritedynentsym(Sym *s, int tag, Sym *t)
/* Mark a start location in the SHeader data */
uint64
startelf(void)
{ {
seek(cout, elfaddr, 0); if(elf64)
return elfaddr; adduint64(s, tag);
else
adduint32(s, tag);
addaddr(s, t);
} }
/* Mark the end of a location in the SHeader data */ void
uint64 elfwritedynentsymsize(Sym *s, int tag, Sym *t)
endelf(void)
{ {
uint64 p; if(elf64)
adduint64(s, tag);
cflush(); else
p = seek(cout, 0, 1); adduint32(s, tag);
if (p < elfaddr) { addsize(s, t);
diag("endelf before elfaddr");
}
if ((p & 7) != 0) {
p = (p + 7) & ~7LL;
seek(cout, p, 0);
}
elfaddr = p;
if (p > ELF64RESERVE) {
diag("endelf overflows reserve %lld\n", p);
}
return elfaddr;
} }
This diff is collapsed.
This diff is collapsed.
...@@ -325,6 +325,8 @@ marktext(Prog *p) ...@@ -325,6 +325,8 @@ marktext(Prog *p)
markdepth++; markdepth++;
if(debug['v'] > 1) if(debug['v'] > 1)
Bprint(&bso, "%d marktext %s\n", markdepth, p->from.sym->name); Bprint(&bso, "%d marktext %s\n", markdepth, p->from.sym->name);
for(a=p->to.autom; a; a=a->link)
mark(a->gotype);
for(p=p->link; p != P; p=p->link) { for(p=p->link; p != P; p=p->link) {
if(p->as == ATEXT || p->as == ADATA || p->as == AGLOBL) if(p->as == ATEXT || p->as == ADATA || p->as == AGLOBL)
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment