]> Cypherpunks repositories - gostls13.git/commitdiff
ld: remove overlap of ELF sections on dynamic binaries
authorGustavo Niemeyer <gustavo@niemeyer.net>
Wed, 20 Jul 2011 15:47:02 +0000 (12:47 -0300)
committerGustavo Niemeyer <gustavo@niemeyer.net>
Wed, 20 Jul 2011 15:47:02 +0000 (12:47 -0300)
The dynamic ELF sections were pointing to the proper data,
but that data was already owned by the rodata and text sections.
Some ELF references explicitly prohibit multiple sections from
owning the same data, and strip behaves accordingly.

The data for these sections was moved out and their ranges are
now owned by their respective sections.  This change makes strip
happy both with and without -s being provided at link time.

A test was added in debug/elf to ensure there are no regressions
on this area in the future.

Fixes #1242.
Fixes #2022.

NOTE: Tested on Linux amd64/386/arm only.

R=rsc
CC=golang-dev
https://golang.org/cl/4808043

src/cmd/5l/asm.c
src/cmd/5l/span.c
src/cmd/6l/asm.c
src/cmd/8l/asm.c
src/cmd/ld/data.c
src/cmd/ld/elf.c
src/cmd/ld/lib.h
src/cmd/ld/pe.c
src/pkg/debug/elf/file_test.go

index b820cc7082a0bdb1438f222a4f550808d03f570c..8a60ff74a90feaf4b8d21c2e9a0dba20381a74bc 100644 (file)
@@ -157,7 +157,7 @@ doelf(void)
 
        /* predefine strings we need for section headers */
        shstrtab = lookup(".shstrtab", 0);
-       shstrtab->type = SELFDATA;
+       shstrtab->type = SELFROSECT;
        shstrtab->reachable = 1;
 
        elfstr[ElfStrEmpty] = addstring(shstrtab, "");
@@ -186,19 +186,22 @@ doelf(void)
                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, "");
@@ -207,37 +210,37 @@ doelf(void)
                /* 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
@@ -274,8 +277,11 @@ datoff(vlong addr)
 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;
 }
 
@@ -331,7 +337,7 @@ asmb(void)
        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)
@@ -486,9 +492,7 @@ asmb(void)
                        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;
@@ -579,6 +583,11 @@ asmb(void)
                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)
@@ -604,11 +613,6 @@ asmb(void)
                        // 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';
@@ -634,7 +638,7 @@ asmb(void)
                a += elfwritephdrs();
                a += elfwriteshdrs();
                cflush();
-               if(a+elfwriteinterp() > ELFRESERVE)
+               if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
        }
@@ -1825,7 +1829,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                        case SCONST:
                        case SRODATA:
                        case SDATA:
-                       case SELFDATA:
+                       case SELFROSECT:
                        case STYPE:
                        case SSTRING:
                        case SGOSTRING:
index 338c9665bfbb387bffe59a3fbf2a58997b59bfdb..2e1232a1a164df7b905f8fdc6e6892838be62e42 100644 (file)
@@ -416,7 +416,7 @@ symaddr(Sym *s)
                return 0;
        
        case STEXT:
-       case SELFDATA:
+       case SELFROSECT:
        case SRODATA:
        case SDATA:
        case SBSS:
index 723ac0efe3af751a665df4cb189f719122009698..fb088fd9eebf06aba6de2f01643988ed0e8d5935 100644 (file)
@@ -559,7 +559,7 @@ doelf(void)
 
        /* predefine strings we need for section headers */
        shstrtab = lookup(".shstrtab", 0);
-       shstrtab->type = SELFDATA;
+       shstrtab->type = SELFROSECT;
        shstrtab->reachable = 1;
 
        elfstr[ElfStrEmpty] = addstring(shstrtab, "");
@@ -591,15 +591,31 @@ doelf(void)
                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, "");
@@ -608,44 +624,44 @@ doelf(void)
                /* 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
@@ -673,8 +689,11 @@ doelf(void)
 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;
 }
 
@@ -746,7 +765,7 @@ asmb(void)
                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)
@@ -890,7 +909,7 @@ asmb(void)
                                        break;
                                }
                        }
-                       elfinterp(sh, startva, interpreter);
+                       shsym(sh, lookup(".interp", 0));
 
                        ph = newElfPhdr();
                        ph->type = PT_INTERP;
@@ -1014,6 +1033,11 @@ asmb(void)
                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)
@@ -1039,11 +1063,6 @@ asmb(void)
                        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';
@@ -1069,7 +1088,7 @@ asmb(void)
                a += elfwritephdrs();
                a += elfwriteshdrs();
                cflush();
-               if(a+elfwriteinterp() > ELFRESERVE)
+               if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
        case Hwindows:
@@ -1111,7 +1130,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                case SCONST:
                case SRODATA:
                case SDATA:
-               case SELFDATA:
+               case SELFROSECT:
                case SMACHOGOT:
                case STYPE:
                case SSTRING:
index 1832b3767b902beaf51121ed5ba7c446443d5f20..5d49628588a9b06182079c31457eb394cb920f7b 100644 (file)
@@ -519,7 +519,7 @@ doelf(void)
 
        /* predefine strings we need for section headers */
        shstrtab = lookup(".shstrtab", 0);
