diff options
| author | Ian Lance Taylor <iant@golang.org> | 2025-11-17 20:20:26 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-11-26 20:29:52 -0800 |
| commit | f1bbc66a10a545811a21dcf9f9431e783aafcb42 (patch) | |
| tree | b03b6c0098812b097f75c1fd21f1c9fc1ddb9e19 /src/cmd | |
| parent | 003f52407a8a32575084ffc4b15486aa8757ec74 (diff) | |
| download | go-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.go | 97 |
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 + } + } + } +} |
