aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/cgo
diff options
context:
space:
mode:
authorqmuntal <quimmuntal@gmail.com>2025-09-22 12:02:13 +0200
committerQuim Muntal <quimmuntal@gmail.com>2025-09-23 11:49:41 -0700
commita13d085a5b66e4d9f3ecfae91c40f62034cfb481 (patch)
tree7d927a0bb27f32641ef8ecab6689c31ff685bcbb /src/cmd/cgo
parent61bf26a9eef5e0c1a5c319f60dfe1e3c51766474 (diff)
downloadgo-a13d085a5b66e4d9f3ecfae91c40f62034cfb481.tar.xz
cmd/cgo: don't hardcode section name in TestNumberOfExportedFunctions
TestNumberOfExportedFunctions checks the number of exported functions announced in the PE export table, getting it from the .edata section. If the section is not found, the test is skipped. However, the PE spec doesn't mandate that the export table be in a section named .edata, making this test prone to being skipped unnecessarily. While here, remove a check in cmd/go.testBuildmodePIE that was testing the same thing in order to verify that the binary had a relocation table . Not only the test is duplicated, but also it in unnecessary because it already testing that the PE characteristics doesn't contain the IMAGE_FILE_RELOCS_STRIPPED flag. Closes #46719 Cq-Include-Trybots: luci.golang.try:gotip-windows-arm64 Change-Id: I28d1e261b38388868dd3c19ef6ddddad7bf105ef Reviewed-on: https://go-review.googlesource.com/c/go/+/705755 Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/cgo')
-rw-r--r--src/cmd/cgo/internal/testcshared/cshared_test.go116
1 files changed, 75 insertions, 41 deletions
diff --git a/src/cmd/cgo/internal/testcshared/cshared_test.go b/src/cmd/cgo/internal/testcshared/cshared_test.go
index 2c4d33f599..f1c30f8f9a 100644
--- a/src/cmd/cgo/internal/testcshared/cshared_test.go
+++ b/src/cmd/cgo/internal/testcshared/cshared_test.go
@@ -375,26 +375,7 @@ func TestExportedSymbols(t *testing.T) {
}
}
-func checkNumberOfExportedFunctionsWindows(t *testing.T, exportAllSymbols bool) {
- const prog = `
-package main
-
-import "C"
-
-//export GoFunc
-func GoFunc() {
- println(42)
-}
-
-//export GoFunc2
-func GoFunc2() {
- println(24)
-}
-
-func main() {
-}
-`
-
+func checkNumberOfExportedFunctionsWindows(t *testing.T, prog string, exportedFunctions int, wantAll bool) {
tmpdir := t.TempDir()
srcfile := filepath.Join(tmpdir, "test.go")
@@ -403,7 +384,7 @@ func main() {
t.Fatal(err)
}
argv := []string{"build", "-buildmode=c-shared"}
- if exportAllSymbols {
+ if wantAll {
argv = append(argv, "-ldflags", "-extldflags=-Wl,--export-all-symbols")
}
argv = append(argv, "-o", objfile, srcfile)
@@ -417,10 +398,36 @@ func main() {
t.Fatalf("pe.Open failed: %v", err)
}
defer f.Close()
- section := f.Section(".edata")
+
+ _, pe64 := f.OptionalHeader.(*pe.OptionalHeader64)
+ // grab the export data directory entry
+ var idd pe.DataDirectory
+ if pe64 {
+ idd = f.OptionalHeader.(*pe.OptionalHeader64).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT]
+ } else {
+ idd = f.OptionalHeader.(*pe.OptionalHeader32).DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT]
+ }
+
+ // figure out which section contains the import directory table
+ var section *pe.Section
+ for _, s := range f.Sections {
+ if s.Offset == 0 {
+ continue
+ }
+ if s.VirtualAddress <= idd.VirtualAddress && idd.VirtualAddress-s.VirtualAddress < s.VirtualSize {
+ section = s
+ break
+ }
+ }
if section == nil {
- t.Skip(".edata section is not present")
+ t.Fatal("no section contains export directory")
}
+ d, err := section.Data()
+ if err != nil {
+ t.Fatal(err)
+ }
+ // seek to the virtual address specified in the export data directory
+ d = d[idd.VirtualAddress-section.VirtualAddress:]
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
type IMAGE_EXPORT_DIRECTORY struct {
@@ -432,26 +439,22 @@ func main() {
_ [3]uint32
}
var e IMAGE_EXPORT_DIRECTORY
- if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
+ if err := binary.Read(bytes.NewReader(d), binary.LittleEndian, &e); err != nil {
t.Fatalf("binary.Read failed: %v", err)
}
- // Only the two exported functions and _cgo_dummy_export should be exported
- expectedNumber := uint32(3)
-
- if exportAllSymbols {
- if e.NumberOfFunctions <= expectedNumber {
- t.Fatalf("missing exported functions: %v", e.NumberOfFunctions)
- }
- if e.NumberOfNames <= expectedNumber {
- t.Fatalf("missing exported names: %v", e.NumberOfNames)
+ // Only the two exported functions and _cgo_dummy_export should be exported.
+ // NumberOfNames is the number of functions exported with a unique name.
+ // NumberOfFunctions can be higher than that because it also counts
+ // functions exported only by ordinal, a unique number asigned by the linker,
+ // and linkers might add an unknown number of their own ordinal-only functions.
+ if wantAll {
+ if e.NumberOfNames <= uint32(exportedFunctions) {
+ t.Errorf("got %d exported names, want > %d", e.NumberOfNames, exportedFunctions)
}
} else {
- if e.NumberOfFunctions != expectedNumber {
- t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber)
- }
- if e.NumberOfNames != expectedNumber {
- t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber)
+ if e.NumberOfNames > uint32(exportedFunctions) {
+ t.Errorf("got %d exported names, want <= %d", e.NumberOfNames, exportedFunctions)
}
}
}
@@ -467,11 +470,42 @@ func TestNumberOfExportedFunctions(t *testing.T) {
t.Parallel()
- t.Run("OnlyExported", func(t *testing.T) {
- checkNumberOfExportedFunctionsWindows(t, false)
+ const prog0 = `
+package main
+
+import "C"
+
+func main() {
+}
+`
+
+ const prog2 = `
+package main
+
+import "C"
+
+//export GoFunc
+func GoFunc() {
+ println(42)
+}
+
+//export GoFunc2
+func GoFunc2() {
+ println(24)
+}
+
+func main() {
+}
+`
+ // All programs export _cgo_dummy_export, so add 1 to the expected counts.
+ t.Run("OnlyExported/0", func(t *testing.T) {
+ checkNumberOfExportedFunctionsWindows(t, prog0, 0+1, false)
+ })
+ t.Run("OnlyExported/2", func(t *testing.T) {
+ checkNumberOfExportedFunctionsWindows(t, prog2, 2+1, false)
})
t.Run("All", func(t *testing.T) {
- checkNumberOfExportedFunctionsWindows(t, true)
+ checkNumberOfExportedFunctionsWindows(t, prog2, 2+1, true)
})
}