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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
|
// This test checks that the SEH directives emit the correct unwind data.
// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=obj %s | llvm-readobj -S -r -u - | FileCheck %s
// Check that the output assembler directives also can be parsed, and
// that they produce equivalent output:
// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=asm %s | llvm-mc -triple thumbv7-pc-win32 -filetype=obj - | llvm-readobj -S -r -u - | FileCheck %s
// CHECK: Sections [
// CHECK: Section {
// CHECK: Name: .text
// CHECK: RelocationCount: 1
// CHECK: Characteristics [
// CHECK-NEXT: ALIGN_4BYTES
// CHECK-NEXT: CNT_CODE
// CHECK-NEXT: MEM_16BIT
// CHECK-NEXT: MEM_EXECUTE
// CHECK-NEXT: MEM_PURGEABLE
// CHECK-NEXT: MEM_READ
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK: Section {
// CHECK: Name: .xdata
// CHECK: RawDataSize: 100
// CHECK: RelocationCount: 1
// CHECK: Characteristics [
// CHECK-NEXT: ALIGN_4BYTES
// CHECK-NEXT: CNT_INITIALIZED_DATA
// CHECK-NEXT: MEM_READ
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK: Section {
// CHECK: Name: .pdata
// CHECK: RelocationCount: 10
// CHECK: Characteristics [
// CHECK-NEXT: ALIGN_4BYTES
// CHECK-NEXT: CNT_INITIALIZED_DATA
// CHECK-NEXT: MEM_READ
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: Relocations [
// CHECK-NEXT: Section (1) .text {
// CHECK-NEXT: 0x5C IMAGE_REL_ARM_BRANCH24T tailcall
// CHECK-NEXT: }
// CHECK-NEXT: Section (4) .xdata {
// CHECK-NEXT: 0x34 IMAGE_REL_ARM_ADDR32NB __C_specific_handler
// CHECK-NEXT: }
// CHECK-NEXT: Section (5) .pdata {
// CHECK-NEXT: 0x0 IMAGE_REL_ARM_ADDR32NB .text
// CHECK-NEXT: 0x4 IMAGE_REL_ARM_ADDR32NB .xdata
// CHECK-NEXT: 0x8 IMAGE_REL_ARM_ADDR32NB .text
// CHECK-NEXT: 0xC IMAGE_REL_ARM_ADDR32NB .xdata
// CHECK-NEXT: 0x10 IMAGE_REL_ARM_ADDR32NB .text
// CHECK-NEXT: 0x14 IMAGE_REL_ARM_ADDR32NB .xdata
// CHECK-NEXT: 0x18 IMAGE_REL_ARM_ADDR32NB .text
// CHECK-NEXT: 0x1C IMAGE_REL_ARM_ADDR32NB .xdata
// CHECK-NEXT: 0x20 IMAGE_REL_ARM_ADDR32NB .text
// CHECK-NEXT: 0x24 IMAGE_REL_ARM_ADDR32NB .xdata
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: UnwindInformation [
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: func
// CHECK-NEXT: ExceptionRecord: .xdata
// CHECK-NEXT: ExceptionData {
// CHECK-NEXT: FunctionLength: 86
// CHECK: EpiloguePacked: Yes
// CHECK: Fragment: No
// CHECK: EpilogueOffset: 31
// CHECK: Prologue [
// CHECK-NEXT: 0xed 0xf8 ; push {r3-r7, lr}
// CHECK-NEXT: 0xf6 0x27 ; vpush {d18-d23}
// CHECK-NEXT: 0xf5 0x7e ; vpush {d7-d14}
// CHECK-NEXT: 0xfb ; nop
// CHECK-NEXT: 0xce ; mov r14, sp
// CHECK-NEXT: 0xe3 ; vpush {d8-d11}
// CHECK-NEXT: 0xe6 ; vpush {d8-d14}
// CHECK-NEXT: 0xed 0xf8 ; push {r3-r7, lr}
// CHECK-NEXT: 0xbd 0x50 ; push.w {r4, r6, r8, r10-r12, lr}
// CHECK-NEXT: 0xd7 ; push {r4-r7, lr}
// CHECK-NEXT: 0xdd ; push.w {r4-r9, lr}
// CHECK-NEXT: 0xfa 0x01 0x00 0x00 ; sub.w sp, sp, #(65536 * 4)
// CHECK-NEXT: 0xfc ; nop.w
// CHECK-NEXT: 0xfc ; nop.w
// CHECK-NEXT: 0xf9 0x04 0x00 ; sub.w sp, sp, #(1024 * 4)
// CHECK-NEXT: 0xe8 0x80 ; sub.w sp, #(128 * 4)
// CHECK-NEXT: 0xe8 0x80 ; sub.w sp, #(128 * 4)
// CHECK-NEXT: 0x06 ; sub sp, #(6 * 4)
// CHECK-NEXT: ]
// CHECK-NEXT: Epilogue [
// CHECK-NEXT: 0xfc ; nop.w
// CHECK-NEXT: 0xf7 0x00 0x80 ; add sp, sp, #(128 * 4)
// CHECK-NEXT: 0xfc ; nop.w
// CHECK-NEXT: 0xfc ; nop.w
// CHECK-NEXT: 0xf8 0x01 0x00 0x00 ; add sp, sp, #(65536 * 4)
// CHECK-NEXT: 0x06 ; add sp, #(6 * 4)
// CHECK-NEXT: 0xef 0x04 ; ldr.w lr, [sp], #16
// CHECK-NEXT: 0xfd ; bx <reg>
// CHECK-NEXT: ]
// CHECK-NEXT: ExceptionHandler [
// CHECK-NEXT: Routine: __C_specific_handler
// CHECK-NEXT: Parameter: 0x0
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: func2
// CHECK: Prologue [
// CHECK-NEXT: 0xd3 ; push {r4-r7}
// CHECK-NEXT: ]
// CHECK-NEXT: Epilogue [
// CHECK-NEXT: 0xd2 ; pop {r4-r6}
// CHECK-NEXT: 0xfe ; b.w <target>
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: func3
// CHECK: FunctionLength: 8
// CHECK: EpilogueOffset: 2
// CHECK: Prologue [
// CHECK-NEXT: 0xd5 ; push {r4-r5, lr}
// CHECK-NEXT: ]
// CHECK-NEXT: Epilogue [
// CHECK-NEXT: 0xd6 ; pop {r4-r6, pc}
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: fragment
// CHECK: FunctionLength: 6
// CHECK: Fragment: Yes
// CHECK: Prologue [
// CHECK-NEXT: 0xcb ; mov r11, sp
// CHECK-NEXT: 0x10 ; sub sp, #(16 * 4)
// CHECK-NEXT: 0xd5 ; push {r4-r5, lr}
// CHECK-NEXT: ]
// CHECK-NEXT: Epilogue [
// CHECK-NEXT: 0x10 ; add sp, #(16 * 4)
// CHECK-NEXT: 0xd5 ; pop {r4-r5, pc}
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: condepilog
// CHECK: FunctionLength: 8
// CHECK: Prologue [
// CHECK-NEXT: 0xd5 ; push {r4-r5, lr}
// CHECK-NEXT: ]
// CHECK-NEXT: EpilogueScopes [
// CHECK-NEXT: EpilogueScope {
// CHECK-NEXT: StartOffset: 3
// CHECK-NEXT: Condition: 10
// CHECK-NEXT: EpilogueStartIndex: 0
// CHECK-NEXT: Opcodes [
// CHECK-NEXT: 0xd5 ; pop {r4-r5, pc}
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
.text
.syntax unified
.globl func
.def func
.scl 2
.type 32
.endef
.seh_proc func
func:
sub sp, sp, #24
.seh_stackalloc 24
sub sp, sp, #512
.seh_stackalloc_w 512
sub sp, sp, #512
.seh_stackalloc_w 512
sub sp, sp, #4096
.seh_stackalloc_w 4096
movw r7, #0
.seh_nop_w
movt r7, #0x4 // 0x40000
.seh_nop_w
sub sp, sp, r7
.seh_stackalloc_w 0x40000
push {r4-r8,lr}
.seh_save_regs_w {r4-r9,lr}
push {r4-r7,lr}
.seh_save_regs {r4-r7,lr}
push {r4,r6,r8,r10,r11,r12,lr}
.seh_save_regs_w {r4,r6,r8,r10,r11,r12,lr}
push {r3-r7,lr}
.seh_save_regs {r3-r7,lr}
vpush {d8-d14}
.seh_save_fregs {d8-d14}
vpush {q4-q5}
.seh_save_fregs {q4-q5}
mov lr, sp
.seh_save_sp lr
nop
.seh_nop
vpush {d7-d14}
.seh_save_fregs {d7-d14}
vpush {d18-d23}
.seh_save_fregs {d18-d23}
push {r3-r7,lr}
.seh_custom 0xed, 0xf8
.seh_endprologue
nop
.seh_startepilogue
mov r7, #512
.seh_nop_w
add sp, sp, r7
.seh_stackalloc 512
movw r7, #0
.seh_nop_w
movt r7, #0x4 // 0x40000
.seh_nop_w
add sp, sp, r7
.seh_stackalloc 0x40000
add sp, sp, #24
.seh_stackalloc 24
ldr lr, [sp], #16
.seh_save_lr 16
bx lr
.seh_nop
.seh_endepilogue
.seh_handler __C_specific_handler, %except
.seh_handlerdata
.long 0
.text
.seh_endproc
.seh_proc func2
func2:
push {r4-r7}
.seh_save_regs {r4-r7}
.seh_endprologue
nop
.seh_startepilogue
pop {r4-r6}
.seh_save_regs {r4-r6}
b.w tailcall
.seh_nop_w
.seh_endepilogue
.seh_endproc
.seh_proc func3
func3:
push {r4-r5,lr}
.seh_save_regs {r4-r5,lr}
.seh_endprologue
nop
// The p2align causes the length of the function to be unknown.
.p2align 1
nop
.seh_startepilogue
pop {r4-r6,pc}
.seh_save_regs {r4-r6,pc}
.seh_endepilogue
.seh_endproc
.seh_proc fragment
fragment:
// Prologue opcodes without matching instructions
.seh_save_regs {r4-r5,lr}
.seh_stackalloc 64
.seh_save_sp r11
.seh_endprologue_fragment
nop
.seh_startepilogue
add sp, sp, #64
.seh_stackalloc 64
pop {r4-r5,pc}
.seh_save_regs {r4-r5,pc}
.seh_endepilogue
.seh_endproc
.seh_proc condepilog
condepilog:
push {r4-r5,lr}
.seh_save_regs {r4-r5,lr}
.seh_endprologue
nop
it ge
.seh_startepilogue_cond ge
popge {r4-r5,pc}
.seh_save_regs {r4-r5,pc}
.seh_endepilogue
.seh_endproc
// Function with no .seh directives; no pdata/xdata entries are
// generated.
.globl smallFunc
.def smallFunc
.scl 2
.type 32
.endef
.seh_proc smallFunc
smallFunc:
bx lr
.seh_endproc
// Function with no .seh directives, but with .seh_handlerdata.
// No xdata/pdata entries are generated, but the custom handler data
// (the .long after .seh_handlerdata) is left orphaned in the xdata
// section.
.globl handlerFunc
.def handlerFunc
.scl 2
.type 32
.endef
.seh_proc handlerFunc
handlerFunc:
bx lr
.seh_handler __C_specific_handler, %except
.seh_handlerdata
.long 0
.text
.seh_endproc
|