From: Than McIntosh Date: Tue, 7 Jul 2020 16:54:46 +0000 (-0400) Subject: [dev.link] cmd/link: add PPC64 debugging option to encourage text section splits X-Git-Tag: go1.16beta1~1378^2~10 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d41b9066dad9091c55e2b6e6c48ceaee7dff1cf6;p=gostls13.git [dev.link] cmd/link: add PPC64 debugging option to encourage text section splits Add a new debugging command line option (-debugppc64textsize=N) that forces the start of a new text section after ".text" hits N bytes as opposed to the architected limit of 2^26. This is intended to enable testing of the linker code paths that handle multiple .text sections on PPC64 without resorting to building giant applications. Updates #20492. Change-Id: I74ab7fd1e412e9124de5bd0d8d248c5e73225ae3 Reviewed-on: https://go-review.googlesource.com/c/go/+/241073 Run-TryBot: Than McIntosh TryBot-Result: Gobot Gobot Reviewed-by: Jeremy Faller --- diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index b9e2408942..dc7096ea8c 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2247,37 +2247,52 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64 // Only break at outermost syms. - if ctxt.Arch.InFamily(sys.PPC64) && ldr.OuterSym(s) == 0 && ctxt.IsExternal() && va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(ldr, s, isTramp) > 0x1c00000 { - // Set the length for the previous text section - sect.Length = va - sect.Vaddr - - // Create new section, set the starting Vaddr - sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05) - sect.Vaddr = va - ldr.SetSymSect(s, sect) - - // Create a symbol for the start of the secondary text sections - ntext := ldr.CreateSymForUpdate(fmt.Sprintf("runtime.text.%d", n), 0) - ntext.SetSect(sect) - if ctxt.IsAIX() { - // runtime.text.X must be a real symbol on AIX. - // Assign its address directly in order to be the - // first symbol of this new section. - ntext.SetType(sym.STEXT) - ntext.SetSize(int64(MINFUNC)) - ntext.SetOnList(true) - ctxt.tramps = append(ctxt.tramps, ntext.Sym()) - - ntext.SetValue(int64(va)) - va += uint64(ntext.Size()) - - if align := ldr.SymAlign(s); align != 0 { - va = uint64(Rnd(int64(va), int64(align))) - } else { - va = uint64(Rnd(int64(va), int64(Funcalign))) + // For debugging purposes, allow text size limit to be cranked down, + // so as to stress test the code that handles multiple text sections. + var textSizelimit uint64 = 0x1c00000 + if *FlagDebugTextSize != 0 { + textSizelimit = uint64(*FlagDebugTextSize) + } + + if ctxt.Arch.InFamily(sys.PPC64) && ldr.OuterSym(s) == 0 && ctxt.IsExternal() { + // Sanity check: make sure the limit is larger than any + // individual text symbol. + if funcsize > textSizelimit { + panic(fmt.Sprintf("error: ppc64 text size limit %d less than text symbol %s size of %d", textSizelimit, ldr.SymName(s), funcsize)) + } + + if va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(ldr, s, isTramp) > textSizelimit { + // Set the length for the previous text section + sect.Length = va - sect.Vaddr + + // Create new section, set the starting Vaddr + sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05) + sect.Vaddr = va + ldr.SetSymSect(s, sect) + + // Create a symbol for the start of the secondary text sections + ntext := ldr.CreateSymForUpdate(fmt.Sprintf("runtime.text.%d", n), 0) + ntext.SetSect(sect) + if ctxt.IsAIX() { + // runtime.text.X must be a real symbol on AIX. + // Assign its address directly in order to be the + // first symbol of this new section. + ntext.SetType(sym.STEXT) + ntext.SetSize(int64(MINFUNC)) + ntext.SetOnList(true) + ctxt.tramps = append(ctxt.tramps, ntext.Sym()) + + ntext.SetValue(int64(va)) + va += uint64(ntext.Size()) + + if align := ldr.SymAlign(s); align != 0 { + va = uint64(Rnd(int64(va), int64(align))) + } else { + va = uint64(Rnd(int64(va), int64(Funcalign))) + } } + n++ } - n++ } ldr.SetSymValue(s, 0) diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 3702f28dd8..4885c4f57e 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -74,22 +74,23 @@ var ( flagExtldflags = flag.String("extldflags", "", "pass `flags` to external linker") flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive") - flagA = flag.Bool("a", false, "no-op (deprecated)") - FlagC = flag.Bool("c", false, "dump call graph") - FlagD = flag.Bool("d", false, "disable dynamic executable") - flagF = flag.Bool("f", false, "ignore version mismatch") - flagG = flag.Bool("g", false, "disable go package data checks") - flagH = flag.Bool("h", false, "halt on error") - flagN = flag.Bool("n", false, "dump symbol table") - FlagS = flag.Bool("s", false, "disable symbol table") - FlagW = flag.Bool("w", false, "disable DWARF generation") - flag8 bool // use 64-bit addresses in symbol table - flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker") - FlagDebugTramp = flag.Int("debugtramp", 0, "debug trampolines") - FlagStrictDups = flag.Int("strictdups", 0, "sanity check duplicate symbol contents during object file reading (1=warn 2=err).") - FlagRound = flag.Int("R", -1, "set address rounding `quantum`") - FlagTextAddr = flag.Int64("T", -1, "set text segment `address`") - flagEntrySymbol = flag.String("E", "", "set `entry` symbol name") + flagA = flag.Bool("a", false, "no-op (deprecated)") + FlagC = flag.Bool("c", false, "dump call graph") + FlagD = flag.Bool("d", false, "disable dynamic executable") + flagF = flag.Bool("f", false, "ignore version mismatch") + flagG = flag.Bool("g", false, "disable go package data checks") + flagH = flag.Bool("h", false, "halt on error") + flagN = flag.Bool("n", false, "dump symbol table") + FlagS = flag.Bool("s", false, "disable symbol table") + FlagW = flag.Bool("w", false, "disable DWARF generation") + flag8 bool // use 64-bit addresses in symbol table + flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker") + FlagDebugTramp = flag.Int("debugtramp", 0, "debug trampolines") + FlagDebugTextSize = flag.Int("debugppc64textsize", 0, "debug PPC64 text section max") + FlagStrictDups = flag.Int("strictdups", 0, "sanity check duplicate symbol contents during object file reading (1=warn 2=err).") + FlagRound = flag.Int("R", -1, "set address rounding `quantum`") + FlagTextAddr = flag.Int64("T", -1, "set text segment `address`") + flagEntrySymbol = flag.String("E", "", "set `entry` symbol name") cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`") memprofile = flag.String("memprofile", "", "write memory profile to `file`")