]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: use >4GB base address for 64-bit PE binaries
authorqmuntal <quimmuntal@gmail.com>
Fri, 9 May 2025 15:42:48 +0000 (17:42 +0200)
committerQuim Muntal <quimmuntal@gmail.com>
Mon, 12 May 2025 18:05:28 +0000 (11:05 -0700)
Windows prefers 64-bit binaries to be loaded at an address above 4GB.

Having a preferred base address below this boundary triggers a
compatibility mode in Address Space Layout Randomization (ASLR) on
recent versions of Windows that reduces the number of locations to which
ASLR may relocate the binary.

The Go internal linker was using a smaller base address due to an issue
with how dynamic cgo symbols were relocated, which has been fixed in
this CL.

Fixes #73561.

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest
Change-Id: Ia8cb35d57d921d9be706a8975fa085af7996f124
Reviewed-on: https://go-review.googlesource.com/c/go/+/671515
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/pe.go
test/nilptr.go

index b3e1ac457dc0f5187a9ca2d0352dc6b1f96c6d25..939de1187613279d229bb5de282172001ee5a3bd 100644 (file)
@@ -894,10 +894,15 @@ func windynrelocsym(ctxt *Link, rel *loader.SymbolBuilder, s loader.Sym) error {
                                rel.AddUint8(0x90)
                                rel.AddUint8(0x90)
                        case sys.AMD64:
+                               // The relocation symbol might be at an absolute offset
+                               // higher than 32 bits, but the jump instruction can't
+                               // encode more than 32 bit offsets. We use a jump
+                               // relative to the instruction pointer to get around this
+                               // limitation.
                                rel.AddUint8(0xff)
-                               rel.AddUint8(0x24)
                                rel.AddUint8(0x25)
-                               rel.AddAddrPlus4(ctxt.Arch, targ, 0)
+                               rel.AddPCRelPlus(ctxt.Arch, targ, 0)
+                               rel.AddUint8(0x90)
                                rel.AddUint8(0x90)
                        }
                } else if tplt >= 0 {
index 2808644150c24294b2aae5725f4901c29e30a980..fbfd928e873be55f70a1c9b9b0ff1315eced7082 100644 (file)
@@ -1097,18 +1097,10 @@ func Peinit(ctxt *Link) {
        if ctxt.Arch.PtrSize == 8 {
                // 64-bit architectures
                pe64 = true
-               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)
        } else {
                // 32-bit architectures
-               PEBASE = 1 << 22
                var oh pe.OptionalHeader32
                l = binary.Size(&oh)
        }
@@ -1122,6 +1114,13 @@ func Peinit(ctxt *Link) {
                PEFILEALIGN = 0
                // We are creating an object file. The absolute address is irrelevant.
                PEBASE = 0
+       } else {
+               // Use the same base image address as MSVC and LLVM.
+               if pe64 {
+                       PEBASE = 0x140000000
+               } else {
+                       PEBASE = 0x400000
+               }
        }
 
        var sh [16]pe.SectionHeader32
index 7f42e930bdee7e95f13d28b8a3ccea4818501241..6a60b18fc110cf8f92319d3920ab4c9acade33b8 100644 (file)
@@ -7,8 +7,8 @@
 // Test that the implementation catches nil ptr indirection
 // in a large address space.
 
-// Address space starts at 1<<32 on AIX and on darwin/arm64 and on windows/arm64, so dummy is too far.
-//go:build !aix && (!darwin || !arm64) && (!windows || !arm64)
+// Address space starts at 1<<32 on AIX and on darwin/arm64 and on windows/[amd64/arm64], so dummy is too far.
+//go:build !aix && (!darwin || !arm64) && (!windows || (!amd64 && !arm64))
 
 package main