1
0
mirror of https://github.com/golang/go synced 2024-11-20 06:04:52 -07:00

First steps towards cleaner support for ELF64 in 6l.

R=rsc
DELTA=337  (165 added, 119 deleted, 53 changed)
OCL=31786
CL=31794
This commit is contained in:
Rob Pike 2009-07-17 14:32:37 -07:00
parent ba0cf083a2
commit 1593b1fc23
7 changed files with 265 additions and 172 deletions

View File

@ -10,6 +10,7 @@ TARG=\
OFILES=\ OFILES=\
asm.$O\ asm.$O\
compat.$O\ compat.$O\
elf64.$O\
enam.$O\ enam.$O\
go.$O\ go.$O\
list.$O\ list.$O\
@ -21,6 +22,7 @@ OFILES=\
HFILES=\ HFILES=\
l.h\ l.h\
../6l/6.out.h\ ../6l/6.out.h\
../ld/elf64.h\
$(TARG): $(OFILES) $(TARG): $(OFILES)
@ -38,3 +40,5 @@ install: $(TARG)
cp $(TARG) $(BIN)/$(TARG) cp $(TARG) $(BIN)/$(TARG)
go.o: ../ld/go.c go.o: ../ld/go.c
elf64.o: ../ld/elf64.c

View File

