diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 1eb7112e64..08c4d4db83 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -55,13 +55,20 @@ type pclntab struct { // addGeneratedSym adds a generator symbol to pclntab, returning the new Sym. // It is the caller's responsibility to save the symbol in state. -func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f generatorFunc) loader.Sym { +func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, align int32, f generatorFunc) loader.Sym { size = Rnd(size, int64(ctxt.Arch.PtrSize)) state.size += size s := ctxt.createGeneratorSymbol(name, 0, sym.SPCLNTAB, size, f) - ctxt.loader.SetAttrReachable(s, true) - ctxt.loader.SetCarrierSym(s, state.carrier) - ctxt.loader.SetAttrNotInSymbolTable(s, true) + ldr := ctxt.loader + ldr.SetSymAlign(s, align) + ldr.SetAttrReachable(s, true) + ldr.SetCarrierSym(s, state.carrier) + ldr.SetAttrNotInSymbolTable(s, true) + + if align > ldr.SymAlign(state.carrier) { + ldr.SetSymAlign(state.carrier, align) + } + return s } @@ -277,7 +284,7 @@ func (state *pclntab) generatePCHeader(ctxt *Link) { } } - state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader) + state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, int32(ctxt.Arch.PtrSize), writeHeader) } // walkFuncs iterates over the funcs, calling a function for each unique @@ -326,7 +333,7 @@ func (state *pclntab) generateFuncnametab(ctxt *Link, funcs []loader.Sym) map[lo size += int64(len(ctxt.loader.SymName(s)) + 1) // NULL terminate }) - state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab) + state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, 1, writeFuncNameTab) return nameOffsets } @@ -442,7 +449,7 @@ func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.Compilat } } } - state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), writeCutab) + state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), 4, writeCutab) // Write filetab. writeFiletab := func(ctxt *Link, s loader.Sym) { @@ -454,7 +461,7 @@ func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.Compilat } } state.nfiles = uint32(len(fileOffsets)) - state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, writeFiletab) + state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, 1, writeFiletab) return cuOffsets } @@ -518,7 +525,7 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) { } } - state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab) + state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, 1, writePctab) } // generateFuncdata writes out the funcdata information. @@ -647,7 +654,7 @@ func (state *pclntab) generateFuncdata(ctxt *Link, funcs []loader.Sym, inlsyms m } } - state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, writeFuncData) + state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, maxAlign, writeFuncData) // Because the funcdata previously was not in pclntab, // we need to keep the visible symbol so that tools can find it. @@ -703,7 +710,7 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma writePCToFunc(ctxt, sb, funcs, startLocations) writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets) } - state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln) + state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, 4, writePcln) } // funcData returns the funcdata and offsets for the FuncInfo. @@ -967,6 +974,10 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab { ldr.SetAttrReachable(state.carrier, true) setCarrierSym(sym.SPCLNTAB, state.carrier) + // Aign pclntab to at least a pointer boundary, + // for pcHeader. This may be raised further by subsymbols. + ldr.SetSymAlign(state.carrier, int32(ctxt.Arch.PtrSize)) + state.generatePCHeader(ctxt) nameOffsets := state.generateFuncnametab(ctxt, funcs) cuOffsets := state.generateFilenameTabs(ctxt, compUnits, funcs) @@ -1076,6 +1087,7 @@ func (ctxt *Link) findfunctab(state *pclntab, container loader.Bitmap) { } state.findfunctab = ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SPCLNTAB, size, writeFindFuncTab) + ldr.SetSymAlign(state.findfunctab, 4) ldr.SetAttrReachable(state.findfunctab, true) ldr.SetAttrLocal(state.findfunctab, true) } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index f9bc7007ed..dd2d74895a 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -672,6 +672,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { addRef("runtime.rodata") addRef("runtime.erodata") addRef("runtime.epclntab") + addRef("go:func.*") // As we use relative addressing for text symbols in functab, it is // important that the offsets we computed stay unchanged by the external // linker, i.e. all symbols in Textp should not be removed. diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 77ae1236c9..5f01eb2507 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -603,14 +603,20 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) { outerSymSize["go:string.*"] = size case sym.SGOFUNC: if !ctxt.DynlinkingGo() { - outerSymSize["go:func.*"] = size + outerSymSize["go:funcdesc"] = size } case sym.SGOFUNCRELRO: - outerSymSize["go:funcrel.*"] = size + outerSymSize["go:funcdescrel"] = size case sym.SGCBITS: outerSymSize["runtime.gcbits.*"] = size case sym.SPCLNTAB: - outerSymSize["runtime.pclntab"] = size + // go:func.* size must be removed from pclntab, + // as it's a real symbol. Same for runtime.findfunctab. + fsize := ldr.SymSize(ldr.Lookup("go:func.*", 0)) + fft := ldr.Lookup("runtime.findfunctab", 0) + fsize = Rnd(fsize, int64(symalign(ldr, fft))) + tsize := ldr.SymSize(fft) + outerSymSize["runtime.pclntab"] = size - (fsize + tsize) } } diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 0c4cde0399..bc7504e5b1 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -1960,33 +1960,55 @@ func TestFuncdataPlacement(t *testing.T) { case xf != nil: defer xf.Close() + var moddataSym, gofuncSym, pclntabSym, epclntabSym *xcoff.Symbol for _, sym := range xf.Symbols { switch sym.Name { case moddataSymName: - moddataAddr = sym.Value + moddataSym = sym case gofuncSymName: - gofuncAddr = sym.Value + gofuncSym = sym + case "runtime.pclntab": + pclntabSym = sym + case "runtime.epclntab": + epclntabSym = sym } } - for _, sec := range xf.Sections { - if sec.Name == ".go.pclntab" { - data, err := sec.Data() - if err != nil { - t.Fatal(err) - } - pclntab = data - pclntabAddr = sec.VirtualAddress - pclntabEnd = sec.VirtualAddress + sec.Size - } - if moddataAddr >= sec.VirtualAddress && moddataAddr < sec.VirtualAddress+sec.Size { - data, err := sec.Data() - if err != nil { - t.Fatal(err) - } - moddataBytes = data[moddataAddr-sec.VirtualAddress:] - } + if moddataSym == nil { + t.Fatalf("could not find symbol %s", moddataSymName) } + if gofuncSym == nil { + t.Fatalf("could not find symbol %s", gofuncSymName) + } + if pclntabSym == nil { + t.Fatal("could not find symbol runtime.pclntab") + } + if epclntabSym == nil { + t.Fatal("could not find symbol runtime.epclntab") + } + + sec := xf.Sections[moddataSym.SectionNumber-1] + data, err := sec.Data() + if err != nil { + t.Fatal(err) + } + moddataBytes = data[moddataSym.Value:] + moddataAddr = uint64(sec.VirtualAddress + moddataSym.Value) + + sec = xf.Sections[gofuncSym.SectionNumber-1] + gofuncAddr = uint64(sec.VirtualAddress + gofuncSym.Value) + + if pclntabSym.SectionNumber != epclntabSym.SectionNumber { + t.Fatalf("runtime.pclntab section %d != runtime.epclntab section %d", pclntabSym.SectionNumber, epclntabSym.SectionNumber) + } + sec = xf.Sections[pclntabSym.SectionNumber-1] + data, err = sec.Data() + if err != nil { + t.Fatal(err) + } + pclntab = data[pclntabSym.Value:epclntabSym.Value] + pclntabAddr = uint64(sec.VirtualAddress + pclntabSym.Value) + pclntabEnd = uint64(sec.VirtualAddress + epclntabSym.Value) default: panic("can't happen") @@ -2183,31 +2205,16 @@ func TestModuledataPlacement(t *testing.T) { } } - 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 - } + case pf != nil, xf != nil: + if pf != nil { + defer pf.Close() } + if xf != nil { + defer xf.Close() + } + + // On Windows and AIX all the Go specific sections + // get stuffed into a few sections, + // so there is nothing to test here. } } diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go index f740a3f738..424ac72e22 100644 --- a/src/cmd/nm/nm_test.go +++ b/src/cmd/nm/nm_test.go @@ -118,11 +118,6 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) { "runtime.noptrdata": "D", } - if runtime.GOOS == "aix" && iscgo { - // pclntab is moved to .data section on AIX. - runtimeSyms["runtime.epclntab"] = "D" - } - out, err = testenv.Command(t, testenv.Executable(t), exe).CombinedOutput() if err != nil { t.Fatalf("go tool nm: %v\n%s", err, string(out))