mirror of
https://github.com/golang/go
synced 2024-11-19 15:44:44 -07:00
ld: fix and simplify ELF symbol generation
I started looking at this code because the nm in GNU binutils was ignoring the first symbol in the .symtab section. Apparently, the System V ABI reserves the first entry and requires all fields inside to be set to zero. The list of changes is as follows: · reserve the first symbol entry (as noted above) · fix the section indices for .data and .bss symbols · factor out common code for Elf32 and Elf64 · remove the special case for elfsymo in [568]l/asm.c:/^asmb · add the "etext" symbol in 6l · add static symbols R=rsc CC=golang-dev https://golang.org/cl/4524075
This commit is contained in:
parent
35b74d6903
commit
c5030e5f4b
@ -34,8 +34,6 @@
|
|||||||
#include "../ld/lib.h"
|
#include "../ld/lib.h"
|
||||||
#include "../ld/elf.h"
|
#include "../ld/elf.h"
|
||||||
|
|
||||||
int32 OFFSET;
|
|
||||||
|
|
||||||
static Prog *PP;
|
static Prog *PP;
|
||||||
|
|
||||||
char linuxdynld[] = "/lib/ld-linux.so.2";
|
char linuxdynld[] = "/lib/ld-linux.so.2";
|
||||||
@ -295,7 +293,7 @@ asmb(void)
|
|||||||
{
|
{
|
||||||
int32 t;
|
int32 t;
|
||||||
int a, dynsym;
|
int a, dynsym;
|
||||||
uint32 fo, symo, startva, elfsymo, elfstro, elfsymsize;
|
uint32 fo, symo, startva;
|
||||||
ElfEhdr *eh;
|
ElfEhdr *eh;
|
||||||
ElfPhdr *ph, *pph;
|
ElfPhdr *ph, *pph;
|
||||||
ElfShdr *sh;
|
ElfShdr *sh;
|
||||||
@ -305,10 +303,6 @@ asmb(void)
|
|||||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
|
|
||||||
elfsymsize = 0;
|
|
||||||
elfstro = 0;
|
|
||||||
elfsymo = 0;
|
|
||||||
|
|
||||||
sect = segtext.sect;
|
sect = segtext.sect;
|
||||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||||
codeblk(sect->vaddr, sect->len);
|
codeblk(sect->vaddr, sect->len);
|
||||||
@ -361,27 +355,22 @@ asmb(void)
|
|||||||
debug['s'] = 1;
|
debug['s'] = 1;
|
||||||
break;
|
break;
|
||||||
case Hplan9x32:
|
case Hplan9x32:
|
||||||
OFFSET = HEADR+textsize+segdata.filelen;
|
symo = HEADR+segtext.len+segdata.filelen;
|
||||||
seek(cout, OFFSET, 0);
|
|
||||||
break;
|
break;
|
||||||
case Hnetbsd:
|
case Hnetbsd:
|
||||||
OFFSET += rnd(segdata.filelen, 4096);
|
symo = rnd(segdata.filelen, 4096);
|
||||||
seek(cout, OFFSET, 0);
|
|
||||||
break;
|
break;
|
||||||
ElfSym:
|
ElfSym:
|
||||||
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
|
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
|
||||||
symo = rnd(symo, INITRND);
|
symo = rnd(symo, INITRND);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
seek(cout, symo, 0);
|
||||||
if(iself) {
|
if(iself) {
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
||||||
elfsymo = symo+8+symsize+lcsize;
|
asmelfsym();
|
||||||
seek(cout, elfsymo, 0);
|
|
||||||
asmelfsym32();
|
|
||||||
cflush();
|
cflush();
|
||||||
elfstro = seek(cout, 0, 1);
|
|
||||||
elfsymsize = elfstro - elfsymo;
|
|
||||||
ewrite(cout, elfstrdat, elfstrsize);
|
ewrite(cout, elfstrdat, elfstrsize);
|
||||||
|
|
||||||
// if(debug['v'])
|
// if(debug['v'])
|
||||||
@ -397,8 +386,7 @@ asmb(void)
|
|||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f header\n", cputime());
|
Bprint(&bso, "%5.2f header\n", cputime());
|
||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
OFFSET = 0;
|
seek(cout, 0L, 0);
|
||||||
seek(cout, OFFSET, 0);
|
|
||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
case Hnoheader: /* no header */
|
case Hnoheader: /* no header */
|
||||||
break;
|
break;
|
||||||
@ -599,15 +587,15 @@ asmb(void)
|
|||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||||
sh->type = SHT_SYMTAB;
|
sh->type = SHT_SYMTAB;
|
||||||
sh->off = elfsymo;
|
sh->off = symo;
|
||||||
sh->size = elfsymsize;
|
sh->size = symsize;
|
||||||
sh->addralign = 4;
|
sh->addralign = 4;
|
||||||
sh->entsize = 16;
|
sh->entsize = 16;
|
||||||
sh->link = eh->shnum; // link to strtab
|
sh->link = eh->shnum; // link to strtab
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||||
sh->type = SHT_STRTAB;
|
sh->type = SHT_STRTAB;
|
||||||
sh->off = elfstro;
|
sh->off = symo+symsize;
|
||||||
sh->size = elfstrsize;
|
sh->size = elfstrsize;
|
||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
|
|
||||||
|
@ -698,7 +698,7 @@ asmb(void)
|
|||||||
{
|
{
|
||||||
int32 magic;
|
int32 magic;
|
||||||
int a, dynsym;
|
int a, dynsym;
|
||||||
vlong vl, startva, symo, elfsymo, elfstro, elfsymsize, machlink;
|
vlong vl, startva, symo, machlink;
|
||||||
ElfEhdr *eh;
|
ElfEhdr *eh;
|
||||||
ElfPhdr *ph, *pph;
|
ElfPhdr *ph, *pph;
|
||||||
ElfShdr *sh;
|
ElfShdr *sh;
|
||||||
@ -709,9 +709,6 @@ asmb(void)
|
|||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
|
|
||||||
elftextsh = 0;
|
elftextsh = 0;
|
||||||
elfsymsize = 0;
|
|
||||||
elfstro = 0;
|
|
||||||
elfsymo = 0;
|
|
||||||
|
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f codeblk\n", cputime());
|
Bprint(&bso, "%5.2f codeblk\n", cputime());
|
||||||
@ -790,36 +787,13 @@ asmb(void)
|
|||||||
symo = rnd(symo, PEFILEALIGN);
|
symo = rnd(symo, PEFILEALIGN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
seek(cout, symo, 0);
|
||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
default:
|
default:
|
||||||
if(iself) {
|
if(iself) {
|
||||||
/*
|
|
||||||
* the symbol information is stored as
|
|
||||||
* 32-bit symbol table size
|
|
||||||
* 32-bit line number table size
|
|
||||||
* symbol table
|
|
||||||
* line number table
|
|
||||||
*/
|
|
||||||
seek(cout, symo+8, 0);
|
|
||||||
if(debug['v'])
|
|
||||||
Bprint(&bso, "%5.2f sp\n", cputime());
|
|
||||||
Bflush(&bso);
|
|
||||||
if(debug['v'])
|
|
||||||
Bprint(&bso, "%5.2f pc\n", cputime());
|
|
||||||
Bflush(&bso);
|
|
||||||
if(!debug['s'])
|
|
||||||
strnput("", INITRND-(8+symsize+lcsize)%INITRND);
|
|
||||||
cflush();
|
|
||||||
seek(cout, symo, 0);
|
seek(cout, symo, 0);
|
||||||
lputl(symsize);
|
asmelfsym();
|
||||||
lputl(lcsize);
|
|
||||||
cflush();
|
cflush();
|
||||||
elfsymo = symo+8+symsize+lcsize;
|
|
||||||
seek(cout, elfsymo, 0);
|
|
||||||
asmelfsym64();
|
|
||||||
cflush();
|
|
||||||
elfstro = seek(cout, 0, 1);
|
|
||||||
elfsymsize = elfstro - elfsymo;
|
|
||||||
ewrite(cout, elfstrdat, elfstrsize);
|
ewrite(cout, elfstrdat, elfstrsize);
|
||||||
|
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
@ -830,7 +804,6 @@ asmb(void)
|
|||||||
break;
|
break;
|
||||||
case Hdarwin:
|
case Hdarwin:
|
||||||
case Hwindows:
|
case Hwindows:
|
||||||
seek(cout, symo, 0);
|
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
||||||
|
|
||||||
@ -1054,15 +1027,15 @@ asmb(void)
|
|||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||||
sh->type = SHT_SYMTAB;
|
sh->type = SHT_SYMTAB;
|
||||||
sh->off = elfsymo;
|
sh->off = symo;
|
||||||
sh->size = elfsymsize;
|
sh->size = symsize;
|
||||||
sh->addralign = 8;
|
sh->addralign = 8;
|
||||||
sh->entsize = 24;
|
sh->entsize = 24;
|
||||||
sh->link = eh->shnum; // link to strtab
|
sh->link = eh->shnum; // link to strtab
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||||
sh->type = SHT_STRTAB;
|
sh->type = SHT_STRTAB;
|
||||||
sh->off = elfstro;
|
sh->off = symo+symsize;
|
||||||
sh->size = elfstrsize;
|
sh->size = elfstrsize;
|
||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
|
|
||||||
@ -1149,6 +1122,10 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
Auto *a;
|
Auto *a;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
|
s = lookup("etext", 0);
|
||||||
|
if(s->type == STEXT)
|
||||||
|
put(s, s->name, 'T', s->value, s->size, s->version, 0);
|
||||||
|
|
||||||
for(s=allsym; s!=S; s=s->allsym) {
|
for(s=allsym; s!=S; s=s->allsym) {
|
||||||
if(s->hide)
|
if(s->hide)
|
||||||
continue;
|
continue;
|
||||||
|
@ -663,7 +663,7 @@ asmb(void)
|
|||||||
{
|
{
|
||||||
int32 v, magic;
|
int32 v, magic;
|
||||||
int a, dynsym;
|
int a, dynsym;
|
||||||
uint32 symo, startva, machlink, elfsymo, elfstro, elfsymsize;
|
uint32 symo, startva, machlink;
|
||||||
ElfEhdr *eh;
|
ElfEhdr *eh;
|
||||||
ElfPhdr *ph, *pph;
|
ElfPhdr *ph, *pph;
|
||||||
ElfShdr *sh;
|
ElfShdr *sh;
|
||||||
@ -675,10 +675,6 @@ asmb(void)
|
|||||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
|
|
||||||
elfsymsize = 0;
|
|
||||||
elfstro = 0;
|
|
||||||
elfsymo = 0;
|
|
||||||
|
|
||||||
sect = segtext.sect;
|
sect = segtext.sect;
|
||||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||||
codeblk(sect->vaddr, sect->len);
|
codeblk(sect->vaddr, sect->len);
|
||||||
@ -724,10 +720,10 @@ asmb(void)
|
|||||||
if(iself)
|
if(iself)
|
||||||
goto Elfsym;
|
goto Elfsym;
|
||||||
case Hgarbunix:
|
case Hgarbunix:
|
||||||
seek(cout, rnd(HEADR+segtext.filelen, 8192)+segdata.filelen, 0);
|
symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen;
|
||||||
break;
|
break;
|
||||||
case Hunixcoff:
|
case Hunixcoff:
|
||||||
seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0);
|
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
|
||||||
break;
|
break;
|
||||||
case Hplan9x32:
|
case Hplan9x32:
|
||||||
symo = HEADR+segtext.filelen+segdata.filelen;
|
symo = HEADR+segtext.filelen+segdata.filelen;
|
||||||
@ -749,17 +745,14 @@ asmb(void)
|
|||||||
symo = rnd(symo, PEFILEALIGN);
|
symo = rnd(symo, PEFILEALIGN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
seek(cout, symo, 0);
|
||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
default:
|
default:
|
||||||
if(iself) {
|
if(iself) {
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
||||||
elfsymo = symo+8+symsize+lcsize;
|
asmelfsym();
|
||||||
seek(cout, elfsymo, 0);
|
|
||||||
asmelfsym32();
|
|
||||||
cflush();
|
cflush();
|
||||||
elfstro = seek(cout, 0, 1);
|
|
||||||
elfsymsize = elfstro - elfsymo;
|
|
||||||
ewrite(cout, elfstrdat, elfstrsize);
|
ewrite(cout, elfstrdat, elfstrsize);
|
||||||
|
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
@ -768,10 +761,9 @@ asmb(void)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Hplan9x32:
|
case Hplan9x32:
|
||||||
seek(cout, symo, 0);
|
|
||||||
asmplan9sym();
|
asmplan9sym();
|
||||||
cflush();
|
cflush();
|
||||||
|
|
||||||
sym = lookup("pclntab", 0);
|
sym = lookup("pclntab", 0);
|
||||||
if(sym != nil) {
|
if(sym != nil) {
|
||||||
lcsize = sym->np;
|
lcsize = sym->np;
|
||||||
@ -783,7 +775,6 @@ asmb(void)
|
|||||||
break;
|
break;
|
||||||
case Hdarwin:
|
case Hdarwin:
|
||||||
case Hwindows:
|
case Hwindows:
|
||||||
seek(cout, symo, 0);
|
|
||||||
if(debug['v'])
|
if(debug['v'])
|
||||||
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
||||||
dwarfemitdebugsections();
|
dwarfemitdebugsections();
|
||||||
@ -1110,15 +1101,15 @@ asmb(void)
|
|||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||||
sh->type = SHT_SYMTAB;
|
sh->type = SHT_SYMTAB;
|
||||||
sh->off = elfsymo;
|
sh->off = symo;
|
||||||
sh->size = elfsymsize;
|
sh->size = symsize;
|
||||||
sh->addralign = 4;
|
sh->addralign = 4;
|
||||||
sh->entsize = 16;
|
sh->entsize = 16;
|
||||||
sh->link = eh->shnum; // link to strtab
|
sh->link = eh->shnum; // link to strtab
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||||
sh->type = SHT_STRTAB;
|
sh->type = SHT_STRTAB;
|
||||||
sh->off = elfstro;
|
sh->off = symo+symsize;
|
||||||
sh->size = elfstrsize;
|
sh->size = elfstrsize;
|
||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
|
|
||||||
|
@ -186,8 +186,7 @@ vlong addsize(Sym*, Sym*);
|
|||||||
vlong adduint8(Sym*, uint8);
|
vlong adduint8(Sym*, uint8);
|
||||||
vlong adduint16(Sym*, uint16);
|
vlong adduint16(Sym*, uint16);
|
||||||
void asmsym(void);
|
void asmsym(void);
|
||||||
void asmelfsym32(void);
|
void asmelfsym(void);
|
||||||
void asmelfsym64(void);
|
|
||||||
void asmplan9sym(void);
|
void asmplan9sym(void);
|
||||||
void strnput(char*, int);
|
void strnput(char*, int);
|
||||||
void dodata(void);
|
void dodata(void);
|
||||||
|
@ -61,11 +61,35 @@ putelfstr(char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
putelfsym64(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
putelfsyment(int off, vlong addr, vlong size, int info, int shndx)
|
||||||
{
|
{
|
||||||
int bind, type, shndx, stroff;
|
switch(thechar) {
|
||||||
|
case '6':
|
||||||
bind = STB_GLOBAL;
|
LPUT(off);
|
||||||
|
cput(info);
|
||||||
|
cput(0);
|
||||||
|
WPUT(shndx);
|
||||||
|
VPUT(addr);
|
||||||
|
VPUT(size);
|
||||||
|
symsize += ELF64SYMSIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LPUT(off);
|
||||||
|
LPUT(addr);
|
||||||
|
LPUT(size);
|
||||||
|
cput(info);
|
||||||
|
cput(0);
|
||||||
|
WPUT(shndx);
|
||||||
|
symsize += ELF32SYMSIZE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
||||||
|
{
|
||||||
|
int bind, type, shndx, off;
|
||||||
|
|
||||||
switch(t) {
|
switch(t) {
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@ -75,65 +99,27 @@ putelfsym64(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
|||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
type = STT_OBJECT;
|
type = STT_OBJECT;
|
||||||
shndx = elftextsh + 1;
|
if((x->type&~SSUB) == SRODATA)
|
||||||
|
shndx = elftextsh + 1;
|
||||||
|
else
|
||||||
|
shndx = elftextsh + 2;
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
type = STT_OBJECT;
|
type = STT_OBJECT;
|
||||||
shndx = elftextsh + 2;
|
shndx = elftextsh + 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
bind = ver ? STB_LOCAL : STB_GLOBAL;
|
||||||
stroff = putelfstr(s);
|
off = putelfstr(s);
|
||||||
LPUT(stroff); // string
|
putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx);
|
||||||
cput((bind<<4)|(type&0xF));
|
|
||||||
cput(0);
|
|
||||||
WPUT(shndx);
|
|
||||||
VPUT(addr);
|
|
||||||
VPUT(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
asmelfsym64(void)
|
asmelfsym(void)
|
||||||
{
|
{
|
||||||
genasmsym(putelfsym64);
|
// the first symbol entry is reserved
|
||||||
}
|
putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0);
|
||||||
|
genasmsym(putelfsym);
|
||||||
void
|
|
||||||
putelfsym32(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
|
||||||
{
|
|
||||||
int bind, type, shndx, stroff;
|
|
||||||
|
|
||||||
bind = STB_GLOBAL;
|
|
||||||
switch(t) {
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
case 'T':
|
|
||||||
type = STT_FUNC;
|
|
||||||
shndx = elftextsh + 0;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
type = STT_OBJECT;
|
|
||||||
shndx = elftextsh + 1;
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
type = STT_OBJECT;
|
|
||||||
shndx = elftextsh + 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
stroff = putelfstr(s);
|
|
||||||
LPUT(stroff); // string
|
|
||||||
LPUT(addr);
|
|
||||||
LPUT(size);
|
|
||||||
cput((bind<<4)|(type&0xF));
|
|
||||||
cput(0);
|
|
||||||
WPUT(shndx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
asmelfsym32(void)
|
|
||||||
{
|
|
||||||
genasmsym(putelfsym32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user