]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: place read-only data in non-executable segment
authorRuss Cox <rsc@golang.org>
Fri, 12 Jul 2013 02:52:48 +0000 (22:52 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 12 Jul 2013 02:52:48 +0000 (22:52 -0400)
R=golang-dev, dave, r
CC=golang-dev, nigeltao
https://golang.org/cl/10713043

src/cmd/5l/asm.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.c
src/cmd/ld/lib.h

index 4a772987048b3c762076cab2d1d245715d98ecdd..20ed5e5ae1cb5f1e8e4ecd095315e90f954f01ec 100644 (file)
@@ -550,13 +550,20 @@ asmb(void)
        sect = segtext.sect;
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
-
-       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
        }
 
+       if(segrodata.filelen > 0) {
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f rodatblk\n", cputime());
+               Bflush(&bso);
+
+               cseek(segrodata.fileoff);
+               datblk(segrodata.vaddr, segrodata.filelen);
+       }
+
        if(debug['v'])
                Bprint(&bso, "%5.2f datblk\n", cputime());
        Bflush(&bso);
@@ -587,7 +594,7 @@ asmb(void)
                        symo = HEADR+segtext.len+segdata.filelen;
                        break;
                ElfSym:
-                       symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
+                       symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen;
                        symo = rnd(symo, INITRND);
                        break;
                }
index 8807a6ed531c8db8315d077204c3b168462a5ee7..81a16bc6a519ec43295efcccb2ae62f425026075 100644 (file)
@@ -625,13 +625,20 @@ asmb(void)
        sect = segtext.sect;
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
-
-       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
        }
 
+       if(segrodata.filelen > 0) {
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f rodatblk\n", cputime());
+               Bflush(&bso);
+
+               cseek(segrodata.fileoff);
+               datblk(segrodata.vaddr, segrodata.filelen);
+       }
+
        if(debug['v'])
                Bprint(&bso, "%5.2f datblk\n", cputime());
        Bflush(&bso);
@@ -696,7 +703,7 @@ asmb(void)
                case Hfreebsd:
                case Hnetbsd:
                case Hopenbsd:
-                       symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
+                       symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen;
                        symo = rnd(symo, INITRND);
                        break;
                case Hwindows:
index 18591cd2f3cad8a91b06e7001bcd384aa0daa61b..712e93e2bd90fbf497a8cd358b7a9da1db087a01 100644 (file)
@@ -595,12 +595,19 @@ asmb(void)
        sect = segtext.sect;
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
-
-       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
        }
+       
+       if(segrodata.filelen > 0) {
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f rodatblk\n", cputime());
+               Bflush(&bso);
+
+               cseek(segrodata.fileoff);
+               datblk(segrodata.vaddr, segrodata.filelen);
+       }
 
        if(debug['v'])
                Bprint(&bso, "%5.2f datblk\n", cputime());
@@ -655,7 +662,7 @@ asmb(void)
                        symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
                        break;
                Elfsym:
-                       symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
+                       symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen;
                        symo = rnd(symo, INITRND);
                        break;
                case Hwindows:
index 547494866e8b941e9bd27ac9c6d8065b83eb2501..c48e1392b06df1f54414c1b1aee1712144a71c5c 100644 (file)
@@ -1040,6 +1040,7 @@ dodata(void)
        int32 n;
        vlong datsize;
        Section *sect;
+       Segment *segro;
        Sym *s, *last, **l;
        Sym *gcdata1, *gcbss1;
 
@@ -1130,7 +1131,7 @@ dodata(void)
                sect->vaddr = datsize;
                s->sect = sect;
                s->type = SDATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
                sect->len = datsize - sect->vaddr;
        }
@@ -1146,7 +1147,7 @@ dodata(void)
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SDATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
@@ -1163,7 +1164,7 @@ dodata(void)
                        datsize = aligndatsize(datsize, s);
                        s->sect = sect;
                        s->type = SDATA;
-                       s->value = datsize;
+                       s->value = datsize - sect->vaddr;
                        growdatsize(&datsize, s);
                }
                sect->len = datsize - sect->vaddr;
@@ -1184,7 +1185,7 @@ dodata(void)
                s->sect = sect;
                s->type = SDATA;
                datsize = aligndatsize(datsize, s);
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                gcaddsym(gcdata1, s, datsize - sect->vaddr);  // gc
                growdatsize(&datsize, s);
        }
@@ -1203,7 +1204,7 @@ dodata(void)
        for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
                s->sect = sect;
                datsize = aligndatsize(datsize, s);
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                gcaddsym(gcbss1, s, datsize - sect->vaddr);  // gc
                growdatsize(&datsize, s);
        }
@@ -1222,7 +1223,7 @@ dodata(void)
        for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
@@ -1241,7 +1242,7 @@ dodata(void)
                for(; s != nil && s->type == STLSBSS; s = s->next) {
                        datsize = aligndatsize(datsize, s);
                        s->sect = sect;
-                       s->value = datsize;
+                       s->value = datsize - sect->vaddr;
                        growdatsize(&datsize, s);
                }
                sect->len = datsize;
