1
0
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:
Anthony Martin 2011-06-07 14:26:16 -04:00 committed by Russ Cox
parent 35b74d6903
commit c5030e5f4b
5 changed files with 69 additions and 128 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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