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