aboutsummaryrefslogtreecommitdiff
path: root/test/ELF/arm-exidx-order.s
blob: 951c71a4c33e13c7d0115ffd76d6e56019625b33 (plain) (blame)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind
// RUN: ld.lld %t %tcantunwind -o %t2 2>&1
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
// Use Linker script to place .ARM.exidx in between .text and orphan sections
// RUN: echo "SECTIONS { \
// RUN:          .text 0x11000 : { *(.text*) } \
// RUN:          .ARM.exidx : { *(.ARM.exidx) } } " > %t.script
// RUN: ld.lld --script %t.script %tcantunwind %t -o %t3 2>&1
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT %s
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT-EXIDX %s
// REQUIRES: arm

// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set
// with the sh_link containing the section index of the executable section
// containing the function it describes. The linker must combine the .ARM.exidx
// InputSections in the same order that it has combined the executable section,
// such that the combined .ARM.exidx OutputSection can be used as a binary
// search table.

 .syntax unified
 .section .text, "ax",%progbits
 .globl _start
_start:
 .fnstart
 bx lr
 .cantunwind
 .fnend

 .section .text.f1, "ax", %progbits
 .globl f1
f1:
 .fnstart
 bx lr
 .cantunwind
 .fnend

 .section .text.f2, "ax", %progbits
 .globl f2
f2:
 .fnstart
 bx lr
 .cantunwind
 .fnend
 .globl f3
f3:
 .fnstart
 bx lr
 .cantunwind
 .fnend

// Check default no linker script order.

// CHECK: Disassembly of section .text:
// CHECK: _start:
// CHECK-NEXT:    11000:       1e ff 2f e1     bx      lr
// CHECK: f1:
// CHECK-NEXT:    11004:       1e ff 2f e1     bx      lr
// CHECK: f2:
// CHECK-NEXT:    11008:       1e ff 2f e1     bx      lr
// CHECK: f3:
// CHECK-NEXT:    1100c:       1e ff 2f e1     bx      lr
// CHECK: func4:
// CHECK-NEXT:    11010:       1e ff 2f e1     bx      lr
// CHECK: func5:
// CHECK-NEXT:    11014:       1e ff 2f e1     bx      lr
// CHECK: Disassembly of section .func1:
// CHECK-NEXT: func1:
// CHECK-NEXT:    11018:       1e ff 2f e1     bx      lr
// CHECK: Disassembly of section .func2:
// CHECK-NEXT: func2:
// CHECK-NEXT:    1101c:       1e ff 2f e1     bx      lr
// CHECK: Disassembly of section .func3:
// CHECK-NEXT: func3:
// CHECK-NEXT:    11020:       1e ff 2f e1     bx      lr

// Each .ARM.exidx section has two 4 byte fields
// Field 1 is the 31-bit offset to the function. The top bit is used to
// indicate whether Field 2 is a pointer or an inline table entry.
// Field 2 is either a pointer to a .ARM.extab section or an inline table
// In this example all Field 2 entries are inline can't unwind (0x1)
// We expect to see the entries in the same order as the functions

// CHECK-EXIDX: Contents of section .ARM.exidx:
// 100d4 + f2c = 11000 = _start
// 100dc + f28 = 11004 = f1
// CHECK-EXIDX-NEXT:       100d4 2c0f0000 01000000 280f0000 01000000
// 100e4 + f24 = 11008 = f2
// 100ec + f20 = 1100c = f3
// CHECK-EXIDX-NEXT:  100e4 240f0000 01000000 200f0000 01000000
// 100f4 + f1c = 11010 = func4
// 100fc + f18 = 11014 = func5
// CHECK-EXIDX-NEXT:  100f4 1c0f0000 01000000 180f0000 01000000
// 10104 + f14 = 11018 = func1
// 1010c + f10 = 1101c = func2
// CHECK-EXIDX-NEXT:  10104 140f0000 01000000 100f0000 01000000
// 10114 + f0c = 11020 = func3
// CHECK-EXIDX-NEXT:  10114 0c0f0000 01000000

