diff options
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/cgo/internal/testcshared/cshared_test.go | 116 | ||||
| -rw-r--r-- | src/cmd/go/go_test.go | 33 |
2 files changed, 75 insertions, 74 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) }) } diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 3e691abe41..e4ee9bd1e8 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -9,7 +9,6 @@ import ( "debug/elf" "debug/macho" "debug/pe" - "encoding/binary" "flag" "fmt" "go/format" @@ -2131,38 +2130,6 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) { if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 { t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set") } - if useCgo { - // Test that only one symbol is exported (#40795). - // PIE binaries don´t require .edata section but unfortunately - // binutils doesn´t generate a .reloc section unless there is - // at least one symbol exported. - // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 - section := f.Section(".edata") - if section == nil { - t.Skip(".edata section is not present") - } - // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go - type IMAGE_EXPORT_DIRECTORY struct { - _ [2]uint32 - _ [2]uint16 - _ [2]uint32 - NumberOfFunctions uint32 - NumberOfNames uint32 - _ [3]uint32 - } - var e IMAGE_EXPORT_DIRECTORY - if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil { - t.Fatalf("binary.Read failed: %v", err) - } - - // Only _cgo_dummy_export should be exported - if e.NumberOfFunctions != 1 { - t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions) - } - if e.NumberOfNames != 1 { - t.Fatalf("got %d exported names; want 1", e.NumberOfNames) - } - } default: // testBuildmodePIE opens object files, so it needs to understand the object // file format. |
