mirror of https://github.com/golang/go.git
make 6l produce dynamically linked binaries (although they are fully statically linked as far
as go is concerned). the -d flag is now flipped; as on the mac, -d disables dynamic. much remains to be improved to move the output closer to the gcc format. R=rsc DELTA=366 (310 added, 30 deleted, 26 changed) OCL=31929 CL=31951
This commit is contained in:
parent
ff790f4704
commit
3d42e691b9
211
src/cmd/6l/asm.c
211
src/cmd/6l/asm.c
|
|
@ -35,6 +35,10 @@
|
|||
|
||||
#define PADDR(a) ((uint32)(a) & ~0x80000000)
|
||||
|
||||
char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
|
||||
|
||||
char zeroes[32];
|
||||
|
||||
vlong
|
||||
entryvalue(void)
|
||||
{
|
||||
|
|
@ -124,11 +128,11 @@ asmb(void)
|
|||
int32 v, magic;
|
||||
int a, nl;
|
||||
uchar *op1;
|
||||
vlong vl, va, fo, w, symo;
|
||||
vlong vl, va, startva, fo, w, symo, hashoff;
|
||||
vlong symdatva = 0x99LL<<32;
|
||||
Elf64Hdr *eh;
|
||||
Elf64PHdr *ph;
|
||||
Elf64SHdr *sh;
|
||||
Elf64PHdr *ph, *pph;
|
||||
Elf64SHdr *sh, *dynsh;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
|
|
@ -237,7 +241,7 @@ asmb(void)
|
|||
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
|
||||
break;
|
||||
case 7:
|
||||
symo = rnd(HEADR+textsize, INITRND)+datsize+STRTABSIZE;
|
||||
symo = rnd(HEADR+textsize, INITRND)+datsize;
|
||||
symo = rnd(symo, INITRND);
|
||||
break;
|
||||
}
|
||||
|
|
@ -419,16 +423,132 @@ asmb(void)
|
|||
/* elf amd-64 */
|
||||
|
||||
fo = 0;
|
||||
va = INITTEXT & ~((vlong)INITRND - 1);
|
||||
startva = INITTEXT - HEADR;
|
||||
va = startva;
|
||||
w = HEADR+textsize;
|
||||
|
||||
/* This null SHdr must appear before all others */
|
||||
sh = newElf64SHdr("");
|
||||
|
||||
pph = nil; /* silence compiler */
|
||||
|
||||
/* Dynamic linking sections */
|
||||
if (!debug['d']) { /* -d suppresses dynamic loader format */
|
||||
|
||||
/* P headers */
|
||||
/* program header info */
|
||||
pph = newElf64PHdr();
|
||||
pph->type = PT_PHDR;
|
||||
pph->flags = PF_R + PF_X;
|
||||
pph->off = ELF64HDRSIZE;
|
||||
pph->vaddr = startva + pph->off;
|
||||
pph->paddr = startva + pph->off;
|
||||
pph->align = 8;
|
||||
|
||||
/* interpreter */
|
||||
ph = newElf64PHdr();
|
||||
ph->type = PT_INTERP;
|
||||
ph->flags = PF_R;
|
||||
ph->off = startelf();
|
||||
ph->vaddr = startva;
|
||||
ph->paddr = startva;
|
||||
write(cout, linuxdynld, sizeof linuxdynld);
|
||||
ph->filesz = endelf() - ph->off;
|
||||
ph->align = 1;
|
||||
|
||||
/* dynamic load section */
|
||||
ph = newElf64PHdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_R + PF_W;
|
||||
ph->off = 0;
|
||||
ph->vaddr = startva + ph->off;
|
||||
ph->paddr = startva + ph->off;
|
||||
ph->align = 8;
|
||||
|
||||
/* S headers inside dynamic load section */
|
||||
dynsh = newElf64SHdr(".dynamic"); // must be first
|
||||
dynsh->off = startelf();
|
||||
|
||||
seek(cout, ELFDYNAMICSIZE, 1); // leave room for dynamic table
|
||||
|
||||
sh = newElf64SHdr(".hash");
|
||||
sh->type = SHT_HASH;
|
||||
sh->flags = SHF_ALLOC;
|
||||
sh->entsize = 4;
|
||||
sh->addr = va;
|
||||
sh->off = seek(cout, 0, 1);
|
||||
hashoff = sh->off;
|
||||
sh->addr = startva + sh->off;
|
||||
/* temporary hack: 8 zeroes means 0 buckets, 0 chains */
|
||||
write(cout, zeroes, 8);
|
||||
sh->size = endelf() - sh->off;
|
||||
sh->addralign = 8;
|
||||
|
||||
sh = newElf64SHdr(".got");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 8;
|
||||
sh->addr = va;
|
||||
sh->off = startelf();
|
||||
sh->addr = startva + sh->off;
|
||||
sh->size = endelf() - sh->off;
|
||||
sh->addralign = 8;
|
||||
|
||||
sh = newElf64SHdr(".got.plt");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
sh->entsize = 8;
|
||||
sh->addr = va;
|
||||
sh->off = startelf();
|
||||
sh->addr = startva + sh->off;
|
||||
sh->size = endelf() - sh->off;
|
||||
sh->addralign = 8;
|
||||
|
||||
/* +8 necessary for now to silence readelf addressing at end of hash section */
|
||||
ph->filesz = endelf() - ph->off +8; /* dynamic section maps these shdrs' data */
|
||||
ph->memsz = ph->filesz;
|
||||
|
||||
dynsh->type = SHT_DYNAMIC;
|
||||
dynsh->flags = SHF_ALLOC+SHF_WRITE;
|
||||
dynsh->entsize = 16;
|
||||
dynsh->addr = startva + dynsh->off;
|
||||
seek(cout, dynsh->off, 0);
|
||||
elf64writedynent(DT_HASH, startva+hashoff);
|
||||
elf64writedynent(DT_STRTAB, startva+ELF64FULLHDRSIZE-STRTABSIZE);
|
||||
elf64writedynent(DT_SYMTAB, startva);
|
||||
elf64writedynent(DT_RELA, startva);
|
||||
elf64writedynent(DT_RELASZ, 0); // size of the whole rela in bytes
|
||||
elf64writedynent(DT_RELAENT, ELF64RELASIZE);
|
||||
elf64writedynent(DT_STRSZ, STRTABSIZE);
|
||||
elf64writedynent(DT_SYMENT, 0);
|
||||
elf64writedynent(DT_REL, startva);
|
||||
elf64writedynent(DT_RELSZ, 0);
|
||||
elf64writedynent(DT_RELENT, ELF64RELSIZE);
|
||||
elf64writedynent(DT_NULL, 0);
|
||||
cflush();
|
||||
dynsh->size = seek(cout, 0, 1) - dynsh->off;
|
||||
dynsh->addralign = 8;
|
||||
|
||||
/* dynamic section */
|
||||
ph = newElf64PHdr();
|
||||
ph->type = PT_DYNAMIC;
|
||||
ph->flags = PF_R + PF_W;
|
||||
ph->off = dynsh->off;
|
||||
ph->filesz = dynsh->size;
|
||||
ph->memsz = dynsh->size;
|
||||
ph->vaddr = startva + ph->off;
|
||||
ph->paddr = startva + ph->off;
|
||||
ph->align = 8;
|
||||
}
|
||||
|
||||
ph = newElf64PHdr();
|
||||
ph->type = PT_LOAD;
|
||||
ph->type = PT_LOAD;
|
||||
ph->flags = PF_X+PF_R;
|
||||
ph->vaddr = va;
|
||||
ph->paddr = va;
|
||||
ph->filesz = w;
|
||||
ph->memsz = w;
|
||||
ph->vaddr = va + ELF64RESERVE;
|
||||
ph->paddr = va + ELF64RESERVE;
|
||||
ph->off = ELF64RESERVE;
|
||||
ph->filesz = w - ELF64RESERVE;
|
||||
ph->memsz = w - ELF64RESERVE;
|
||||
ph->align = INITRND;
|
||||
|
||||
fo = rnd(fo+w, INITRND);
|
||||
|
|
@ -462,11 +582,8 @@ asmb(void)
|
|||
ph->flags = PF_X+PF_W+PF_R;
|
||||
ph->align = 8;
|
||||
|
||||
sh = newElf64SHdr("");
|
||||
|
||||
stroffset = 1; /* 0 means no name, so start at 1 */
|
||||
fo = HEADR;
|
||||
va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
|
||||
fo = ELF64RESERVE;
|
||||
va = startva + fo;
|
||||
w = textsize;
|
||||
|
||||
sh = newElf64SHdr(".text");
|
||||
|
|
@ -501,38 +618,37 @@ asmb(void)
|
|||
sh->size = w;
|
||||
sh->addralign = 8;
|
||||
|
||||
w = STRTABSIZE;
|
||||
if (!debug['s']) {
|
||||
fo = symo+8;
|
||||
w = symsize;
|
||||
|
||||
sh = newElf64SHdr(".gosymtab");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
sh->entsize = 24;
|
||||
|
||||
fo += w;
|
||||
w = lcsize;
|
||||
|
||||
sh = newElf64SHdr(".gopclntab");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
sh->entsize = 24;
|
||||
}
|
||||
|
||||
sh = newElf64SHdr(".shstrtab");
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->off = startelf();
|
||||
sh->addr = sh->off + startva;
|
||||
sh->addralign = 1;
|
||||
elf64writestrtable();
|
||||
sh->size = endelf() - sh->off;
|
||||
|
||||
if (debug['s'])
|
||||
break;
|
||||
|
||||
fo = symo+8;
|
||||
w = symsize;
|
||||
|
||||
sh = newElf64SHdr(".gosymtab");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
sh->entsize = 24;
|
||||
|
||||
fo += w;
|
||||
w = lcsize;
|
||||
|
||||
sh = newElf64SHdr(".gopclntab");
|
||||
sh->type = SHT_PROGBITS;
|
||||
sh->off = fo;
|
||||
sh->size = w;
|
||||
sh->addralign = 1;
|
||||
sh->entsize = 24;
|
||||
|
||||
// main header */
|
||||
/* Main header */
|
||||
eh = getElf64Hdr();
|
||||
eh->ident[EI_MAG0] = '\177';
|
||||
eh->ident[EI_MAG1] = 'E';
|
||||
|
|
@ -547,6 +663,12 @@ asmb(void)
|
|||
eh->version = EV_CURRENT;
|
||||
eh->entry = entryvalue();
|
||||
|
||||
if (!debug['d']) {
|
||||
pph->filesz = eh->phnum * ELF64PHDRSIZE;
|
||||
pph->memsz = pph->filesz;
|
||||
}
|
||||
|
||||
seek(cout, 0, 0);
|
||||
a = 0;
|
||||
a += elf64writehdr();
|
||||
a += elf64writephdrs();
|
||||
|
|
@ -556,11 +678,6 @@ asmb(void)
|
|||
}
|
||||
cflush();
|
||||
|
||||
/* string table */
|
||||
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
|
||||
elf64writestrtable();
|
||||
cflush();
|
||||
|
||||
break;
|
||||
}
|
||||
cflush();
|
||||
|
|
|
|||
|
|
@ -353,7 +353,6 @@ EXTERN int imports, nimports;
|
|||
EXTERN int exports, nexports;
|
||||
EXTERN char* EXPTAB;
|
||||
EXTERN Prog undefp;
|
||||
EXTERN uint32 stroffset;
|
||||
EXTERN vlong textstksiz;
|
||||
EXTERN vlong textarg;
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ main(int argc, char *argv[])
|
|||
INITRND = 4096;
|
||||
break;
|
||||
case 7: /* elf64 executable */
|
||||
HEADR = ELF64FULLHDRSIZE;
|
||||
HEADR = ELF64RESERVE;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = (1<<22)+HEADR;
|
||||
if(INITDAT == -1)
|
||||
|
|
|
|||
|
|
@ -8,20 +8,25 @@
|
|||
|
||||
#define NSECT 16
|
||||
static int numstr;
|
||||
static int stroffset;
|
||||
static Elf64Hdr hdr;
|
||||
static Elf64PHdr *phdr[NSECT];
|
||||
static Elf64SHdr *shdr[NSECT];
|
||||
static char *sname[NSECT];
|
||||
static char *str[NSECT];
|
||||
|
||||
/*
|
||||
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;
|
||||
hdr.shoff = ELF64HDRSIZE;
|
||||
hdr.ehsize = ELF64HDRSIZE;
|
||||
hdr.phentsize = ELF64PHDRSIZE;
|
||||
hdr.shentsize = 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 */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -168,3 +173,57 @@ elf64writehdr()
|
|||
WPUT(hdr.shstrndx);
|
||||
return ELF64HDRSIZE;
|
||||
}
|
||||
|
||||
/* Taken directly from the definition document for ELF64 */
|
||||
uint32
|
||||
elf64_hash(uchar *name)
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
if (g = h & 0xf0000000)
|
||||
h ^= g >> 24;
|
||||
h &= 0x0fffffff;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
elf64writedynent(int tag, uint64 val)
|
||||
{
|
||||
VPUT(tag);
|
||||
VPUT(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)
|
||||
{
|
||||
seek(cout, elfaddr, 0);
|
||||
return elfaddr;
|
||||
}
|
||||
|
||||
/* Mark the end of a location in the SHeader data */
|
||||
uint64
|
||||
endelf(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ struct Elf64PHdr
|
|||
#define PT_DYNAMIC 2 /* Dynamic linking tables */
|
||||
#define PT_INTERP 3 /* Program interpreter path name */
|
||||
#define PT_NOTE 4 /* Note sections */
|
||||
#define PT_PHDR 6 /* Program header table */
|
||||
|
||||
/* P flags */
|
||||
#define PF_X 0x1 /* Execute permission */
|
||||
|
|
@ -169,6 +170,103 @@ struct Elf64SHdr
|
|||
#define SHF_MASKOS 0x0F000000 /* Environment-specific use */
|
||||
#define SHF_MASKPROC 0xF0000000 /* Processor-specific use */
|
||||
|
||||
|
||||
typedef struct Elf64Dyn Elf64Dyn;
|
||||
struct Elf64Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union {
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
/* Dyn table entries */
|
||||
#define DT_NULL 0 /* ignored: Marks the end of the dynamic array */
|
||||
#define DT_NEEDED 1 /* d_val: The string table offset of the name of
|
||||
a needed library. */
|
||||
#define DT_PLTRELSZ 2 /* d_val: Total size, in bytes, of the relocation
|
||||
entries associated with the procedure linkage table. */
|
||||
#define DT_PLTGOT 3 /* d_ptr: Contains an address associated with the linkage
|
||||
table. The specific meaning of this field is
|
||||
processor-dependent. */
|
||||
#define DT_HASH 4 /* d_ptr: Address of the symbol hash table. */
|
||||
#define DT_STRTAB 5 /* d_ptr: Address of the dynamic string table. */
|
||||
#define DT_SYMTAB 6 /* d_ptr: Address of the dynamic symbol table. */
|
||||
#define DT_RELA 7 /* d_ptr Address of a relocation table with Elf64_Rela
|
||||
entries. */
|
||||
#define DT_RELASZ 8 /* d_val: Total size, in bytes, of the DT_RELA relocation
|
||||
table. */
|
||||
#define DT_RELAENT 9 /* d_val: Size, in bytes, of each DT_RELA relocation
|
||||
entry. */
|
||||
#define DT_STRSZ 10 /* d_val: Total size, in bytes, of the string table. */
|
||||
#define DT_SYMENT 11 /* d_val: Size, in bytes, of each symbol table entry. */
|
||||
#define DT_INIT 12 /* d_ptr Address of the initialization function. */
|
||||
#define DT_FINI 13 /* d_ptr Address of the termination function. */
|
||||
#define DT_SONAME 14 /* d_val The string table offset of the name of this
|
||||
shared object. */
|
||||
#define DT_RPATH 15 /* d_val The string table offset of a shared library
|
||||
search path string. */
|
||||
#define DT_SYMBOLIC 16 /* ignored The presence of this dynamic table entry
|
||||
modifies the symbol resolution algorithm for references
|
||||
within the library. Symbols defined within the library
|
||||
are used to resolve references before the dynamic
|
||||
linker searches the usual search path. */
|
||||
#define DT_REL 17 /* d_ptr Address of a relocation table with Elf64_Rel
|
||||
entries. */
|
||||
#define DT_RELSZ 18 /* d_val Total size, in bytes, of the DT_REL relocation
|
||||
table. */
|
||||
#define DT_RELENT 19 /* d_val Size, in bytes, of each DT_REL relocation
|
||||
entry. */
|
||||
#define DT_PLTREL 20 /* d_val Type of relocation entry used for the procedure
|
||||
linkage table. The d_val member contains either DT_REL
|
||||
or DT_RELA. */
|
||||
#define DT_DEBUG 21 /* d_ptr Reserved for debugger use. */
|
||||
#define DT_TEXTREL 22 /* ignored The presence of this dynamic table entry
|
||||
signals that the relocation table contains relocations
|
||||
for a non-writable segment. */
|
||||
#define DT_JMPREL 23 /* d_ptr Address of the relocations associated with the
|
||||
procedure linkage table. */
|
||||
#define DT_BIND_NOW 24 /* ignored The presence of this dynamic table entry
|
||||
signals that the dynamic loader should process all
|
||||
relocations for this object before transferring
|
||||
control to the program. */
|
||||
#define DT_INIT_ARRAY 25 /* d_ptr Pointer to an array of pointers to initialization
|
||||
functions. */
|
||||
#define DT_FINI_ARRAY 26 /* d_ptr Pointer to an array of pointers to termination
|
||||
functions. */
|
||||
#define DT_INIT_ARRAYSZ 27 /* d_val Size, in bytes, of the array of initialization
|
||||
functions. */
|
||||
#define DT_FINI_ARRAYSZ 28 /* d_val Size, in bytes, of the array of termination
|
||||
functions. */
|
||||
#define DT_LOOS 0x60000000 /* Defines a range of dynamic table tags that are reserved
|
||||
for environment-specific use. */
|
||||
#define DT_HIOS 0x6FFFFFFF
|
||||
#define DT_LOPROC 0x70000000 /* Defines a range of dynamic table tags that are
|
||||
reserved for processor-specific use. */
|
||||
#define DT_HIPROC 0x7FFFFFFF
|
||||
|
||||
typedef struct Elf64_Rel Elf64_Rel;
|
||||
struct Elf64_Rel
|
||||
{
|
||||
Elf64_Addr r_offset; /* Address of reference */
|
||||
Elf64_Xword r_info; /* Symbol index and type of relocation */
|
||||
};
|
||||
#define ELF64RELSIZE 8
|
||||
|
||||
typedef struct Elf64_Rela Elf64_Rela;
|
||||
struct Elf64_Rela
|
||||
{
|
||||
Elf64_Addr r_offset; /* Address of reference */
|
||||
Elf64_Xword r_info; /* Symbol index and type of relocation */
|
||||
Elf64_Sxword r_addend; /* Constant part of expression */
|
||||
};
|
||||
#define ELF64RELASIZE 24
|
||||
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((i) & 0xffffffffL)
|
||||
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t) & 0xffffffffL))
|
||||
|
||||
void elf64init(void);
|
||||
Elf64Hdr *getElf64Hdr();
|
||||
Elf64SHdr *newElf64SHdr(char*);
|
||||
|
|
@ -177,10 +275,17 @@ uint32 elf64writehdr(void);
|
|||
uint32 elf64writephdrs(void);
|
||||
uint32 elf64writeshdrs(void);
|
||||
void elf64writestrtable(void);
|
||||
|
||||
void elf64writedynent(int, uint64);
|
||||
uint32 elf64_hash(uchar*);
|
||||
uint64 startelf(void);
|
||||
uint64 endelf(void);
|
||||
extern int nume64phdr;
|
||||
extern int nume64shdr;
|
||||
|
||||
#define STRTABSIZE 256
|
||||
/* Amount of space to reserve at the start of the file; may waste some */
|
||||
/* Amount of space available for Header, PHeaders and SHeaders */
|
||||
#define ELF64FULLHDRSIZE 2048
|
||||
/* Space reserved after ELF64FULLHEADERSIZE for dynamic info */
|
||||
#define ELFDYNAMICSIZE 256
|
||||
/* Total amount of ELF space to reserve at the start of the file; may waste some */
|
||||
#define ELF64RESERVE 4096
|
||||
|
|
|
|||
Loading…
Reference in New Issue