...
1// Copyright 2023 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build (ppc64 || ppc64le) && linux && cgo
6
7// When linking C ELFv2 objects, the Go linker may need to insert calling stubs.
8// A call stub is usually needed when the ELFv2 st_other attribute is different
9// between caller and callee.
10//
11// The type of call stub inserted will vary depending on GOPPC64 and the
12// buildmode (e.g pie builds shared code, default builds fixed-position code).
13// CI is set up to run for P8 and P10 machines, and this test is run in both
14// pie and default modes.
15//
16// Several functions are written with interesting st_other attributes, and
17// call each other to test various calling combinations which require stubs.
18//
19// The call tree is as follows, starting from TestPPC64Stubs (A C function):
20// TestPPC64Stubs (compiled PIC by default by Go)
21// notoc_func [called TOC -> NOTOC (but R2 is preserved)]
22// toc_func [called NOTOC -> TOC]
23// notoc_nor2_func [called TOC -> NOTOC]
24// random [dynamic TOC call]
25// random [dynamic NOTOC call]
26//
27// Depending on the GOPPC64/buildmode used, and type of call, one of 7 stubs may need inserted:
28//
29// TOC -> NOTOC: Save R2, call global entry. (valid for any GOPPC64)
30// TOC save slot is rewrittent to restore TOC.
31// NOTOC -> TOC [P10]: A PIC call stub using P10 instructions to call the global entry
32// NOTOC -> TOC [P8]: A PIC call stub using P8 instructions to call the global entry
33//
34// TOC -> dynamic: A PLT call stub is generated which saves R2.
35// TOC save slot is rewritten to restore TOC.
36// NOTOC -> dynamic [P10]: A stub using pcrel instructions is generated.
37// NOTOC -> dynamic [P8/default]: A P8 compatible, non-PIC stub is generated
38// NOTOC -> dynamic [P8/pie]: A P8 compatible, PIC stub is generated
39//
40//
41// Some notes about other cases:
42// TOC -> TOC, NOTOC -> NOTOC, NOTOC -> TOC local calls do not require require call stubs.
43// TOC -> NOTOC (R2 is preserved, st_other==0): A special case where a call stub is not needed.
44
45// This test requires a binutils with power10 and ELFv2 1.5 support. This is earliest verified version.
46.if .gasversion. >= 23500
47
48// A function which does not guarantee R2 is preserved.
49// R2 is clobbered here to ensure the stubs preserve it.
50 .globl notoc_nor2_func
51 .type notoc_nor2_func, @function
52notoc_nor2_func:
53 .localentry notoc_nor2_func,1
54 li 2,0
55 blr
56
57// A function which expects R2 to hold TOC, and has a distinct local entry.
58 .globl toc_func
59 .type toc_func, @function
60toc_func:
61 addis 2,12,.TOC.-toc_func@ha
62 addi 2,2,.TOC.-toc_func@l
63 .localentry toc_func, .-toc_func
64 mflr 0
65 std 0,16(1)
66 stdu 1,-32(1)
67
68 // Call a NOTOC function which clobbers R2.
69 bl notoc_nor2_func
70 nop
71
72 // Call libc random. This should generate a TOC relative plt stub.
73 bl random
74 nop
75
76 addi 1,1,32
77 ld 0,16(1)
78 mtlr 0
79 blr
80
81// An ELFv2 st_other==0 function. It preserves R2 (TOC), but does not use it.
82 .globl notoc_func
83 .type notoc_func, @function
84notoc_func:
85 // Save R2 and LR and stack a frame.
86 mflr 0
87 std 0,16(1)
88 stdu 1,-32(1)
89
90 // Save R2 in TOC save slot.
91 std 2,24(1)
92
93 // clobber R2
94 li 2,0
95
96 // Call type2_func. A call stub from notoc to toc should be inserted.
97 bl toc_func@notoc
98
99 // Call libc random. A notoc plt stub should be inserted.
100 bl random@notoc
101
102 // Return 0 to indicate the test ran.
103 li 3,0
104
105 // Restore R2
106 ld 2,24(1)
107
108 // Restore LR and pop stack
109 addi 1,1,32
110 ld 0,16(1)
111 mtlr 0
112 blr
113
114.else
115
116// A stub for older binutils
117 .globl notoc_func
118 .type notoc_func, @function
119notoc_func:
120 // Return 1 to indicate the test was skipped.
121 li 3,1
122 blr
123
124.endif
View as plain text