aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/testdata/script/trampoline_reuse_test.txt
blob: bca897c16d0544ab6d8d369c732ca5dc10c569c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 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
[!ppc64] [!ppc64le] skip
[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() {
}