diff options
Diffstat (limited to 'src/cmd/ld')
-rw-r--r-- | src/cmd/ld/data.c | 102 | ||||
-rw-r--r-- | src/cmd/ld/elf.c | 12 | ||||
-rw-r--r-- | src/cmd/ld/lib.c | 11 | ||||
-rw-r--r-- | src/cmd/ld/lib.h | 8 |
4 files changed, 106 insertions, 27 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 547494866..c48e1392b 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -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; } diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c index e0a522ad7..51a48c518 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -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 diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index d9e3af4c0..18943d5f3 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -36,6 +36,13 @@ #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; diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 63775b5ff..d7998a6a5 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -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; |