@@ -1252,27 +1253,56 @@ dodata(void)
                diag("unexpected symbol type %d for %s", s->type, s->name);
        }
 
-       /* we finished segdata, begin segtext */
+       /*
+        * We finished data, begin read-only data.
+        * Not all systems support a separate read-only non-executable data section.
+        * ELF systems do.
+        * OS X and Plan 9 do not.
+        * Windows PE may, but if so we have not implemented it.
+        * And if we're using external linking mode, the point is moot,
+        * since it's not our decision; that code expects the sections in
+        * segtext.
+        */
+       if(iself && linkmode == LinkInternal)
+               segro = &segrodata;
+       else
+               segro = &segtext;
+
        s = datap;
+       
+       datsize = 0;
+       
+       /* read-only executable ELF, Mach-O sections */
+       for(; s != nil && s->type < STYPE; s = s->next) {
+               sect = addsection(&segtext, s->name, 04);
+               sect->align = symalign(s);
+               datsize = rnd(datsize, sect->align);
+               sect->vaddr = datsize;
+               s->sect = sect;
+               s->type = SRODATA;
+               s->value = datsize - sect->vaddr;
+               growdatsize(&datsize, s);
+               sect->len = datsize - sect->vaddr;
+       }
 
        /* read-only data */
-       sect = addsection(&segtext, ".rodata", 04);
+       sect = addsection(segro, ".rodata", 04);
        sect->align = maxalign(s, STYPELINK-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = 0;
        lookup("rodata", 0)->sect = sect;
        lookup("erodata", 0)->sect = sect;
-       datsize = 0;
        for(; s != nil && s->type < STYPELINK; s = s->next) {
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
 
        /* typelink */
-       sect = addsection(&segtext, ".typelink", 04);
+       sect = addsection(segro, ".typelink", 04);
        sect->align = maxalign(s, STYPELINK);
        datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
@@ -1282,13 +1312,13 @@ dodata(void)
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
 
        /* gosymtab */
-       sect = addsection(&segtext, ".gosymtab", 04);
+       sect = addsection(segro, ".gosymtab", 04);
        sect->align = maxalign(s, SPCLNTAB-1);
        datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
@@ -1298,13 +1328,13 @@ dodata(void)
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
 
        /* gopclntab */
-       sect = addsection(&segtext, ".gopclntab", 04);
+       sect = addsection(segro, ".gopclntab", 04);
        sect->align = maxalign(s, SELFROSECT-1);
        datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
@@ -1314,33 +1344,35 @@ dodata(void)
                datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
        }
        sect->len = datsize - sect->vaddr;
 
        /* read-only ELF, Mach-O sections */
        for(; s != nil && s->type < SELFSECT; s = s->next) {
-               sect = addsection(&segtext, s->name, 04);
+               sect = addsection(segro, s->name, 04);
                sect->align = symalign(s);
                datsize = rnd(datsize, sect->align);
                sect->vaddr = datsize;
                s->sect = sect;
                s->type = SRODATA;
-               s->value = datsize;
+               s->value = datsize - sect->vaddr;
                growdatsize(&datsize, s);
                sect->len = datsize - sect->vaddr;
        }
 
        // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
        if(datsize != (uint32)datsize) {
-               diag("text segment too large");
+               diag("read-only data segment too large");
        }
        
        /* number the sections */
        n = 1;
        for(sect = segtext.sect; sect != nil; sect = sect->next)
                sect->extnum = n++;
+       for(sect = segrodata.sect; sect != nil; sect = sect->next)
+               sect->extnum = n++;
        for(sect = segdata.sect; sect != nil; sect = sect->next)
                sect->extnum = n++;
 }
@@ -1402,6 +1434,7 @@ address(void)
        segtext.vaddr = va;
        segtext.fileoff = HEADR;
        for(s=segtext.sect; s != nil; s=s->next) {
+//print("%s at %#llux + %#llux\n", s->name, va, (vlong)s->len);
                va = rnd(va, s->align);
                s->vaddr = va;
                va += s->len;
@@ -1409,8 +1442,25 @@ address(void)
        segtext.len = va - INITTEXT;
        segtext.filelen = segtext.len;
 
-       va = rnd(va, INITRND);
+       if(segrodata.sect != nil) {
+               // align to page boundary so as not to mix
+               // rodata and executable text.
+               va = rnd(va, INITRND);
+
+               segrodata.rwx = 04;
+               segrodata.vaddr = va;
+               segrodata.fileoff = va - segtext.vaddr + segtext.fileoff;
+               segrodata.filelen = 0;
+               for(s=segrodata.sect; s != nil; s=s->next) {
+                       va = rnd(va, s->align);
+                       s->vaddr = va;
+                       va += s->len;
+               }
+               segrodata.len = va - segrodata.vaddr;
+               segrodata.filelen = segrodata.len;
+       }
 
+       va = rnd(va, INITRND);
        segdata.rwx = 06;
        segdata.vaddr = va;
        segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
@@ -1445,17 +1495,17 @@ address(void)
        segdata.filelen = bss->vaddr - segdata.vaddr;
 
        text = segtext.sect;
-       rodata = text->next;
+       if(segrodata.sect)
+               rodata = segrodata.sect;
+       else
+               rodata = text->next;
        typelink = rodata->next;
        symtab = typelink->next;
        pclntab = symtab->next;
 
        for(sym = datap; sym != nil; sym = sym->next) {
                cursym = sym;
-               if(sym->type < SNOPTRDATA)
-                       sym->value += rodata->vaddr;
-               else
-                       sym->value += segdata.sect->vaddr;
+               sym->value += sym->sect->vaddr;
                for(sub = sym->sub; sub != nil; sub = sub->sub)
                        sub->value += sym->value;
        }
index e0a522ad7f30f1116e8d9a70ecff89913f706bb5..51a48c5181e13a1a8ac60f3a69188ea5ae650823 100644 (file)
@@ -864,6 +864,8 @@ elfemitreloc(void)
        elfrelocsect(segtext.sect, textp);
        for(sect=segtext.sect->next; sect!=nil; sect=sect->next)
                elfrelocsect(sect, datap);      
+       for(sect=segrodata.sect; sect!=nil; sect=sect->next)
+               elfrelocsect(sect, datap);      
        for(sect=segdata.sect; sect!=nil; sect=sect->next)
                elfrelocsect(sect, datap);      
 }
