/*
* We finished data, begin read-only data.
* Not all systems support a separate read-only non-executable data section.
- * ELF systems do.
+ * ELF and Windows PE 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.
var segro *sym.Segment
if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
segro = &Segrodata
+ } else if ctxt.HeadType == objabi.Hwindows {
+ segro = &Segrodata
} else {
segro = &Segtext
}
Segrodata.Vaddr = va
Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
Segrodata.Filelen = 0
+ if ctxt.HeadType == objabi.Hwindows {
+ Segrodata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
+ }
for _, s := range Segrodata.Sections {
va = uint64(Rnd(int64(va), int64(s.Align)))
s.Vaddr = va
Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
Segdata.Filelen = 0
if ctxt.HeadType == objabi.Hwindows {
- Segdata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
+ Segdata.Fileoff = Segrodata.Fileoff + uint64(Rnd(int64(Segrodata.Length), PEFILEALIGN))
}
if ctxt.HeadType == objabi.Hplan9 {
Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen
sections []*peSection
stringTable peStringTable
textSect *peSection
+ rdataSect *peSection
dataSect *peSection
bssSect *peSection
ctorsSect *peSection
return relocs
}
- f.textSect.emitRelocations(ctxt.Out, func() int {
- n := relocsect(Segtext.Sections[0], ctxt.Textp, Segtext.Vaddr)
- for _, sect := range Segtext.Sections[1:] {
- n += relocsect(sect, datap, Segtext.Vaddr)
- }
- return n
- })
-
- f.dataSect.emitRelocations(ctxt.Out, func() int {
- var n int
- for _, sect := range Segdata.Sections {
- n += relocsect(sect, datap, Segdata.Vaddr)
- }
- return n
- })
+ sects := []struct {
+ peSect *peSection
+ seg *sym.Segment
+ syms []*sym.Symbol
+ }{
+ {f.textSect, &Segtext, ctxt.Textp},
+ {f.rdataSect, &Segrodata, datap},
+ {f.dataSect, &Segdata, datap},
+ }
+ for _, s := range sects {
+ s.peSect.emitRelocations(ctxt.Out, func() int {
+ var n int
+ for _, sect := range s.seg.Sections {
+ n += relocsect(sect, s.syms, s.seg.Vaddr)
+ }
+ return n
+ })
+ }
dwarfLoop:
for _, sect := range Segdwarf.Sections {
if s.Sect.Seg == &Segtext {
return f.textSect.index, int64(uint64(s.Value) - Segtext.Vaddr), nil
}
+ if s.Sect.Seg == &Segrodata {
+ return f.rdataSect.index, int64(uint64(s.Value) - Segrodata.Vaddr), nil
+ }
if s.Sect.Seg != &Segdata {
- return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .data section", s.Name)
+ return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", s.Name)
}
v := uint64(s.Value) - Segdata.Vaddr
if linkmode != LinkExternal {
}
if ctxt.LinkMode == LinkExternal {
- PESECTALIGN = 0
+ // .rdata section will contain "masks" and "shifts" symbols, and they
+ // need to be aligned to 16-bytes. So make all sections aligned
+ // to 32-byte and mark them all IMAGE_SCN_ALIGN_32BYTES so external
+ // linker will honour that requirement.
+ PESECTALIGN = 32
PEFILEALIGN = 0
}
t.checkSegment(&Segtext)
pefile.textSect = t
+ ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
+ ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+ if ctxt.LinkMode == LinkExternal {
+ // some data symbols (e.g. masks) end up in the .rdata section, and they normally
+ // expect larger alignment requirement than the default text section alignment.
+ ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
+ } else {
+ // TODO(brainman): should not need IMAGE_SCN_MEM_EXECUTE, but I do not know why it carshes without it
+ ro.characteristics |= IMAGE_SCN_MEM_EXECUTE
+ }
+ ro.checkSegment(&Segrodata)
+ pefile.rdataSect = ro
+
var d *peSection
if ctxt.LinkMode != LinkExternal {
d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
names["main."+f[0]] = f[1]
}
+ runtimeSyms := map[string]string{
+ "runtime.text": "T",
+ "runtime.etext": "T",
+ "runtime.rodata": "R",
+ "runtime.erodata": "R",
+ "runtime.epclntab": "R",
+ "runtime.noptrdata": "D",
+ }
+
out, err = exec.Command(testnmpath, exe).CombinedOutput()
if err != nil {
t.Fatalf("go tool nm: %v\n%s", err, string(out))
if _, found := dups[name]; found {
t.Errorf("duplicate name of %q is found", name)
}
+ if stype, found := runtimeSyms[name]; found {
+ if want, have := stype, strings.ToUpper(f[1]); have != want {
+ t.Errorf("want %s type for %s symbol, but have %s", want, name, have)
+ }
+ delete(runtimeSyms, name)
+ }
}
err = scanner.Err()
if err != nil {
if len(names) > 0 {
t.Errorf("executable is missing %v symbols", names)
}
+ if len(runtimeSyms) > 0 {
+ t.Errorf("executable is missing %v symbols", runtimeSyms)
+ }
}
func TestGoExec(t *testing.T) {