@ -29,6 +29,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "l.h" #include "l.h"
#include "../ld/elf64.h"
#define Dbufslop 100 #define Dbufslop 100
@ -126,6 +127,7 @@ asmb(void)
vlong vl, va, fo, w, symo; vlong vl, va, fo, w, symo;
int strtabsize; int strtabsize;
vlong symdatva = 0x99LL<<32; vlong symdatva = 0x99LL<<32;
Elf64SHdr *sh;
strtabsize = 0; strtabsize = 0;
@ -194,7 +196,7 @@ asmb(void)
case 7: case 7:
debug['8'] = 1; /* 64-bit addresses */ debug['8'] = 1; /* 64-bit addresses */
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = linuxstrtable(); strtabsize = elf64strtable();
cflush(); cflush();
v = rnd(HEADR+textsize, INITRND); v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0); seek(cout, v, 0);
@ -448,7 +450,7 @@ asmb(void)
va = INITTEXT & ~((vlong)INITRND - 1); va = INITTEXT & ~((vlong)INITRND - 1);
w = HEADR+textsize; w = HEADR+textsize;
linuxphdr(1, /* text - type = PT_LOAD */ elf64phdr(1, /* text - type = PT_LOAD */
1L+4L, /* text - flags = PF_X+PF_R */ 1L+4L, /* text - flags = PF_X+PF_R */
0, /* file offset */ 0, /* file offset */
va, /* vaddr */ va, /* vaddr */
@ -461,7 +463,7 @@ asmb(void)
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
linuxphdr(1, /* data - type = PT_LOAD */ elf64phdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */ 2L+4L, /* data - flags = PF_W+PF_R */
fo, /* file offset */ fo, /* file offset */
va, /* vaddr */ va, /* vaddr */
@ -471,7 +473,7 @@ asmb(void)
INITRND); /* alignment */ INITRND); /* alignment */
if(!debug['s']) { if(!debug['s']) {
linuxphdr(1, /* data - type = PT_LOAD */ elf64phdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */ 2L+4L, /* data - flags = PF_W+PF_R */
symo, /* file offset */ symo, /* file offset */
symdatva, /* vaddr */ symdatva, /* vaddr */
@ -481,7 +483,7 @@ asmb(void)
INITRND); /* alignment */ INITRND); /* alignment */
} }
linuxphdr(0x6474e551, /* gok - type = gok */ elf64phdr(0x6474e551, /* gok - type = gok */
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ 1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */
0, /* file offset */ 0, /* file offset */
0, /* vaddr */ 0, /* vaddr */
@ -490,75 +492,57 @@ asmb(void)
0, /* memory size */ 0, /* memory size */
8); /* alignment */ 8); /* alignment */
linuxshdr(nil, /* name */ sh = newElf64SHdr();
0, /* type */ elf64shdr(nil, sh);
0, /* flags */
0, /* addr */
0, /* off */
0, /* size */
0, /* link */
0, /* info */
0, /* align */
0); /* entsize */
stroffset = 1; /* 0 means no name, so start at 1 */ stroffset = 1; /* 0 means no name, so start at 1 */
fo = HEADR; fo = HEADR;
va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
w = textsize; w = textsize;
linuxshdr(".text", /* name */ sh = newElf64SHdr();
1, /* type */ sh->type = 1;
6, /* flags */ sh->flags = 6;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 8;
0, /* info */ elf64shdr(".text", sh);
8, /* align */
0); /* entsize */
fo = rnd(fo+w, INITRND); fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND); va = rnd(va+w, INITRND);
w = datsize; w = datsize;
linuxshdr(".data", /* name */ sh = newElf64SHdr();
1, /* type */ sh->type = 1;
3, /* flags */ sh->flags = 3;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 8;
0, /* info */ elf64shdr(".data", sh);
8, /* align */
0); /* entsize */
fo += w; fo += w;
va += w; va += w;
w = bsssize; w = bsssize;
linuxshdr(".bss", /* name */ sh = newElf64SHdr();
8, /* type */ sh->type = 8;
3, /* flags */ sh->flags = 3;
va, /* addr */ sh->addr = va;
fo, /* off */ sh->off = fo;
w, /* size */ sh->size = w;
0, /* link */ sh->addralign = 8;
0, /* info */ elf64shdr(".bss", sh);
8, /* align */
0); /* entsize */
w = strtabsize; w = strtabsize;
linuxshdr(".shstrtab", /* name */ sh = newElf64SHdr();
3, /* type */ sh->type = 3;
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */ elf64shdr(".shstrtab", sh);
0, /* link */
0, /* info */
1, /* align */
0); /* entsize */
if (debug['s']) if (debug['s'])
break; break;
@ -566,30 +550,25 @@ asmb(void)
fo = symo+8; fo = symo+8;
w = symsize; w = symsize;
linuxshdr(".gosymtab", /* name */ sh = newElf64SHdr();
1, /* type 1 = SHT_PROGBITS */ sh->type = 1; /* type 1 = SHT_PROGBITS */
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */ sh->entsize = 24;
0, /* link */ elf64shdr(".gosymtab", sh);
0, /* info */
1, /* align */
24); /* entsize */
fo += w; fo += w;
w = lcsize; w = lcsize;
linuxshdr(".gopclntab", /* name */ sh = newElf64SHdr();
1, /* type 1 = SHT_PROGBITS*/ sh->type = 1; /* type 1 = SHT_PROGBITS */
0, /* flags */ sh->off = fo;
0, /* addr */ sh->size = w;
fo, /* off */ sh->addralign = 1;
w, /* size */ sh->entsize = 24;
0, /* link */ elf64shdr(".gopclntab", sh);
0, /* info */
1, /* align */
24); /* entsize */
break; break;
} }
cflush(); cflush();
@ -899,91 +878,3 @@ machheadr(void)
return a*4; return a*4;
} }
uint32
linuxheadr(void)
{
uint32 a;
a = 64; /* a.out header */
a += 56; /* page zero seg */
a += 56; /* text seg */
a += 56; /* stack seg */
a += 64; /* nil sect */
a += 64; /* .text sect */
a += 64; /* .data seg */
a += 64; /* .bss sect */
a += 64; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 56; /* symdat seg */
a += 64; /* .gosymtab sect */
a += 64; /* .gopclntab sect */
}
return a;
}
void
linuxphdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align)
{
lputl(type); /* text - type = PT_LOAD */
lputl(flags); /* text - flags = PF_X+PF_R */
vputl(foff); /* file offset */
vputl(vaddr); /* vaddr */
vputl(paddr); /* paddr */
vputl(filesize); /* file size */
vputl(memsize); /* memory size */
vputl(align); /* alignment */
}
void
linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
vlong size, uint32 link, uint32 info, vlong align, vlong entsize)
{
lputl(stroffset);
lputl(type);
vputl(flags);
vputl(addr);
vputl(off);
vputl(size);
lputl(link);
lputl(info);
vputl(align);
vputl(entsize);
if(name != nil)
stroffset += strlen(name)+1;
}
int
putstrtab(char* name) {
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
int
linuxstrtable(void)
{
int size;
size = 0;
size += putstrtab("");
size += putstrtab(".text");
size += putstrtab(".data");
size += putstrtab(".bss");
size += putstrtab(".shstrtab");
if (!debug['s']) {
size += putstrtab(".gosymtab");
size += putstrtab(".gopclntab");
}
return size;
}

6
src/cmd/6l/elf64.c Normal file
View File

@ -0,0 +1,6 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "l.h"
#include "../ld/elf64.c"

View File

@ -432,9 +432,11 @@ int relinv(int);
int32 reuse(Prog*, Sym*); int32 reuse(Prog*, Sym*);
vlong rnd(vlong, vlong); vlong rnd(vlong, vlong);
void span(void); void span(void);
void strnput(char*, int);
void undef(void); void undef(void);
void undefsym(Sym*); void undefsym(Sym*);
vlong vaddr(Adr*); vlong vaddr(Adr*);
void vputl(vlong);
void wput(ushort); void wput(ushort);
void xdefine(char*, int, vlong); void xdefine(char*, int, vlong);
void xfol(Prog*); void xfol(Prog*);
@ -448,14 +450,6 @@ void machstack(vlong);
void machdylink(void); void machdylink(void);
uint32 machheadr(void); uint32 machheadr(void);
uint32 linuxheadr(void);
void linuxphdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align);
void linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off,
vlong size, uint32 link, uint32 info, vlong align, vlong entsize);
int linuxstrtable(void);
#pragma varargck type "D" Adr* #pragma varargck type "D" Adr*
#pragma varargck type "P" Prog* #pragma varargck type "P" Prog*

View File

