/* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFDATA;
+ shstrtab->type = SELFROSECT;
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
/* interpreter string */
+ if(interpreter == nil)
+ interpreter = linuxdynld;
s = lookup(".interp", 0);
+ s->type = SELFROSECT;
s->reachable = 1;
- s->type = SELFDATA; // TODO: rodata
+ addstring(s, interpreter);
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
s->value += ELF32SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
if(s->size == 0)
addstring(s, "");
/* relocation table */
s = lookup(".rel", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* global offset table */
s = lookup(".got", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFSECT; // writable
/* hash */
s = lookup(".hash", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* got.plt */
s = lookup(".got.plt", 0);
s->reachable = 1;
- s->type = SDATA; // writable, so not SELFDATA
+ s->type = SELFSECT; // writable
s = lookup(".plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".rel.plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
elfsetupplt();
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/*
* .dynamic table
void
shsym(Elf64_Shdr *sh, Sym *s)
{
- sh->addr = symaddr(s);
- sh->off = datoff(sh->addr);
+ vlong addr;
+ addr = symaddr(s);
+ if(sh->flags&SHF_ALLOC)
+ sh->addr = addr;
+ sh->off = datoff(addr);
sh->size = s->size;
}
if(iself) {
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
- elftextsh = 1;
+ elftextsh = 2;
if(!debug['d']) {
elftextsh += 10;
if(elfverneed)
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
- if(interpreter == nil)
- interpreter = linuxdynld;
- elfinterp(sh, startva, interpreter);
+ shsym(sh, lookup(".interp", 0));
ph = newElfPhdr();
ph->type = PT_INTERP;
ph->flags = PF_W+PF_R;
ph->align = 4;
+ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
+ sh->type = SHT_STRTAB;
+ sh->addralign = 1;
+ shsym(sh, lookup(".shstrtab", 0));
+
if(elftextsh != eh->shnum)
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
for(sect=segtext.sect; sect!=nil; sect=sect->next)
// dwarfaddelfheaders();
}
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
/* Main header */
eh->ident[EI_MAG0] = '\177';
eh->ident[EI_MAG1] = 'E';
a += elfwritephdrs();
a += elfwriteshdrs();
cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
+ if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
}
case SCONST:
case SRODATA:
case SDATA:
- case SELFDATA:
+ case SELFROSECT:
case STYPE:
case SSTRING:
case SGOSTRING:
return 0;
case STEXT:
- case SELFDATA:
+ case SELFROSECT:
case SRODATA:
case SDATA:
case SBSS:
/* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFDATA;
+ shstrtab->type = SELFROSECT;
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
+ /* interpreter string */
+ if(interpreter == nil) {
+ switch(HEADTYPE) {
+ case Hlinux:
+ interpreter = linuxdynld;
+ break;
+ case Hfreebsd:
+ interpreter = freebsddynld;
+ break;
+ }
+ }
+ s = lookup(".interp", 0);
+ s->type = SELFROSECT;
+ s->reachable = 1;
+ addstring(s, interpreter);
+
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
s->size += ELF64SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
if(s->size == 0)
addstring(s, "");
/* relocation table */
s = lookup(".rela", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* global offset table */
s = lookup(".got", 0);
s->reachable = 1;
- s->type = SDATA; // writable, so not SELFDATA
+ s->type = SELFSECT; // writable
/* hash */
s = lookup(".hash", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".got.plt", 0);
s->reachable = 1;
- s->type = SDATA; // writable, not SELFDATA
+ s->type = SELFSECT; // writable
s = lookup(".plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
elfsetupplt();
s = lookup(".rela.plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".gnu.version", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".gnu.version_r", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/*
* .dynamic table
void
shsym(ElfShdr *sh, Sym *s)
{
- sh->addr = symaddr(s);
- sh->off = datoff(sh->addr);
+ vlong addr;
+ addr = symaddr(s);
+ if(sh->flags&SHF_ALLOC)
+ sh->addr = addr;
+ sh->off = datoff(addr);
sh->size = s->size;
}
debug['8'] = 1; /* 64-bit addresses */
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
- elftextsh = 1;
+ elftextsh = 2;
if(!debug['d']) {
elftextsh += 10;
if(elfverneed)
break;
}
}
- elfinterp(sh, startva, interpreter);
+ shsym(sh, lookup(".interp", 0));
ph = newElfPhdr();
ph->type = PT_INTERP;
ph->flags = PF_W+PF_R;
ph->align = 8;
+ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
+ sh->type = SHT_STRTAB;
+ sh->addralign = 1;
+ shsym(sh, lookup(".shstrtab", 0));
+
if(elftextsh != eh->shnum)
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
for(sect=segtext.sect; sect!=nil; sect=sect->next)
dwarfaddelfheaders();
}
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
/* Main header */
eh->ident[EI_MAG0] = '\177';
eh->ident[EI_MAG1] = 'E';
a += elfwritephdrs();
a += elfwriteshdrs();
cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
+ if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
case Hwindows:
case SCONST:
case SRODATA:
case SDATA:
- case SELFDATA:
+ case SELFROSECT:
case SMACHOGOT:
case STYPE:
case SSTRING:
/* predefine strings we need for section headers */
shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFDATA;
+ shstrtab->type = SELFROSECT;
shstrtab->reachable = 1;
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
/* interpreter string */
+ if(interpreter == nil) {
+ switch(HEADTYPE) {
+ case Hlinux:
+ interpreter = linuxdynld;
+ break;
+ case Hfreebsd:
+ interpreter = freebsddynld;
+ break;
+ }
+ }
s = lookup(".interp", 0);
+ s->type = SELFROSECT;
s->reachable = 1;
- s->type = SELFDATA;
+ addstring(s, interpreter);
/* dynamic symbol table - first entry all zeros */
s = lookup(".dynsym", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
s->size += ELF32SYMSIZE;
/* dynamic string table */
s = lookup(".dynstr", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
if(s->size == 0)
addstring(s, "");
dynstr = s;
/* relocation table */
s = lookup(".rel", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* global offset table */
s = lookup(".got", 0);
s->reachable = 1;
- s->type = SDATA; // writable, so not SELFDATA
+ s->type = SELFSECT; // writable
/* hash */
s = lookup(".hash", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/* got.plt */
s = lookup(".got.plt", 0);
s->reachable = 1;
- s->type = SDATA; // writable, so not SELFDATA
+ s->type = SELFSECT; // writable
s = lookup(".plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".rel.plt", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".gnu.version", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s = lookup(".gnu.version_r", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
elfsetupplt();
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
- s->type = SELFDATA;
+ s->type = SELFROSECT;
/*
* .dynamic table
void
shsym(Elf64_Shdr *sh, Sym *s)
{
- sh->addr = symaddr(s);
- sh->off = datoff(sh->addr);
+ vlong addr;
+ addr = symaddr(s);
+ if(sh->flags&SHF_ALLOC)
+ sh->addr = addr;
+ sh->off = datoff(addr);
sh->size = s->size;
}
if(iself) {
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
- elftextsh = 1;
+ elftextsh = 2;
if(!debug['d']) {
elftextsh += 10;
if(elfverneed)
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
- if(interpreter == nil) {
- switch(HEADTYPE) {
- case Hlinux:
- interpreter = linuxdynld;
- break;
- case Hfreebsd:
- interpreter = freebsddynld;
- break;
- }
- }
- elfinterp(sh, startva, interpreter);
+ shsym(sh, lookup(".interp", 0));
ph = newElfPhdr();
ph->type = PT_INTERP;
ph->flags = PF_W+PF_R;
ph->align = 4;
+ sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
+ sh->type = SHT_STRTAB;
+ sh->addralign = 1;
+ shsym(sh, lookup(".shstrtab", 0));
+
if(elftextsh != eh->shnum)
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
for(sect=segtext.sect; sect!=nil; sect=sect->next)
dwarfaddelfheaders();
}
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
/* Main header */
eh->ident[EI_MAG0] = '\177';
eh->ident[EI_MAG1] = 'E';
a += elfwritephdrs();
a += elfwriteshdrs();
cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
+ if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
case SCONST:
case SRODATA:
case SDATA:
- case SELFDATA:
+ case SELFROSECT:
case SMACHO:
case SMACHOGOT:
case STYPE:
s = datap;
for(; s != nil && s->type < SSYMTAB; s = s->next) {
s->type = SRODATA;
- t = rnd(s->size, PtrSize);
s->value = datsize;
- datsize += t;
+ datsize += rnd(s->size, PtrSize);
}
sect->len = datsize - sect->vaddr;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
+ datsize = rnd(datsize, PtrSize);
/* gopclntab */
sect = addsection(&segtext, ".gopclntab", 04);
sect->vaddr = datsize;
- for(; s != nil && s->type < SDATA; s = s->next) {
+ for(; s != nil && s->type < SELFROSECT; s = s->next) {
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
+ datsize = rnd(datsize, PtrSize);
- /* data */
+ /* read-only ELF sections */
+ for(; s != nil && s->type < SELFSECT; s = s->next) {
+ sect = addsection(&segtext, s->name, 04);
+ sect->vaddr = datsize;
+ s->type = SRODATA;
+ s->value = datsize;
+ datsize += rnd(s->size, PtrSize);
+ sect->len = datsize - sect->vaddr;
+ }
+
+ /* writable ELF sections */
datsize = 0;
+ for(; s != nil && s->type < SDATA; s = s->next) {
+ sect = addsection(&segdata, s->name, 06);
+ sect->vaddr = datsize;
+ s->type = SDATA;
+ s->value = datsize;
+ datsize += rnd(s->size, PtrSize);
+ sect->len = datsize - sect->vaddr;
+ }
+
+ /* data */
sect = addsection(&segdata, ".data", 06);
sect->vaddr = 0;
for(; s != nil && s->type < SBSS; s = s->next) {
segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) {
s->vaddr = va;
- va += s->len;
- segtext.len = va - INITTEXT;
- va = rnd(va, INITRND);
+ va += rnd(s->len, PtrSize);
}
+ segtext.len = va - INITTEXT;
segtext.filelen = segtext.len;
+ va = rnd(va, INITRND);
+
segdata.rwx = 06;
segdata.vaddr = va;
segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
+ segdata.filelen = 0;
if(HEADTYPE == Hwindows)
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
if(HEADTYPE == Hplan9x32)
segdata.fileoff = segtext.fileoff + segtext.filelen;
+ data = nil;
for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va;
va += s->len;
+ segdata.filelen += s->len;
segdata.len = va - segdata.vaddr;
+ if(strcmp(s->name, ".data") == 0)
+ data = s;
}
- segdata.filelen = segdata.sect->len; // assume .data is first
-
+ segdata.filelen -= data->next->len; // deduct .bss
+
text = segtext.sect;
rodata = text->next;
symtab = rodata->next;
pclntab = symtab->next;
- data = segdata.sect;
for(sym = datap; sym != nil; sym = sym->next) {
cursym = sym;
if(sym->type < SDATA)
sym->value += rodata->vaddr;
else
- sym->value += data->vaddr;
+ sym->value += segdata.sect->vaddr;
for(sub = sym->sub; sub != nil; sub = sub->sub)
sub->value += sym->value;
}
static ElfEhdr hdr;
static ElfPhdr *phdr[NSECT];
static ElfShdr *shdr[NSECT];
-static char *interp;
typedef struct Elfstring Elfstring;
struct Elfstring
addsize(s, t);
}
-int
-elfwriteinterp(void)
-{
- int n;
-
- if(interp == nil)
- return 0;
-
- n = strlen(interp)+1;
- cseek(ELFRESERVE-n);
- cwrite(interp, n);
- return n;
-}
-
-void
-elfinterp(ElfShdr *sh, uint64 startva, char *p)
-{
- int n;
-
- interp = p;
- n = strlen(interp)+1;
- sh->addr = startva + ELFRESERVE - n;
- sh->off = ELFRESERVE - n;
- sh->size = n;
-}
-
extern int nelfsym;
int elfverneed;
nsym = nelfsym;
s = lookup(".hash", 0);
- s->type = SELFDATA;
+ s->type = SELFROSECT;
s->reachable = 1;
i = nsym;
return nil;
found:
+ for(i=0; i<hdr.shnum; i++) {
+ sh = shdr[i];
+ if(sh->name == off)
+ return sh;
+ }
+
sh = newElfShdr(off);
if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
sh->type = SHT_PROGBITS;
/* order here is order in output file */
STEXT,
- SELFDATA,
SMACHOPLT,
STYPE,
SSTRING,
SRODATA,
SSYMTAB,
SPCLNTAB,
+ SELFROSECT,
+ SELFSECT,
SDATA,
SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
/* relocation table */
rel = lookup(".rel", 0);
rel->reachable = 1;
- rel->type = SELFDATA;
+ rel->type = SELFROSECT;
initdynimport();
initdynexport();
import (
"debug/dwarf"
"encoding/binary"
+ "net"
+ "os"
"reflect"
+ "runtime"
"testing"
)
}
}
}
+
+func TestNoSectionOverlaps(t *testing.T) {
+ // Ensure 6l outputs sections without overlaps.
+ if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
+ return // not ELF
+ }
+ _ = net.ResolveIPAddr // force dynamic linkage
+ f, err := Open(os.Args[0])
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ for i, si := range f.Sections {
+ sih := si.SectionHeader
+ for j, sj := range f.Sections {
+ sjh := sj.SectionHeader
+ if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 {
+ continue
+ }
+ if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size {
+ t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
+ sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size)
+ }
+ }
+ }
+}