Skip to content

Commit 276cc4d

Browse files
ianlancetaylorgopherbot
authored andcommitted
cmd/link: fix AIX builds after recent linker changes
This updates XCOFF-specific code for the recent addition of funcdata to pclntab. Because XCOFF puts separate symbols into separate csects, each with their own alignment, it's important to tell the external linker the expected alignment of each part of pclntab. Otherwise the offsets within pclntab may change as the external linker aligns symbols. This CL sets the correct alignment for each pclntab child symbol, and sets pclntab's alignment to the max of that of its children. Tested on the GCC compile farm. Fixes #76486 Change-Id: I77d8a90c4b4b79d80ca11ede8d9a2aa9cc89f53f Reviewed-on: https://go-review.googlesource.com/c/go/+/725603 Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Mui <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent f2d9627 commit 276cc4d

File tree

5 files changed

+83
-62
lines changed

5 files changed

+83
-62
lines changed

src/cmd/link/internal/ld/pcln.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,20 @@ type pclntab struct {
5555

5656
// addGeneratedSym adds a generator symbol to pclntab, returning the new Sym.
5757
// It is the caller's responsibility to save the symbol in state.
58-
func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f generatorFunc) loader.Sym {
58+
func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, align int32, f generatorFunc) loader.Sym {
5959
size = Rnd(size, int64(ctxt.Arch.PtrSize))
6060
state.size += size
6161
s := ctxt.createGeneratorSymbol(name, 0, sym.SPCLNTAB, size, f)
62-
ctxt.loader.SetAttrReachable(s, true)
63-
ctxt.loader.SetCarrierSym(s, state.carrier)
64-
ctxt.loader.SetAttrNotInSymbolTable(s, true)
62+
ldr := ctxt.loader
63+
ldr.SetSymAlign(s, align)
64+
ldr.SetAttrReachable(s, true)
65+
ldr.SetCarrierSym(s, state.carrier)
66+
ldr.SetAttrNotInSymbolTable(s, true)
67+
68+
if align > ldr.SymAlign(state.carrier) {
69+
ldr.SetSymAlign(state.carrier, align)
70+
}
71+
6572
return s
6673
}
6774

@@ -277,7 +284,7 @@ func (state *pclntab) generatePCHeader(ctxt *Link) {
277284
}
278285
}
279286

280-
state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader)
287+
state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, int32(ctxt.Arch.PtrSize), writeHeader)
281288
}
282289

283290
// 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
326333
size += int64(len(ctxt.loader.SymName(s)) + 1) // NULL terminate
327334
})
328335

329-
state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab)
336+
state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, 1, writeFuncNameTab)
330337
return nameOffsets
331338
}
332339

@@ -442,7 +449,7 @@ func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.Compilat
442449
}
443450
}
444451
}
445-
state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), writeCutab)
452+
state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), 4, writeCutab)
446453

447454
// Write filetab.
448455
writeFiletab := func(ctxt *Link, s loader.Sym) {
@@ -454,7 +461,7 @@ func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.Compilat
454461
}
455462
}
456463
state.nfiles = uint32(len(fileOffsets))
457-
state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, writeFiletab)
464+
state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, 1, writeFiletab)
458465

459466
return cuOffsets
460467
}
@@ -518,7 +525,7 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) {
518525
}
519526
}
520527

521-
state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab)
528+
state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, 1, writePctab)
522529
}
523530

524531
// generateFuncdata writes out the funcdata information.
@@ -647,7 +654,7 @@ func (state *pclntab) generateFuncdata(ctxt *Link, funcs []loader.Sym, inlsyms m
647654
}
648655
}
649656

650-
state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, writeFuncData)
657+
state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, maxAlign, writeFuncData)
651658

652659
// Because the funcdata previously was not in pclntab,
653660
// 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
703710
writePCToFunc(ctxt, sb, funcs, startLocations)
704711
writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets)
705712
}
706-
state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln)
713+
state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, 4, writePcln)
707714
}
708715

709716
// funcData returns the funcdata and offsets for the FuncInfo.
@@ -967,6 +974,10 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
967974
ldr.SetAttrReachable(state.carrier, true)
968975
setCarrierSym(sym.SPCLNTAB, state.carrier)
969976

977+
// Aign pclntab to at least a pointer boundary,
978+
// for pcHeader. This may be raised further by subsymbols.
979+
ldr.SetSymAlign(state.carrier, int32(ctxt.Arch.PtrSize))
980+
970981
state.generatePCHeader(ctxt)
971982
nameOffsets := state.generateFuncnametab(ctxt, funcs)
972983
cuOffsets := state.generateFilenameTabs(ctxt, compUnits, funcs)
@@ -1076,6 +1087,7 @@ func (ctxt *Link) findfunctab(state *pclntab, container loader.Bitmap) {
10761087
}
10771088

10781089
state.findfunctab = ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SPCLNTAB, size, writeFindFuncTab)
1090+
ldr.SetSymAlign(state.findfunctab, 4)
10791091
ldr.SetAttrReachable(state.findfunctab, true)
10801092
ldr.SetAttrLocal(state.findfunctab, true)
10811093
}

src/cmd/link/internal/ld/symtab.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
672672
addRef("runtime.rodata")
673673
addRef("runtime.erodata")
674674
addRef("runtime.epclntab")
675+
addRef("go:func.*")
675676
// As we use relative addressing for text symbols in functab, it is
676677
// important that the offsets we computed stay unchanged by the external
677678
// linker, i.e. all symbols in Textp should not be removed.

