@@ -67,7 +67,7 @@ func isRuntimeDepPkg(pkg string) bool {
6767// Estimate the max size needed to hold any new trampolines created for this function. This
6868// is used to determine when the section can be split if it becomes too large, to ensure that
6969// the trampolines are in the same section as the function that uses them.
70- func maxSizeTrampolinesPPC64 ( ldr * loader.Loader , s loader.Sym , isTramp bool ) uint64 {
70+ func maxSizeTrampolines ( ctxt * Link , ldr * loader.Loader , s loader.Sym , isTramp bool ) uint64 {
7171 // If thearch.Trampoline is nil, then trampoline support is not available on this arch.
7272 // A trampoline does not need any dependent trampolines.
7373 if thearch .Trampoline == nil || isTramp {
@@ -82,8 +82,14 @@ func maxSizeTrampolinesPPC64(ldr *loader.Loader, s loader.Sym, isTramp bool) uin
8282 n ++
8383 }
8484 }
85- // Trampolines in ppc64 are 4 instructions.
86- return n * 16
85+
86+ if ctxt .IsPPC64 () {
87+ return n * 16 // Trampolines in PPC64 are 4 instructions.
88+ }
89+ if ctxt .IsARM64 () {
90+ return n * 12 // Trampolines in ARM64 are 3 instructions.
91+ }
92+ panic ("unreachable" )
8793}
8894
8995// detect too-far jumps in function s, and add trampolines if necessary
@@ -2348,15 +2354,11 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
23482354 funcsize = uint64 (ldr .SymSize (s ))
23492355 }
23502356
2351- // On ppc64x a text section should not be larger than 2^26 bytes due to the size of
2352- // call target offset field in the bl instruction. Splitting into smaller text
2353- // sections smaller than this limit allows the GNU linker to modify the long calls
2354- // appropriately. The limit allows for the space needed for tables inserted by the linker.
2355- //
2356- // If this function doesn't fit in the current text section, then create a new one.
2357+ // If we need to split text sections, and this function doesn't fit in the current
2358+ // section, then create a new one.
23572359 //
23582360 // Only break at outermost syms.
2359- if ctxt . Arch . InFamily ( sys . PPC64 ) && ldr .OuterSym (s ) == 0 && ctxt . IsExternal () && big {
2361+ if big && splitTextSections ( ctxt ) && ldr .OuterSym (s ) == 0 {
23602362 // For debugging purposes, allow text size limit to be cranked down,
23612363 // so as to stress test the code that handles multiple text sections.
23622364 var textSizelimit uint64 = thearch .TrampLimit
@@ -2367,18 +2369,22 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
23672369 // Sanity check: make sure the limit is larger than any
23682370 // individual text symbol.
23692371 if funcsize > textSizelimit {
2370- panic (fmt .Sprintf ("error: ppc64 text size limit %d less than text symbol %s size of %d" , textSizelimit , ldr .SymName (s ), funcsize ))
2372+ panic (fmt .Sprintf ("error: text size limit %d less than text symbol %s size of %d" , textSizelimit , ldr .SymName (s ), funcsize ))
23712373 }
23722374
2373- if va - sect .Vaddr + funcsize + maxSizeTrampolinesPPC64 (ldr , s , isTramp ) > textSizelimit {
2374- // Align the next text section to the worst case function alignment likely
2375- // to be encountered when processing function symbols. The start address
2376- // is rounded against the final alignment of the text section later on in
2377- // (*Link).address. This may happen due to usage of PCALIGN directives
2378- // larger than Funcalign, or usage of ISA 3.1 prefixed instructions
2379- // (see ISA 3.1 Book I 1.9).
2380- const ppc64maxFuncalign = 64
2381- va = uint64 (Rnd (int64 (va ), ppc64maxFuncalign ))
2375+ if va - sect .Vaddr + funcsize + maxSizeTrampolines (ctxt , ldr , s , isTramp ) > textSizelimit {
2376+ sectAlign := int32 (thearch .Funcalign )
2377+ if ctxt .IsPPC64 () {
2378+ // Align the next text section to the worst case function alignment likely
2379+ // to be encountered when processing function symbols. The start address
2380+ // is rounded against the final alignment of the text section later on in
2381+ // (*Link).address. This may happen due to usage of PCALIGN directives
2382+ // larger than Funcalign, or usage of ISA 3.1 prefixed instructions
2383+ // (see ISA 3.1 Book I 1.9).
2384+ const ppc64maxFuncalign = 64
2385+ sectAlign = ppc64maxFuncalign
2386+ va = uint64 (Rnd (int64 (va ), ppc64maxFuncalign ))
2387+ }
23822388
23832389 // Set the length for the previous text section
23842390 sect .Length = va - sect .Vaddr
@@ -2387,7 +2393,7 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
23872393 sect = addsection (ctxt .loader , ctxt .Arch , & Segtext , ".text" , 05 )
23882394
23892395 sect .Vaddr = va
2390- sect .Align = ppc64maxFuncalign
2396+ sect .Align = sectAlign
23912397 ldr .SetSymSect (s , sect )
23922398
23932399 // Create a symbol for the start of the secondary text sections
@@ -2400,7 +2406,7 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
24002406 ntext .SetType (sym .STEXT )
24012407 ntext .SetSize (int64 (MINFUNC ))
24022408 ntext .SetOnList (true )
2403- ntext .SetAlign (ppc64maxFuncalign )
2409+ ntext .SetAlign (sectAlign )
24042410 ctxt .tramps = append (ctxt .tramps , ntext .Sym ())
24052411
24062412 ntext .SetValue (int64 (va ))
@@ -2429,6 +2435,19 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
24292435 return sect , n , va
24302436}
24312437
2438+ // Return whether we may need to split text sections.
2439+ //
2440+ // On PPC64x whem external linking a text section should not be larger than 2^25 bytes
2441+ // due to the size of call target offset field in the bl instruction. Splitting into
2442+ // smaller text sections smaller than this limit allows the system linker to modify the long
2443+ // calls appropriately. The limit allows for the space needed for tables inserted by the
2444+ // linker.
2445+ //
2446+ // The same applies to Darwin/ARM64, with 2^27 byte threshold.
2447+ func splitTextSections (ctxt * Link ) bool {
2448+ return (ctxt .IsPPC64 () || (ctxt .IsARM64 () && ctxt .IsDarwin ())) && ctxt .IsExternal ()
2449+ }
2450+
24322451// address assigns virtual addresses to all segments and sections and
24332452// returns all segments in file order.
24342453func (ctxt * Link ) address () []* sym.Segment {
0 commit comments