aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2025-11-17 20:20:26 -0800
committerGopher Robot <gobot@golang.org>2025-11-26 20:29:52 -0800
commitf1bbc66a10a545811a21dcf9f9431e783aafcb42 (patch)
treeb03b6c0098812b097f75c1fd21f1c9fc1ddb9e19 /src/cmd
parent003f52407a8a32575084ffc4b15486aa8757ec74 (diff)
downloadgo-f1bbc66a10a545811a21dcf9f9431e783aafcb42.tar.xz
cmd/link: test that moduledata is in its own section
This is a test for CL 720660. For #76038 Change-Id: I2f630b738ddb5a9c48e3c5d4374c1e995910541a Reviewed-on: https://go-review.googlesource.com/c/go/+/721480 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/link/link_test.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 77bbc3c1f8..0c4cde0399 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -2114,3 +2114,100 @@ func TestFuncdataPlacement(t *testing.T) {
t.Errorf("findfunctab address %#x not between %#x and %#x", moddata.findfunctab, pclntabAddr, pclntabEnd)
}
}
+
+// Test that moduledata winds up in its own .go.module section.
+func TestModuledataPlacement(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ t.Parallel()
+
+ tmpdir := t.TempDir()
+ src := filepath.Join(tmpdir, "x.go")
+ if err := os.WriteFile(src, []byte(trivialSrc), 0o444); err != nil {
+ t.Fatal(err)
+ }
+
+ exe := filepath.Join(tmpdir, "x.exe")
+ cmd := goCmd(t, "build", "-o", exe, src)
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("build failed; %v, output:\n%s", err, out)
+ }
+
+ ef, _ := elf.Open(exe)
+ mf, _ := macho.Open(exe)
+ pf, _ := pe.Open(exe)
+ xf, _ := xcoff.Open(exe)
+ // TODO: plan9
+ if ef == nil && mf == nil && pf == nil && xf == nil {
+ t.Skip("unrecognized executable file format")
+ }
+
+ const moddataSymName = "runtime.firstmoduledata"
+ switch {
+ case ef != nil:
+ defer ef.Close()
+
+ syms, err := ef.Symbols()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, sym := range syms {
+ if sym.Name == moddataSymName {
+ sec := ef.Sections[sym.Section]
+ if sec.Name != ".go.module" {
+ t.Errorf("moduledata in section %s, not .go.module", sec.Name)
+ }
+ if sym.Value != sec.Addr {
+ t.Errorf("moduledata address %#x != section start address %#x", sym.Value, sec.Addr)
+ }
+ break
+ }
+ }
+
+ case mf != nil:
+ defer mf.Close()
+
+ for _, sym := range mf.Symtab.Syms {
+ if sym.Name == moddataSymName {
+ if sym.Sect == 0 {
+ t.Error("moduledata not in a section")
+ } else {
+ sec := mf.Sections[sym.Sect-1]
+ if sec.Name != "__go_module" {
+ t.Errorf("moduledata in section %s, not __go.module", sec.Name)
+ }
+ if sym.Value != sec.Addr {
+ t.Errorf("moduledata address %#x != section start address %#x", sym.Value, sec.Addr)
+ }
+ }
+ break
+ }
+ }
+
+ case pf != nil:
+ defer pf.Close()
+
+ // On Windows all the Go specific sections seem to
+ // get stuffed into a few Windows sections,
+ // so there is nothing to test here.
+
+ case xf != nil:
+ defer xf.Close()
+
+ for _, sym := range xf.Symbols {
+ if sym.Name == moddataSymName {
+ if sym.SectionNumber == 0 {
+ t.Errorf("moduledata not in a section")
+ } else {
+ sec := xf.Sections[sym.SectionNumber-1]
+ if sec.Name != ".go.module" {
+ t.Errorf("moduledata in section %s, not .go.module", sec.Name)
+ }
+ if sym.Value != sec.VirtualAddress {
+ t.Errorf("moduledata address %#x != section start address %#x", sym.Value, sec.VirtualAddress)
+ }
+ }
+ break
+ }
+ }
+ }
+}