src/cmd/link/internal/ld/xcoff.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -603,14 +603,20 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
603603
outerSymSize["go:string.*"] = size
604604
case sym.SGOFUNC:
605605
if !ctxt.DynlinkingGo() {
606-
outerSymSize["go:func.*"] = size
606+
outerSymSize["go:funcdesc"] = size
607607
}
608608
case sym.SGOFUNCRELRO:
609-
outerSymSize["go:funcrel.*"] = size
609+
outerSymSize["go:funcdescrel"] = size
610610
case sym.SGCBITS:
611611
outerSymSize["runtime.gcbits.*"] = size
612612
case sym.SPCLNTAB:
613-
outerSymSize["runtime.pclntab"] = size
613+
// go:func.* size must be removed from pclntab,
614+
// as it's a real symbol. Same for runtime.findfunctab.
615+
fsize := ldr.SymSize(ldr.Lookup("go:func.*", 0))
616+
fft := ldr.Lookup("runtime.findfunctab", 0)
617+
fsize = Rnd(fsize, int64(symalign(ldr, fft)))
618+
tsize := ldr.SymSize(fft)
619+
outerSymSize["runtime.pclntab"] = size - (fsize + tsize)
614620
}
615621
}
616622

src/cmd/link/link_test.go

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,34 +1960,56 @@ func TestFuncdataPlacement(t *testing.T) {
19601960
case xf != nil:
19611961
defer xf.Close()
19621962

1963+
var moddataSym, gofuncSym, pclntabSym, epclntabSym *xcoff.Symbol
19631964
for _, sym := range xf.Symbols {
19641965
switch sym.Name {
19651966
case moddataSymName:
1966-
moddataAddr = sym.Value
1967+
moddataSym = sym
19671968
case gofuncSymName:
1968-
gofuncAddr = sym.Value
1969+
gofuncSym = sym
1970+
case "runtime.pclntab":
1971+
pclntabSym = sym
1972+
case "runtime.epclntab":
1973+
epclntabSym = sym
19691974
}
19701975
}
19711976

1972-
for _, sec := range xf.Sections {
1973-
if sec.Name == ".go.pclntab" {
1974-
data, err := sec.Data()
1975-
if err != nil {
1976-
t.Fatal(err)
1977-
}
1978-
pclntab = data
1979-
pclntabAddr = sec.VirtualAddress
1980-
pclntabEnd = sec.VirtualAddress + sec.Size
1981-
}
1982-
if moddataAddr >= sec.VirtualAddress && moddataAddr < sec.VirtualAddress+sec.Size {
1983-
data, err := sec.Data()
1984-
if err != nil {
1985-
t.Fatal(err)
1986-
}
1987-
moddataBytes = data[moddataAddr-sec.VirtualAddress:]
1988-
}
1977+
if moddataSym == nil {
1978+
t.Fatalf("could not find symbol %s", moddataSymName)
1979+
}
1980+
if gofuncSym == nil {
1981+
t.Fatalf("could not find symbol %s", gofuncSymName)
1982+
}
1983+
if pclntabSym == nil {
1984+
t.Fatal("could not find symbol runtime.pclntab")
1985+
}
1986+
if epclntabSym == nil {
1987+
t.Fatal("could not find symbol runtime.epclntab")
19891988
}
19901989

1990+
sec := xf.Sections[moddataSym.SectionNumber-1]
1991+
data, err := sec.Data()
1992+
if err != nil {
1993+
t.Fatal(err)
1994+
}
1995+
moddataBytes = data[moddataSym.Value:]
1996+
moddataAddr = uint64(sec.VirtualAddress + moddataSym.Value)
1997+
1998+
sec = xf.Sections[gofuncSym.SectionNumber-1]
1999+
gofuncAddr = uint64(sec.VirtualAddress + gofuncSym.Value)
2000+
2001+
if pclntabSym.SectionNumber != epclntabSym.SectionNumber {
2002+
t.Fatalf("runtime.pclntab section %d != runtime.epclntab section %d", pclntabSym.SectionNumber, epclntabSym.SectionNumber)
2003+
}
2004+
sec = xf.Sections[pclntabSym.SectionNumber-1]
2005+
data, err = sec.Data()
2006+
if err != nil {
2007+
t.Fatal(err)
2008+
}
2009+
pclntab = data[pclntabSym.Value:epclntabSym.Value]
2010+
pclntabAddr = uint64(sec.VirtualAddress + pclntabSym.Value)
2011+
pclntabEnd = uint64(sec.VirtualAddress + epclntabSym.Value)
2012+
19912013
default:
19922014
panic("can't happen")
19932015
}
@@ -2183,31 +2205,16 @@ func TestModuledataPlacement(t *testing.T) {
21832205
}
21842206
}
21852207

2186-
case pf != nil:
2187-
defer pf.Close()
2208+
case pf != nil, xf != nil:
2209+
if pf != nil {
2210+
defer pf.Close()
2211+
}
2212+
if xf != nil {
2213+
defer xf.Close()
2214+
}
21882215

2189-
// On Windows all the Go specific sections seem to
2190-
// get stuffed into a few Windows sections,
2216+
// On Windows and AIX all the Go specific sections
2217+
// get stuffed into a few sections,
21912218
// 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-
}
22122219
}
22132220
}

src/cmd/nm/nm_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,6 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
118118
"runtime.noptrdata": "D",
119119
}
120120

121-
if runtime.GOOS == "aix" && iscgo {
122-
// pclntab is moved to .data section on AIX.
123-
runtimeSyms["runtime.epclntab"] = "D"
124-
}
125-
126121
out, err = testenv.Command(t, testenv.Executable(t), exe).CombinedOutput()
127122
if err != nil {
128123
t.Fatalf("go tool nm: %v\n%s", err, string(out))

0 commit comments

Comments
 (0)