github.com/bir3/gocompiler@v0.9.2202/src/cmd/cgo/internal/test/stubtest_linux_ppc64le.S (about) 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 50 notoc_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 58 toc_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 82 notoc_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 117 notoc_func: 118 // Return 1 to indicate the test was skipped. 119 li 3,1 120 blr 121 122 .endif