@ -30,6 +30,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/elf64.h"
#include <ar.h> #include <ar.h>
char *noname = "<none>"; char *noname = "<none>";
@ -196,7 +197,7 @@ main(int argc, char *argv[])
INITRND = 4096; INITRND = 4096;
break; break;
case 7: /* elf64 executable */ case 7: /* elf64 executable */
HEADR = linuxheadr(); HEADR = elf64headr();
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = (1<<22)+HEADR; INITTEXT = (1<<22)+HEADR;
if(INITDAT == -1) if(INITDAT == -1)

108
src/cmd/ld/elf64.c Normal file
View File

@ -0,0 +1,108 @@
// Copyright 2009 The Go Authors. All rights reserved.
// 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"
void
elf64phdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align)
{
lputl(type); /* type */
lputl(flags); /* flags */
vputl(foff); /* file offset */
vputl(vaddr); /* vaddr */
vputl(paddr); /* paddr */
vputl(filesize); /* file size */
vputl(memsize); /* memory size */
vputl(align); /* alignment */
}
void
elf64shdr(char *name, Elf64SHdr *e)
{
lputl(e->name);
lputl(e->type);
vputl(e->flags);
vputl(e->addr);
vputl(e->off);
vputl(e->size);
lputl(e->link);
lputl(e->info);
vputl(e->addralign);
vputl(e->entsize);
if(name != nil)
stroffset += strlen(name)+1;
}
int
putelf64strtab(char* name)
{
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
int
elf64strtable(void)
{
int size;
size = 0;
size += putelf64strtab("");
size += putelf64strtab(".text");
size += putelf64strtab(".data");
size += putelf64strtab(".bss");
size += putelf64strtab(".shstrtab");
if (!debug['s']) {
size += putelf64strtab(".gosymtab");
size += putelf64strtab(".gopclntab");
}
return size;
}
uint32
elf64headr(void)
{
uint32 a;
a = 64; /* a.out header */
a += 56; /* page zero seg */
a += 56; /* text seg */
a += 56; /* stack seg */
a += 64; /* nil sect */
a += 64; /* .text sect */
a += 64; /* .data seg */
a += 64; /* .bss sect */
a += 64; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 56; /* symdat seg */
a += 64; /* .gosymtab sect */
a += 64; /* .gopclntab sect */
}
return a;
}
Elf64SHdr*
newElf64SHdr()
{
Elf64SHdr *e;
e = malloc(sizeof *e);
memset(e, 0, sizeof *e);
e->name = stroffset;
return e;
}

89
src/cmd/ld/elf64.h Normal file
View File

@ -0,0 +1,89 @@
/*
* Derived from:
* $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
* $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
* $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
* $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
* $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
* $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
* $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
* $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
* $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
*
* Copyright (c) 1996-1998 John D. Polstra. All rights reserved.
* Copyright (c) 2001 David E. O'Brien
* Portions Copyright 2009 The Go Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
typedef uint64 Elf64_Addr; /* Unsigned program address */
typedef uint64 Elf64_Off; /* Unsigned file offset */
typedef uint16 Elf64_Half; /* Unsigned medium integer */
typedef uint32 Elf64_Word; /* Unsigned integer */
typedef int32 Elf64_Sword; /* Signed integer */
typedef uint64 Elf64_Xword; /* Unsigned long integer */
typedef int64 Elf64_Sxword; /* Signed long integer */
typedef struct Elf64Hdr Elf64Hdr;
typedef struct Elf64SHdr Elf64SHdr;
struct Elf64Hdr
{
uchar ident[16]; /* ELF identification */
Elf64_Half type; /* Object file type */
Elf64_Half machine; /* Machine type */
Elf64_Word version; /* Object file version */
Elf64_Addr entry; /* Entry point address */
Elf64_Off phoff; /* Program header offset */
Elf64_Off shoff; /* Section header offset */
Elf64_Word flags; /* Processor-specific flags */
Elf64_Half ehsize; /* ELF header size */
Elf64_Half phentsize; /* Size of program header entry */
Elf64_Half phnum; /* Number of program header entries */
Elf64_Half shentsize; /* Size of section header entry */
Elf64_Half shnum; /* Number of section header entries */
Elf64_Half shstrndx; /* Section name string table index */
};
struct Elf64SHdr
{
Elf64_Word name; /* Section name */
Elf64_Word type; /* Section type */
Elf64_Xword flags; /* Section attributes */
Elf64_Addr addr; /* Virtual address in memory */
Elf64_Off off; /* Offset in file */
Elf64_Xword size; /* Size of section */
Elf64_Word link; /* Link to other section */
Elf64_Word info; /* Miscellaneous information */
Elf64_Xword addralign; /* Address alignment boundary */
Elf64_Xword entsize; /* Size of entries, if section has table */
};
Elf64SHdr *newElf64SHdr();
uint32 elf64headr(void);
void elf64phdr(int type, int flags, vlong foff,
vlong vaddr, vlong paddr,
vlong filesize, vlong memsize, vlong align);
void elf64shdr(char*, Elf64SHdr*);
int elf64strtable(void);