-       shstrtab->type = SELFDATA;
+       shstrtab->type = SELFROSECT;
        shstrtab->reachable = 1;
 
        elfstr[ElfStrEmpty] = addstring(shstrtab, "");
@@ -552,20 +552,31 @@ doelf(void)
                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;
@@ -573,45 +584,45 @@ doelf(void)
                /* 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
@@ -638,8 +649,11 @@ doelf(void)
 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;
 }
 
@@ -696,7 +710,7 @@ asmb(void)
        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)
@@ -950,17 +964,7 @@ asmb(void)
                        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;
@@ -1084,6 +1088,11 @@ asmb(void)
                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)
@@ -1109,11 +1118,6 @@ asmb(void)
                        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';
@@ -1144,7 +1148,7 @@ asmb(void)
                a += elfwritephdrs();
                a += elfwriteshdrs();
                cflush();
-               if(a+elfwriteinterp() > ELFRESERVE)
+               if(a > ELFRESERVE)      
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
                break;
 
@@ -1200,7 +1204,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                        case SCONST:
                        case SRODATA:
                        case SDATA:
-                       case SELFDATA:
+                       case SELFROSECT:
                        case SMACHO:
                        case SMACHOGOT:
                        case STYPE:
index 9974dbc5136af1c09daeeadba149d7ac3f9c075a..5cf5f4d7a049f70dc0bc87d04b002b2dd9b70a7e 100644 (file)
@@ -821,9 +821,8 @@ dodata(void)
        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;
 
@@ -836,19 +835,41 @@ dodata(void)
                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) {
@@ -950,38 +971,43 @@ address(void)
        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;
        }
index 9c72890d432b0c8cb4b3e2c357b70153be194f34..3fe8ba83a6627224efc3f031c15e32e0fa4f99b5 100644 (file)
@@ -19,7 +19,6 @@ static        int     elf64;
 static ElfEhdr hdr;
 static ElfPhdr *phdr[NSECT];
 static ElfShdr *shdr[NSECT];
-static char    *interp;
 
 typedef struct Elfstring Elfstring;
 struct Elfstring
@@ -304,32 +303,6 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t)
        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;
 
@@ -393,7 +366,7 @@ elfdynhash(void)
 
        nsym = nelfsym;
        s = lookup(".hash", 0);
-       s->type = SELFDATA;
+       s->type = SELFROSECT;
        s->reachable = 1;
 
        i = nsym;
@@ -539,6 +512,12 @@ elfshbits(Section *sect)
        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;
index e2b9858cb04732a33026f272c6000a39b8062cd0..ee7eb87c006a5890f53d82c457a593ac790d67ed 100644 (file)
@@ -34,7 +34,6 @@ enum
        
        /* order here is order in output file */
        STEXT,
-       SELFDATA,
        SMACHOPLT,
        STYPE,
        SSTRING,
@@ -42,6 +41,8 @@ enum
        SRODATA,
        SSYMTAB,
        SPCLNTAB,
+       SELFROSECT,
+       SELFSECT,
        SDATA,
        SMACHO, /* Mach-O __nl_symbol_ptr */
        SMACHOGOT,
index d13801ac02e02594240e955e5725258b8891aa3f..d235e33c1311d46515abaf045aaedff6bad72aff 100644 (file)
@@ -396,7 +396,7 @@ dope(void)
        /* relocation table */
        rel = lookup(".rel", 0);
        rel->reachable = 1;
-       rel->type = SELFDATA;
+       rel->type = SELFROSECT;
 
        initdynimport();
        initdynexport();
index 62e2f3b2df59890dd6813175d764c36b36a4bd9e..451d3d5147f207c06c3ac1deee17ed13d6402ffb 100644 (file)
@@ -7,7 +7,10 @@ package elf
 import (
        "debug/dwarf"
        "encoding/binary"
+       "net"
+       "os"
        "reflect"
+       "runtime"
        "testing"
 )
 
@@ -210,3 +213,29 @@ func TestDWARFRelocations(t *testing.T) {
                }
        }
 }
+
+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)
+                       }
+               }
+       }
+}