@@ -2114,3 +2114,100 @@ func TestFuncdataPlacement(t *testing.T) {
21142114 t .Errorf ("findfunctab address %#x not between %#x and %#x" , moddata .findfunctab , pclntabAddr , pclntabEnd )
21152115 }
21162116}
2117+
2118+ // Test that moduledata winds up in its own .go.module section.
2119+ func TestModuledataPlacement (t * testing.T ) {
2120+ testenv .MustHaveGoBuild (t )
2121+ t .Parallel ()
2122+
2123+ tmpdir := t .TempDir ()
2124+ src := filepath .Join (tmpdir , "x.go" )
2125+ if err := os .WriteFile (src , []byte (trivialSrc ), 0o444 ); err != nil {
2126+ t .Fatal (err )
2127+ }
2128+
2129+ exe := filepath .Join (tmpdir , "x.exe" )
2130+ cmd := goCmd (t , "build" , "-o" , exe , src )
2131+ if out , err := cmd .CombinedOutput (); err != nil {
2132+ t .Fatalf ("build failed; %v, output:\n %s" , err , out )
2133+ }
2134+
2135+ ef , _ := elf .Open (exe )
2136+ mf , _ := macho .Open (exe )
2137+ pf , _ := pe .Open (exe )
2138+ xf , _ := xcoff .Open (exe )
2139+ // TODO: plan9
2140+ if ef == nil && mf == nil && pf == nil && xf == nil {
2141+ t .Skip ("unrecognized executable file format" )
2142+ }
2143+
2144+ const moddataSymName = "runtime.firstmoduledata"
2145+ switch {
2146+ case ef != nil :
2147+ defer ef .Close ()
2148+
2149+ syms , err := ef .Symbols ()
2150+ if err != nil {
2151+ t .Fatal (err )
2152+ }
2153+ for _ , sym := range syms {
2154+ if sym .Name == moddataSymName {
2155+ sec := ef .Sections [sym .Section ]
2156+ if sec .Name != ".go.module" {
2157+ t .Errorf ("moduledata in section %s, not .go.module" , sec .Name )
2158+ }
2159+ if sym .Value != sec .Addr {
2160+ t .Errorf ("moduledata address %#x != section start address %#x" , sym .Value , sec .Addr )
2161+ }
2162+ break
2163+ }
2164+ }
2165+
2166+ case mf != nil :
2167+ defer mf .Close ()
2168+
2169+ for _ , sym := range mf .Symtab .Syms {
2170+ if sym .Name == moddataSymName {
2171+ if sym .Sect == 0 {
2172+ t .Error ("moduledata not in a section" )
2173+ } else {
2174+ sec := mf .Sections [sym .Sect - 1 ]
2175+ if sec .Name != "__go_module" {
2176+ t .Errorf ("moduledata in section %s, not __go.module" , sec .Name )
2177+ }
2178+ if sym .Value != sec .Addr {
2179+ t .Errorf ("moduledata address %#x != section start address %#x" , sym .Value , sec .Addr )
2180+ }
2181+ }
2182+ break
2183+ }
2184+ }
2185+
2186+ case pf != nil :
2187+ defer pf .Close ()
2188+
2189+ // On Windows all the Go specific sections seem to
2190+ // get stuffed into a few Windows sections,
2191+ // so there is nothing to test here.
2192+
2193+ case xf != nil :
2194+ defer xf .Close ()
2195+
2196+ for _ , sym := range xf .Symbols {
2197+ if sym .Name == moddataSymName {
2198+ if sym .SectionNumber == 0 {
2199+ t .Errorf ("moduledata not in a section" )
2200+ } else {
2201+ sec := xf .Sections [sym .SectionNumber - 1 ]
2202+ if sec .Name != ".go.module" {
2203+ t .Errorf ("moduledata in section %s, not .go.module" , sec .Name )
2204+ }
2205+ if sym .Value != sec .VirtualAddress {
2206+ t .Errorf ("moduledata address %#x != section start address %#x" , sym .Value , sec .VirtualAddress )
2207+ }
2208+ }
2209+ break
2210+ }
2211+ }
2212+ }
2213+ }
0 commit comments