// Check that PT_ARM_EXIDX program header has been generated that describes
// the .ARM.exidx output section
// CHECK-PT:          Name: .ARM.exidx
// CHECK-PT-NEXT:     Type: SHT_ARM_EXIDX (0x70000001)
// CHECK-PT-NEXT:     Flags [
// CHECK-PT-NEXT:       SHF_ALLOC
// CHECK-PT-NEXT:       SHF_LINK_ORDER
// CHECK-PT-NEXT:     ]
// CHECK-PT-NEXT:     Address: 0x100D4
// CHECK-PT-NEXT:     Offset: 0xD4
// CHECK-PT-NEXT:     Size: 80

// CHECK-PT:          Type: PT_ARM_EXIDX (0x70000001)
// CHECK-PT-NEXT:     Offset: 0xD4
// CHECK-PT-NEXT:     VirtualAddress: 0x100D4
// CHECK-PT-NEXT:     PhysicalAddress: 0x100D4
// CHECK-PT-NEXT:     FileSize: 80
// CHECK-PT-NEXT:     MemSize: 80
// CHECK-PT-NEXT:     Flags [ (0x4)
// CHECK-PT-NEXT:       PF_R (0x4)
// CHECK-PT-NEXT:     ]
// CHECK-PT-NEXT:     Alignment: 4
// CHECK-PT-NEXT:   }


// Check linker script order. The .ARM.exidx section will be inserted after
// the .text section but before the orphan sections

// CHECK-SCRIPT: Disassembly of section .text:
// CHECK-SCRIPT-NEXT: func4:
// CHECK-SCRIPT-NEXT:    11000:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT:      func5:
// CHECK-SCRIPT-NEXT:    11004:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT:      _start:
// CHECK-SCRIPT-NEXT:    11008:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT:      f1:
// CHECK-SCRIPT-NEXT:    1100c:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT:      f2:
// CHECK-SCRIPT-NEXT:    11010:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT:      f3:
// CHECK-SCRIPT-NEXT:    11014:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT-NEXT: Disassembly of section .func1:
// CHECK-SCRIPT-NEXT: func1:
// CHECK-SCRIPT-NEXT:    11068:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT-NEXT: Disassembly of section .func2:
// CHECK-SCRIPT-NEXT: func2:
// CHECK-SCRIPT-NEXT:    1106c:       1e ff 2f e1     bx      lr
// CHECK-SCRIPT-NEXT: Disassembly of section .func3:
// CHECK-SCRIPT-NEXT: func3:
// CHECK-SCRIPT-NEXT:    11070:       1e ff 2f e1     bx      lr

// Check that the .ARM.exidx section is sorted in order as the functions
// The offset in field 1, is 32-bit so in the binary the most significant bit
// 11018 - 18 = 11000 func4
// 11020 - 1c = 11004 func5
// CHECK-SCRIPT-EXIDX:       11018 e8ffff7f 01000000 e4ffff7f 01000000
// 11028 - 20 = 11008 _start
// 11030 - 24 = 1100c f1
// CHECK-SCRIPT-EXIDX-NEXT:  11028 e0ffff7f 01000000 dcffff7f 01000000
// 11038 - 28 = 11010 f2
// 11040 - 2c = 11014 f3
// CHECK-SCRIPT-EXIDX-NEXT:  11038 d8ffff7f 01000000 d4ffff7f 01000000
// 11048 + 20 = 11068 func1
// 11050 + 1c = 1106c func2
// CHECK-SCRIPT-EXIDX-NEXT:  11048 20000000 01000000 1c000000 01000000
// 11058 + 18 = 11070 func3
// 11060 + 14 = 11074 func3 + sizeof(func3)
// CHECK-SCRIPT-EXIDX-NEXT:  11058 18000000 01000000 14000000 01000000