mirror of
https://github.com/golang/go
synced 2024-11-21 16:44:43 -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/elf.h"
|
||||
|
||||
int32 OFFSET;
|
||||
|
||||
static Prog *PP;
|
||||
|
||||
char linuxdynld[] = "/lib/ld-linux.so.2";
|
||||
@ -295,7 +293,7 @@ asmb(void)
|
||||
{
|
||||
int32 t;
|
||||
int a, dynsym;
|
||||
uint32 fo, symo, startva, elfsymo, elfstro, elfsymsize;
|
||||
uint32 fo, symo, startva;
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
ElfShdr *sh;
|
||||
@ -305,10 +303,6 @@ asmb(void)
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
elfsymsize = 0;
|
||||
elfstro = 0;
|
||||
elfsymo = 0;
|
||||
|
||||
sect = segtext.sect;
|
||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||
codeblk(sect->vaddr, sect->len);
|
||||
@ -361,27 +355,22 @@ asmb(void)
|
||||
debug['s'] = 1;
|
||||
break;
|
||||
case Hplan9x32:
|
||||
OFFSET = HEADR+textsize+segdata.filelen;
|
||||
seek(cout, OFFSET, 0);
|
||||
symo = HEADR+segtext.len+segdata.filelen;
|
||||
break;
|
||||
case Hnetbsd:
|
||||
OFFSET += rnd(segdata.filelen, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
symo = rnd(segdata.filelen, 4096);
|
||||
break;
|
||||
ElfSym:
|
||||
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
|
||||
symo = rnd(symo, INITRND);
|
||||
break;
|
||||
}
|
||||
seek(cout, symo, 0);
|
||||
if(iself) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
||||
elfsymo = symo+8+symsize+lcsize;
|
||||
seek(cout, elfsymo, 0);
|
||||
asmelfsym32();
|
||||
asmelfsym();
|
||||
cflush();
|
||||
elfstro = seek(cout, 0, 1);
|
||||
elfsymsize = elfstro - elfsymo;
|
||||
ewrite(cout, elfstrdat, elfstrsize);
|
||||
|
||||
// if(debug['v'])
|
||||
@ -397,8 +386,7 @@ asmb(void)
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f header\n", cputime());
|
||||
Bflush(&bso);
|
||||
OFFSET = 0;
|
||||
seek(cout, OFFSET, 0);
|
||||
seek(cout, 0L, 0);
|
||||
switch(HEADTYPE) {
|
||||
case Hnoheader: /* no header */
|
||||
break;
|
||||
@ -599,15 +587,15 @@ asmb(void)
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||
sh->type = SHT_SYMTAB;
|
||||
sh->off = elfsymo;
|
||||
sh->size = elfsymsize;
|
||||
sh->off = symo;
|
||||
sh->size = symsize;
|
||||
sh->addralign = 4;
|
||||
sh->entsize = 16;
|
||||
sh->link = eh->shnum; // link to strtab
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->off = elfstro;
|
||||
sh->off = symo+symsize;
|
||||
sh->size = elfstrsize;
|
||||
sh->addralign = 1;
|
||||
|
||||
|
@ -698,7 +698,7 @@ asmb(void)
|
||||
{
|
||||
int32 magic;
|
||||
int a, dynsym;
|
||||
vlong vl, startva, symo, elfsymo, elfstro, elfsymsize, machlink;
|
||||
vlong vl, startva, symo, machlink;
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
ElfShdr *sh;
|
||||
@ -709,9 +709,6 @@ asmb(void)
|
||||
Bflush(&bso);
|
||||
|
||||
elftextsh = 0;
|
||||
elfsymsize = 0;
|
||||
elfstro = 0;
|
||||
elfsymo = 0;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f codeblk\n", cputime());
|
||||
@ -790,36 +787,13 @@ asmb(void)
|
||||
symo = rnd(symo, PEFILEALIGN);
|
||||
break;
|
||||
}
|
||||
seek(cout, symo, 0);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
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);
|
||||
lputl(symsize);
|
||||
lputl(lcsize);
|
||||
asmelfsym();
|
||||
cflush();
|
||||
elfsymo = symo+8+symsize+lcsize;
|
||||
seek(cout, elfsymo, 0);
|
||||
asmelfsym64();
|
||||
cflush();
|
||||
elfstro = seek(cout, 0, 1);
|
||||
elfsymsize = elfstro - elfsymo;
|
||||
ewrite(cout, elfstrdat, elfstrsize);
|
||||
|
||||
if(debug['v'])
|
||||
@ -830,7 +804,6 @@ asmb(void)
|
||||
break;
|
||||
case Hdarwin:
|
||||
case Hwindows:
|
||||
seek(cout, symo, 0);
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
||||
|
||||
@ -1054,15 +1027,15 @@ asmb(void)
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||
sh->type = SHT_SYMTAB;
|
||||
sh->off = elfsymo;
|
||||
sh->size = elfsymsize;
|
||||
sh->off = symo;
|
||||
sh->size = symsize;
|
||||
sh->addralign = 8;
|
||||
sh->entsize = 24;
|
||||
sh->link = eh->shnum; // link to strtab
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->off = elfstro;
|
||||
sh->off = symo+symsize;
|
||||
sh->size = elfstrsize;
|
||||
sh->addralign = 1;
|
||||
|
||||
@ -1149,6 +1122,10 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
||||
Auto *a;
|
||||
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) {
|
||||
if(s->hide)
|
||||
continue;
|
||||
|
@ -663,7 +663,7 @@ asmb(void)
|
||||
{
|
||||
int32 v, magic;
|
||||
int a, dynsym;
|
||||
uint32 symo, startva, machlink, elfsymo, elfstro, elfsymsize;
|
||||
uint32 symo, startva, machlink;
|
||||
ElfEhdr *eh;
|
||||
ElfPhdr *ph, *pph;
|
||||
ElfShdr *sh;
|
||||
@ -675,10 +675,6 @@ asmb(void)
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
elfsymsize = 0;
|
||||
elfstro = 0;
|
||||
elfsymo = 0;
|
||||
|
||||
sect = segtext.sect;
|
||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||
codeblk(sect->vaddr, sect->len);
|
||||
@ -724,10 +720,10 @@ asmb(void)
|
||||
if(iself)
|
||||
goto Elfsym;
|
||||
case Hgarbunix:
|
||||
seek(cout, rnd(HEADR+segtext.filelen, 8192)+segdata.filelen, 0);
|
||||
symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen;
|
||||
break;
|
||||
case Hunixcoff:
|
||||
seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0);
|
||||
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
|
||||
break;
|
||||
case Hplan9x32:
|
||||
symo = HEADR+segtext.filelen+segdata.filelen;
|
||||
@ -749,17 +745,14 @@ asmb(void)
|
||||
symo = rnd(symo, PEFILEALIGN);
|
||||
break;
|
||||
}
|
||||
seek(cout, symo, 0);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
if(iself) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f elfsym\n", cputime());
|
||||
elfsymo = symo+8+symsize+lcsize;
|
||||
seek(cout, elfsymo, 0);
|
||||
asmelfsym32();
|
||||
asmelfsym();
|
||||
cflush();
|
||||
elfstro = seek(cout, 0, 1);
|
||||
elfsymsize = elfstro - elfsymo;
|
||||
ewrite(cout, elfstrdat, elfstrsize);
|
||||
|
||||
if(debug['v'])
|
||||
@ -768,10 +761,9 @@ asmb(void)
|
||||
}
|
||||
break;
|
||||
case Hplan9x32:
|
||||
seek(cout, symo, 0);
|
||||
asmplan9sym();
|
||||
cflush();
|
||||
|
||||
|
||||
sym = lookup("pclntab", 0);
|
||||
if(sym != nil) {
|
||||
lcsize = sym->np;
|
||||
@ -783,7 +775,6 @@ asmb(void)
|
||||
break;
|
||||
case Hdarwin:
|
||||
case Hwindows:
|
||||
seek(cout, symo, 0);
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
||||
dwarfemitdebugsections();
|
||||
@ -1110,15 +1101,15 @@ asmb(void)
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrSymtab]);
|
||||
sh->type = SHT_SYMTAB;
|
||||
sh->off = elfsymo;
|
||||
sh->size = elfsymsize;
|
||||
sh->off = symo;
|
||||
sh->size = symsize;
|
||||
sh->addralign = 4;
|
||||
sh->entsize = 16;
|
||||
sh->link = eh->shnum; // link to strtab
|
||||
|
||||
sh = newElfShdr(elfstr[ElfStrStrtab]);
|
||||
sh->type = SHT_STRTAB;
|
||||
sh->off = elfstro;
|
||||
sh->off = symo+symsize;
|
||||
sh->size = elfstrsize;
|
||||
sh->addralign = 1;
|
||||
|
||||
|
@ -186,8 +186,7 @@ vlong addsize(Sym*, Sym*);
|
||||
vlong adduint8(Sym*, uint8);
|
||||
vlong adduint16(Sym*, uint16);
|
||||
void asmsym(void);
|
||||
void asmelfsym32(void);
|
||||
void asmelfsym64(void);
|
||||
void asmelfsym(void);
|
||||
void asmplan9sym(void);
|
||||
void strnput(char*, int);
|
||||
void dodata(void);
|
||||
|
@ -61,11 +61,35 @@ putelfstr(char *s)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bind = STB_GLOBAL;
|
||||
switch(thechar) {
|
||||
case '6':
|
||||
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) {
|
||||
default:
|
||||
return;
|
||||
@ -75,65 +99,27 @@ putelfsym64(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
||||
break;
|
||||
case 'D':
|
||||
type = STT_OBJECT;
|
||||
shndx = elftextsh + 1;
|
||||
if((x->type&~SSUB) == SRODATA)
|
||||
shndx = elftextsh + 1;
|
||||
else
|
||||
shndx = elftextsh + 2;
|
||||
break;
|
||||
case 'B':
|
||||
type = STT_OBJECT;
|
||||
shndx = elftextsh + 2;
|
||||
shndx = elftextsh + 3;
|
||||
break;
|
||||
}
|
||||
|
||||
stroff = putelfstr(s);
|
||||
LPUT(stroff); // string
|
||||
cput((bind<<4)|(type&0xF));
|
||||
cput(0);
|
||||
WPUT(shndx);
|
||||
VPUT(addr);
|
||||
VPUT(size);
|
||||
bind = ver ? STB_LOCAL : STB_GLOBAL;
|
||||
off = putelfstr(s);
|
||||
putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx);
|
||||
}
|
||||
|
||||
void
|
||||
asmelfsym64(void)
|
||||
asmelfsym(void)
|
||||
{
|
||||
genasmsym(putelfsym64);
|
||||
}
|
||||
|
||||
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);
|
||||
// the first symbol entry is reserved
|
||||
putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0);
|
||||
genasmsym(putelfsym);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user