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
D_INDIR, /* additive */
D_SBIG = D_INDIR + D_INDIR,
D_SIZE = D_INDIR + D_INDIR, /* 6l internal */
T_TYPE = 1<<0,
T_INDEX = 1<<1,
......
......@@ -10,7 +10,7 @@ TARG=\
OFILES=\
asm.$O\
compat.$O\
elf64.$O\
elf.$O\
enam.$O\
go.$O\
list.$O\
......@@ -22,7 +22,7 @@ OFILES=\
HFILES=\
l.h\
../6l/6.out.h\
../ld/elf64.h\
../ld/elf.h\
../6l/compat.h\
......@@ -42,4 +42,4 @@ install: $(TARG)
go.o: ../ld/go.c
elf64.o: ../ld/elf64.c
elf.o: ../ld/elf.c
This diff is collapsed.
......@@ -3,4 +3,4 @@
// license that can be found in the LICENSE file.
#include "l.h"
#include "../ld/elf64.c"
#include "../ld/elf.c"
......@@ -120,6 +120,7 @@ struct Sym
uchar dupok;
uchar reachable;
vlong value;
vlong size;
int32 sig;
Sym* link;
Prog* text;
......@@ -358,6 +359,7 @@ EXTERN char* EXPTAB;
EXTERN Prog undefp;
EXTERN vlong textstksiz;
EXTERN vlong textarg;
extern char thechar;
#define UP (&undefp)
......@@ -373,6 +375,11 @@ int Sconv(Fmt*);
void addhist(int32, int);
void addstackmark(void);
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 asmdyn(void);
void asmins(Prog*);
......@@ -392,6 +399,7 @@ void deadcode(void);
void diag(char*, ...);
void dobss(void);
void dodata(void);
void doelf(void);
void doinit(void);
void doprof1(void);
void doprof2(void);
......@@ -438,6 +446,7 @@ void strnput(char*, int);
void undef(void);
void undefsym(Sym*);
vlong vaddr(Adr*);
vlong symaddr(Sym*);
void vputl(uint64);
void wputb(uint16);
void wputl(uint16);
......
......@@ -30,7 +30,7 @@
#define EXTERN
#include "l.h"
#include "../ld/elf64.h"
#include "../ld/elf.h"
#include <ar.h>
char *noname = "<none>";
......@@ -197,7 +197,8 @@ main(int argc, char *argv[])
INITRND = 4096;
break;
case 7: /* elf64 executable */
HEADR = ELF64RESERVE;
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
INITTEXT = (1<<22)+HEADR;
if(INITDAT == -1)
......@@ -389,6 +390,7 @@ main(int argc, char *argv[])
patch();
follow();
doelf();
dodata();
dobss();
dostkoff();
......@@ -438,7 +440,6 @@ loop:
void
errorexit(void)
{
if(nerrors) {
if(cout >= 0)
remove(outfile);
......
......@@ -73,7 +73,7 @@ dodata(void)
if(s->type != SBSS)
continue;
t = s->value;
if(t == 0) {
if(t == 0 && s->name[0] != '.') {
diag("%s: no size", s->name);
t = 1;
}
......@@ -83,6 +83,7 @@ dodata(void)
continue;
if(t >= 8)
datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize;
datsize += t;
s->type = SDATA1;
......@@ -101,6 +102,7 @@ dodata(void)
t = s->value;
if(t >= 8)
datsize = rnd(datsize, 8);
s->size = t;
s->value = datsize;
datsize += t;
}
......@@ -124,6 +126,7 @@ dodata(void)
if(t > u)
continue;
u -= t;
s->size = t;
s->value = datsize;
s->type = SDATA;
datsize += t;
......@@ -148,6 +151,7 @@ dobss(void)
if(s->type != SBSS)
continue;
t = s->value;
s->size = t;
if(t >= 8)
bsssize = rnd(bsssize, 8);
s->value = bsssize + datsize;
......
......@@ -185,7 +185,7 @@ putsymb(char *s, int t, vlong v, int ver, Sym *go)
gv = 0;
if(go) {
if(!go->reachable)
sysfatal("unreachable type %s", go->name);
diag("unreachable type %s", go->name);
gv = go->value+INITDAT;
}
if(l == 8)
......@@ -268,7 +268,6 @@ asmsym(void)
/* frame, auto and param after */
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)
if(a->type == D_AUTO)
putsymb(a->asym->name, 'a', -a->aoffset, 0, a->gotype);
......@@ -673,6 +672,18 @@ put8(vlong v)
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
vaddr(Adr *a)
{
......@@ -697,14 +708,14 @@ vaddr(Adr *a)
case STEXT:
case SCONST:
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)
v += INITTEXT; /* TO DO */
v += s->value;
break;
default:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
diag("unreachable symbol in vaddr - %s", s->name);
v += INITDAT + s->value;
}
}
......
......@@ -449,8 +449,7 @@ enum
D_INDIR, /* additive */
D_SBIG = D_INDIR + D_INDIR,
D_CONST2,
D_CONST2 = D_INDIR+D_INDIR,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
......
......@@ -700,7 +700,7 @@ datblk(int32 s, int32 n)
for(p = datap; p != P; p = p->link) {
curp = p;
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;
c = p->from.scale;
i = 0;
......@@ -769,19 +769,6 @@ datblk(int32 s, int32 n)
}
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:
fl = p->to.offset;
if(p->to.type == D_ADDR) {
......
......@@ -2,35 +2,52 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Support for 64-bit Elf binaries
#include "../ld/elf64.h"
#include "../ld/elf.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
static int numstr;
static int stroffset;
static Elf64Hdr hdr;
static Elf64PHdr *phdr[NSECT];
static Elf64SHdr *shdr[NSECT];
static int elf64;
static Elf64_Ehdr hdr;
static Elf64_Phdr *phdr[NSECT];
static Elf64_Shdr *shdr[NSECT];
static char *sname[NSECT];
static char *str[20];
/*
Initialize the global variable that describes the ELF header. It will be updated as
we write section and prog headers.
*/
void
elf64init(void)
{
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 */
elfinit(void)
{
switch(thechar) {
// 64-bit architectures
case '6':
elf64 = 1;
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
elf64phdr(Elf64PHdr *e)
elf64phdr(Elf64_Phdr *e)
{
LPUT(e->type);
LPUT(e->flags);
......@@ -43,7 +60,7 @@ elf64phdr(Elf64PHdr *e)
}
void
elf64shdr(char *name, Elf64SHdr *e)
elf64shdr(char *name, Elf64_Shdr *e)
{
LPUT(e->name);
LPUT(e->type);
......@@ -57,44 +74,6 @@ elf64shdr(char *name, Elf64SHdr *e)
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
elf64writeshdrs(void)
{
......@@ -115,10 +94,10 @@ elf64writephdrs(void)
return hdr.phnum * ELF64PHDRSIZE;
}
Elf64PHdr*
newElf64PHdr(void)
Elf64_Phdr*
newElf64_Phdr(void)
{
Elf64PHdr *e;
Elf64_Phdr *e;
e = malloc(sizeof *e);
memset(e, 0, sizeof *e);
......@@ -130,16 +109,21 @@ newElf64PHdr(void)
return e;
}
Elf64SHdr*
newElf64SHdr(char *name)
Elf64_Shdr*
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);
memset(e, 0, sizeof *e);
e->name = elf64addstr(name);
e->name = name;
if (hdr.shnum >= NSECT) {
diag("too many shdrs");
} else {
......@@ -148,8 +132,8 @@ newElf64SHdr(char *name)
return e;
}
Elf64Hdr*
getElf64Hdr(void)
Elf64_Ehdr*
getElf64_Ehdr(void)
{
return &hdr;
}
......@@ -192,41 +176,33 @@ elf64_hash(uchar *name)
}
void
elf64writedynent(int tag, uint64 val)
elfwritedynent(Sym *s, int tag, uint64 val)
{
VPUT(tag);
VPUT(val);
if(elf64) {
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 */
uint64 elfaddr = ELF64FULLHDRSIZE;
/* Mark a start location in the SHeader data */
uint64
startelf(void)
void
elfwritedynentsym(Sym *s, int tag, Sym *t)
{
seek(cout, elfaddr, 0);
return elfaddr;
if(elf64)
adduint64(s, tag);
else
adduint32(s, tag);
addaddr(s, t);
}
/* Mark the end of a location in the SHeader data */
uint64
endelf(void)
void
elfwritedynentsymsize(Sym *s, int tag, Sym *t)
{
uint64 p;
cflush();
p = seek(cout, 0, 1);
if (p < elfaddr) {
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;
if(elf64)
adduint64(s, tag);
else
adduint32(s, tag);
addsize(s, t);
}
This diff is collapsed.
This diff is collapsed.
......@@ -325,6 +325,8 @@ marktext(Prog *p)
markdepth++;
if(debug['v'] > 1)
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) {
if(p->as == ATEXT || p->as == ADATA || p->as == AGLOBL)
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