@@ -1001,7 +1003,7 @@ doelf(void)
 
                s = lookup(".plt", 0);
                s->reachable = 1;
-               s->type = SELFROSECT;
+               s->type = SELFRXSECT;
                
                elfsetupplt();
                
@@ -1105,6 +1107,8 @@ asmbelfsetup(void)
        
        for(sect=segtext.sect; sect!=nil; sect=sect->next)
                elfshalloc(sect);
+       for(sect=segrodata.sect; sect!=nil; sect=sect->next)
+               elfshalloc(sect);
        for(sect=segdata.sect; sect!=nil; sect=sect->next)
                elfshalloc(sect);
 }
@@ -1232,6 +1236,8 @@ asmbelf(vlong symo)
        USED(resoff);
 
        elfphload(&segtext);
+       if(segrodata.sect != nil)
+               elfphload(&segrodata);
        elfphload(&segdata);
 
        /* Dynamic linking sections */
@@ -1397,12 +1403,16 @@ elfobj:
 
        for(sect=segtext.sect; sect!=nil; sect=sect->next)
                elfshbits(sect);
+       for(sect=segrodata.sect; sect!=nil; sect=sect->next)
+               elfshbits(sect);
        for(sect=segdata.sect; sect!=nil; sect=sect->next)
                elfshbits(sect);
 
        if(linkmode == LinkExternal) {
                for(sect=segtext.sect; sect!=nil; sect=sect->next)
                        elfshreloc(sect);
+               for(sect=segrodata.sect; sect!=nil; sect=sect->next)
+                       elfshreloc(sect);
                for(sect=segdata.sect; sect!=nil; sect=sect->next)
                        elfshreloc(sect);
                // add a .note.GNU-stack section to mark the stack as non-executable
index d9e3af4c0fb8a8e23f1bb467f63bc5972416da73..18943d5f3d8b1014d6a1e5ce9fb8bf1e4f520949 100644 (file)
 
 #include       <ar.h>
 
+enum
+{
+       // Whether to assume that the external linker is "gold"
+       // (http://sourceware.org/ml/binutils/2008-03/msg00162.html).
+       AssumeGoldLinker = 0,
+};
+
 int iconv(Fmt*);
 
 char   symname[]       = SYMDEF;
@@ -676,6 +683,10 @@ hostlink(void)
        }
        if(HEADTYPE == Hdarwin)
                argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
+       
+       if(iself && AssumeGoldLinker)
+               argv[argc++] = "-Wl,--rosegment";
+
        argv[argc++] = "-o";
        argv[argc++] = outfile;
        
index 63775b5ff59976b5ca4cb306b3e5fc1ac9f764e6..d7998a6a5ab589af32f3ab6abc64d02a310d4c3e 100644 (file)
@@ -33,7 +33,11 @@ enum
        Sxxx,
 
        /* order here is order in output file */
+       /* readonly, executable */
        STEXT,
+       SELFRXSECT,
+       
+       /* readonly, non-executable */
        STYPE,
        SSTRING,
        SGOSTRING,
@@ -42,6 +46,8 @@ enum
        SSYMTAB,
        SPCLNTAB,
        SELFROSECT,
+       
+       /* writable, non-executable */
        SMACHOPLT,
        SELFSECT,
        SMACHO, /* Mach-O __nl_symbol_ptr */
@@ -54,6 +60,7 @@ enum
        SNOPTRBSS,
        STLSBSS,
 
+       /* not mapped */
        SXREF,
        SMACHOSYMSTR,
        SMACHOSYMTAB,
@@ -177,6 +184,7 @@ enum
 };
 
 EXTERN Segment segtext;
+EXTERN Segment segrodata;
 EXTERN Segment segdata;
 EXTERN Segment segdwarf;