mirror of
https://github.com/golang/go
synced 2024-11-17 05:54:46 -07:00
cmd/link: clean up windows PE generation
A bunch of places are a bit too picky about the architecture. Simplify them. Also use a large PEBASE for 64-bit systems. This more closely matches what is usually used on Windows x86-64 and is required for Windows arm64. Unfortunately, we still need a special case for x86-64 because of some cgo relocations. This may be fixable separately. This CL is part of a stack adding windows/arm64 support (#36439), intended to land in the Go 1.17 cycle. This CL is, however, not windows/arm64-specific. It is cleanup meant to make the port (and future ports) easier. Change-Id: I65212d28ad4d8c40e2b70dc29f7fce072babecb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/288816 Trust: Russ Cox <rsc@golang.org> Trust: Jason A. Donenfeld <Jason@zx2c4.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
b6379f190b
commit
1c659f2525
@ -42,11 +42,11 @@ type IMAGE_EXPORT_DIRECTORY struct {
|
||||
AddressOfNameOrdinals uint32
|
||||
}
|
||||
|
||||
const (
|
||||
PEBASE = 0x00400000
|
||||
)
|
||||
|
||||
var (
|
||||
// PEBASE is the base address for the executable.
|
||||
// It is small for 32-bit and large for 64-bit.
|
||||
PEBASE int64
|
||||
|
||||
// SectionAlignment must be greater than or equal to FileAlignment.
|
||||
// The default is the page size for the architecture.
|
||||
PESECTALIGN int64 = 0x1000
|
||||
@ -316,8 +316,8 @@ func (sect *peSection) checkOffset(off int64) {
|
||||
// checkSegment verifies COFF section sect matches address
|
||||
// and file offset provided in segment seg.
|
||||
func (sect *peSection) checkSegment(seg *sym.Segment) {
|
||||
if seg.Vaddr-PEBASE != uint64(sect.virtualAddress) {
|
||||
Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-PEBASE)))
|
||||
if seg.Vaddr-uint64(PEBASE) != uint64(sect.virtualAddress) {
|
||||
Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-uint64(PEBASE))))
|
||||
errorexit()
|
||||
}
|
||||
if seg.Fileoff != uint64(sect.pointerToRawData) {
|
||||
@ -852,8 +852,8 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
|
||||
}
|
||||
oh64.BaseOfCode = f.textSect.virtualAddress
|
||||
oh.BaseOfCode = f.textSect.virtualAddress
|
||||
oh64.ImageBase = PEBASE
|
||||
oh.ImageBase = PEBASE
|
||||
oh64.ImageBase = uint64(PEBASE)
|
||||
oh.ImageBase = uint32(PEBASE)
|
||||
oh64.SectionAlignment = uint32(PESECTALIGN)
|
||||
oh.SectionAlignment = uint32(PESECTALIGN)
|
||||
oh64.FileAlignment = uint32(PEFILEALIGN)
|
||||
@ -891,13 +891,7 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
|
||||
oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
|
||||
// The DLL can be relocated at load time.
|
||||
switch ctxt.Arch.Family {
|
||||
case sys.AMD64, sys.I386:
|
||||
if ctxt.BuildMode == BuildModePIE {
|
||||
oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
}
|
||||
case sys.ARM:
|
||||
if needPEBaseReloc(ctxt) {
|
||||
oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
}
|
||||
@ -975,18 +969,23 @@ var pefile peFile
|
||||
func Peinit(ctxt *Link) {
|
||||
var l int
|
||||
|
||||
switch ctxt.Arch.Family {
|
||||
// 64-bit architectures
|
||||
case sys.AMD64:
|
||||
if ctxt.Arch.PtrSize == 8 {
|
||||
// 64-bit architectures
|
||||
pe64 = 1
|
||||
PEBASE = 1 << 32
|
||||
if ctxt.Arch.Family == sys.AMD64 {
|
||||
// TODO(rsc): For cgo we currently use 32-bit relocations
|
||||
// that fail when PEBASE is too large.
|
||||
// We need to fix this, but for now, use a smaller PEBASE.
|
||||
PEBASE = 1 << 22
|
||||
}
|
||||
var oh64 pe.OptionalHeader64
|
||||
l = binary.Size(&oh64)
|
||||
|
||||
// 32-bit architectures
|
||||
default:
|
||||
} else {
|
||||
// 32-bit architectures
|
||||
PEBASE = 1 << 22
|
||||
var oh pe.OptionalHeader32
|
||||
l = binary.Size(&oh)
|
||||
|
||||
}
|
||||
|
||||
if ctxt.LinkMode == LinkExternal {
|
||||
@ -1210,7 +1209,7 @@ func addimports(ctxt *Link, datsect *peSection) {
|
||||
endoff := ctxt.Out.Offset()
|
||||
|
||||
// write FirstThunks (allocated in .data section)
|
||||
ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - PEBASE
|
||||
ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - uint64(PEBASE)
|
||||
|
||||
ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
|
||||
for d := dr; d != nil; d = d.next {
|
||||
@ -1463,17 +1462,18 @@ func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
|
||||
}
|
||||
}
|
||||
|
||||
func needPEBaseReloc(ctxt *Link) bool {
|
||||
// Non-PIE x86 binaries don't need the base relocation table.
|
||||
// Everyone else does.
|
||||
if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func addPEBaseReloc(ctxt *Link) {
|
||||
// Arm does not work without base relocation table.
|
||||
// 386 and amd64 will only require the table for BuildModePIE.
|
||||
switch ctxt.Arch.Family {
|
||||
default:
|
||||
if !needPEBaseReloc(ctxt) {
|
||||
return
|
||||
case sys.I386, sys.AMD64:
|
||||
if ctxt.BuildMode != BuildModePIE {
|
||||
return
|
||||
}
|
||||
case sys.ARM:
|
||||
}
|
||||
|
||||
var rt peBaseRelocTable
|
||||
@ -1562,12 +1562,6 @@ func addpersrc(ctxt *Link) {
|
||||
}
|
||||
|
||||
func asmbPe(ctxt *Link) {
|
||||
switch ctxt.Arch.Family {
|
||||
default:
|
||||
Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
|
||||
case sys.AMD64, sys.I386, sys.ARM:
|
||||
}
|
||||
|
||||
t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
|
||||
t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
|
||||
if ctxt.LinkMode == LinkExternal {
|
||||
|
Loading…
Reference in New Issue
Block a user