mirror of
https://github.com/golang/go
synced 2024-11-23 21:10:05 -07:00
cmd/link: split pe .text section into .text and .rdata
Fixes #24725 Change-Id: I2864b88315ab15be036e8940d0a5884d876698d6 Reviewed-on: https://go-review.googlesource.com/115975 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
1f137052e4
commit
d67db88146
@ -1352,9 +1352,8 @@ func (ctxt *Link) dodata() {
|
||||
/*
|
||||
* 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.
|
||||
@ -1362,6 +1361,8 @@ func (ctxt *Link) dodata() {
|
||||
var segro *sym.Segment
|
||||
if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
|
||||
segro = &Segrodata
|
||||
} else if ctxt.HeadType == objabi.Hwindows {
|
||||
segro = &Segrodata
|
||||
} else {
|
||||
segro = &Segtext
|
||||
}
|
||||
@ -1940,6 +1941,9 @@ func (ctxt *Link) address() {
|
||||
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
|
||||
@ -1974,7 +1978,7 @@ func (ctxt *Link) address() {
|
||||
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
|
||||
|
@ -395,6 +395,7 @@ type peFile struct {
|
||||
sections []*peSection
|
||||
stringTable peStringTable
|
||||
textSect *peSection
|
||||
rdataSect *peSection
|
||||
dataSect *peSection
|
||||
bssSect *peSection
|
||||
ctorsSect *peSection
|
||||
@ -548,21 +549,24 @@ func (f *peFile) emitRelocations(ctxt *Link) {
|
||||
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 {
|
||||
@ -622,8 +626,11 @@ func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int
|
||||
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 {
|
||||
@ -904,7 +911,11 @@ func Peinit(ctxt *Link) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -1325,6 +1336,19 @@ func Asmbpe(ctxt *Link) {
|
||||
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))
|
||||
|
@ -126,6 +126,15 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
|
||||
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))
|
||||
@ -147,6 +156,12 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
|
||||
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 {
|
||||
@ -155,6 +170,9 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user