Skip to content

Commit 82f9c6c

Browse files
qmuntaldmitshur
authored andcommitted
[release-branch.go1.15] cmd/link: avoid exporting all symbols on windows buildmode=pie
Marking one functions with __declspec(dllexport) forces mingw to create .reloc section without having to export all symbols. See https://insights.sei.cmu.edu/cert/2018/08/when-aslr-is-not-really-aslr---the-case-of-incorrect-assumptions-and-bad-defaults.html for more info. This change cuts 73kb of a "hello world" pie binary. Updates #6853. Updates #40795. Fixes #43592. Change-Id: I3cc57c3b64f61187550bc8751dfa085f106c8475 Reviewed-on: https://go-review.googlesource.com/c/go/+/264459 Trust: Alex Brainman <[email protected]> Run-TryBot: Alex Brainman <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Austin Clements <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/300692 Trust: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent 5055314 commit 82f9c6c

File tree

6 files changed

+52
-7
lines changed

6 files changed

+52
-7
lines changed

misc/cgo/testcshared/cshared_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ func main() {
401401
defer f.Close()
402402
section := f.Section(".edata")
403403
if section == nil {
404-
t.Error(".edata section is not present")
404+
t.Fatalf(".edata section is not present")
405405
}
406406

407407
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
@@ -418,7 +418,8 @@ func main() {
418418
t.Fatalf("binary.Read failed: %v", err)
419419
}
420420

421-
expectedNumber := uint32(2)
421+
// Only the two exported functions and _cgo_dummy_export should be exported
422+
expectedNumber := uint32(3)
422423

423424
if exportAllSymbols {
424425
if e.NumberOfFunctions <= expectedNumber {
@@ -429,10 +430,10 @@ func main() {
429430
}
430431
} else {
431432
if e.NumberOfFunctions != expectedNumber {
432-
t.Fatalf("too many exported functions: %v", e.NumberOfFunctions)
433+
t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber)
433434
}
434435
if e.NumberOfNames != expectedNumber {
435-
t.Fatalf("too many exported names: %v", e.NumberOfNames)
436+
t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber)
436437
}
437438
}
438439
}

src/cmd/go/go_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"debug/elf"
1010
"debug/macho"
1111
"debug/pe"
12+
"encoding/binary"
1213
"flag"
1314
"fmt"
1415
"go/format"
@@ -2166,6 +2167,38 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
21662167
if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
21672168
t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
21682169
}
2170+
if useCgo {
2171+
// Test that only one symbol is exported (#40795).
2172+
// PIE binaries don´t require .edata section but unfortunately
2173+
// binutils doesn´t generate a .reloc section unless there is
2174+
// at least one symbol exported.
2175+
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
2176+
section := f.Section(".edata")
2177+
if section == nil {
2178+
t.Fatalf(".edata section is not present")
2179+
}
2180+
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2181+
type IMAGE_EXPORT_DIRECTORY struct {
2182+
_ [2]uint32
2183+
_ [2]uint16
2184+
_ [2]uint32
2185+
NumberOfFunctions uint32
2186+
NumberOfNames uint32
2187+
_ [3]uint32
2188+
}
2189+
var e IMAGE_EXPORT_DIRECTORY
2190+
if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
2191+
t.Fatalf("binary.Read failed: %v", err)
2192+
}
2193+
2194+
// Only _cgo_dummy_export should be exported
2195+
if e.NumberOfFunctions != 1 {
2196+
t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2197+
}
2198+
if e.NumberOfNames != 1 {
2199+
t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2200+
}
2201+
}
21692202
default:
21702203
panic("unreachable")
21712204
}

src/cmd/link/internal/ld/lib.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,9 +1423,6 @@ func (ctxt *Link) hostlink() {
14231423
if ctxt.Arch.PtrSize >= 8 {
14241424
argv = append(argv, "-Wl,--high-entropy-va")
14251425
}
1426-
// Work around binutils limitation that strips relocation table for dynamicbase.
1427-
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
1428-
argv = append(argv, "-Wl,--export-all-symbols")
14291426
default:
14301427
// ELF.
14311428
if ctxt.UseRelro() {

src/runtime/cgo/gcc_windows_386.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stdio.h>
1010
#include <errno.h>
1111
#include "libcgo.h"
12+
#include "libcgo_windows.h"
1213

1314
static void threadentry(void*);
1415

src/runtime/cgo/gcc_windows_amd64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stdio.h>
1010
#include <errno.h>
1111
#include "libcgo.h"
12+
#include "libcgo_windows.h"
1213

1314
static void threadentry(void*);
1415

src/runtime/cgo/libcgo_windows.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Ensure there's one symbol marked __declspec(dllexport).
6+
// If there are no exported symbols, the unfortunate behavior of
7+
// the binutils linker is to also strip the relocations table,
8+
// resulting in non-PIE binary. The other option is the
9+
// --export-all-symbols flag, but we don't need to export all symbols
10+
// and this may overflow the export table (#40795).
11+
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
12+
__declspec(dllexport) int _cgo_dummy_export;

0 commit comments

Comments
 (0)