| # Verify PPC64 does not reuse a trampoline which is too far away. |
| # This tests an edge case where the direct call relocation addend should |
| # be ignored when computing the distance from the direct call to the |
| # already placed trampoline |
| [short] skip |
| [!GOARCH:ppc64] [!GOARCH:ppc64le] skip |
| [GOOS:aix] skip |
| |
| # Note, this program does not run. Presumably, 'DWORD $0' is simpler to |
| # assembly 2^26 or so times. |
| # |
| # We build something which should be laid out as such: |
| # |
| # bar.Bar |
| # main.Func1 |
| # bar.Bar+400-tramp0 |
| # main.BigAsm |
| # main.Func2 |
| # bar.Bar+400-tramp1 |
| # |
| # bar.Bar needs to be placed far enough away to generate relocations |
| # from main package calls. and main.Func1 and main.Func2 are placed |
| # a bit more than the direct call limit apart, but not more than 0x400 |
| # bytes beyond it (to verify the reloc calc). |
| |
| go build |
| |
| -- go.mod -- |
| |
| module foo |
| |
| go 1.19 |
| |
| -- main.go -- |
| |
| package main |
| |
| import "foo/bar" |
| |
| func Func1() |
| |
| func main() { |
| Func1() |
| bar.Bar2() |
| } |
| |
| -- foo.s -- |
| |
| TEXT main·Func1(SB),0,$0-0 |
| CALL bar·Bar+0x400(SB) |
| CALL main·BigAsm(SB) |
| // A trampoline will be placed here to bar.Bar |
| |
| // This creates a gap sufficiently large to prevent trampoline reuse |
| #define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; |
| #define NOP256 NOP64 NOP64 NOP64 NOP64 |
| #define NOP2S10 NOP256 NOP256 NOP256 NOP256 |
| #define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 |
| #define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 |
| #define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 |
| #define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 |
| #define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 |
| #define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 |
| #define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 |
| #define BIGNOP NOP2S24 NOP2S24 |
| TEXT main·BigAsm(SB),0,$0-0 |
| // Fill to the direct call limit so Func2 must generate a new trampoline. |
| // As the implicit trampoline above is just barely unreachable. |
| BIGNOP |
| MOVD $main·Func2(SB), R3 |
| |
| TEXT main·Func2(SB),0,$0-0 |
| CALL bar·Bar+0x400(SB) |
| // Another trampoline should be placed here. |
| |
| -- bar/bar.s -- |
| |
| #define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; |
| #define NOP256 NOP64 NOP64 NOP64 NOP64 |
| #define NOP2S10 NOP256 NOP256 NOP256 NOP256 |
| #define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 |
| #define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 |
| #define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 |
| #define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 |
| #define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 |
| #define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 |
| #define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 |
| #define BIGNOP NOP2S24 NOP2S24 NOP2S10 |
| // A very big not very interesting function. |
| TEXT bar·Bar(SB),0,$0-0 |
| BIGNOP |
| |
| -- bar/bar.go -- |
| |
| package bar |
| |
| func Bar() |
| |
| func Bar2() { |
| } |