1// This test checks that the SEH directives emit the correct unwind data. 2 3// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=obj %s | llvm-readobj -S -r -u - | FileCheck %s 4 5// Check that the output assembler directives also can be parsed, and 6// that they produce equivalent output: 7 8// 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 9 10// CHECK: Sections [ 11// CHECK: Section { 12// CHECK: Name: .text 13// CHECK: RelocationCount: 1 14// CHECK: Characteristics [ 15// CHECK-NEXT: ALIGN_4BYTES 16// CHECK-NEXT: CNT_CODE 17// CHECK-NEXT: MEM_16BIT 18// CHECK-NEXT: MEM_EXECUTE 19// CHECK-NEXT: MEM_PURGEABLE 20// CHECK-NEXT: MEM_READ 21// CHECK-NEXT: ] 22// CHECK-NEXT: } 23// CHECK: Section { 24// CHECK: Name: .xdata 25// CHECK: RawDataSize: 100 26// CHECK: RelocationCount: 1 27// CHECK: Characteristics [ 28// CHECK-NEXT: ALIGN_4BYTES 29// CHECK-NEXT: CNT_INITIALIZED_DATA 30// CHECK-NEXT: MEM_READ 31// CHECK-NEXT: ] 32// CHECK-NEXT: } 33// CHECK: Section { 34// CHECK: Name: .pdata 35// CHECK: RelocationCount: 10 36// CHECK: Characteristics [ 37// CHECK-NEXT: ALIGN_4BYTES 38// CHECK-NEXT: CNT_INITIALIZED_DATA 39// CHECK-NEXT: MEM_READ 40// CHECK-NEXT: ] 41// CHECK-NEXT: } 42// CHECK-NEXT: ] 43 44// CHECK-NEXT: Relocations [ 45// CHECK-NEXT: Section (1) .text { 46// CHECK-NEXT: 0x5C IMAGE_REL_ARM_BRANCH24T tailcall 47// CHECK-NEXT: } 48// CHECK-NEXT: Section (4) .xdata { 49// CHECK-NEXT: 0x34 IMAGE_REL_ARM_ADDR32NB __C_specific_handler 50// CHECK-NEXT: } 51// CHECK-NEXT: Section (5) .pdata { 52// CHECK-NEXT: 0x0 IMAGE_REL_ARM_ADDR32NB .text 53// CHECK-NEXT: 0x4 IMAGE_REL_ARM_ADDR32NB .xdata 54// CHECK-NEXT: 0x8 IMAGE_REL_ARM_ADDR32NB .text 55// CHECK-NEXT: 0xC IMAGE_REL_ARM_ADDR32NB .xdata 56// CHECK-NEXT: 0x10 IMAGE_REL_ARM_ADDR32NB .text 57// CHECK-NEXT: 0x14 IMAGE_REL_ARM_ADDR32NB .xdata 58// CHECK-NEXT: 0x18 IMAGE_REL_ARM_ADDR32NB .text 59// CHECK-NEXT: 0x1C IMAGE_REL_ARM_ADDR32NB .xdata 60// CHECK-NEXT: 0x20 IMAGE_REL_ARM_ADDR32NB .text 61// CHECK-NEXT: 0x24 IMAGE_REL_ARM_ADDR32NB .xdata 62// CHECK-NEXT: } 63// CHECK-NEXT: ] 64 65// CHECK-NEXT: UnwindInformation [ 66// CHECK-NEXT: RuntimeFunction { 67// CHECK-NEXT: Function: func 68// CHECK-NEXT: ExceptionRecord: .xdata 69// CHECK-NEXT: ExceptionData { 70// CHECK-NEXT: FunctionLength: 86 71// CHECK: EpiloguePacked: Yes 72// CHECK: Fragment: No 73// CHECK: EpilogueOffset: 31 74// CHECK: Prologue [ 75// CHECK-NEXT: 0xed 0xf8 ; push {r3-r7, lr} 76// CHECK-NEXT: 0xf6 0x27 ; vpush {d18-d23} 77// CHECK-NEXT: 0xf5 0x7e ; vpush {d7-d14} 78// CHECK-NEXT: 0xfb ; nop 79// CHECK-NEXT: 0xce ; mov r14, sp 80// CHECK-NEXT: 0xe3 ; vpush {d8-d11} 81// CHECK-NEXT: 0xe6 ; vpush {d8-d14} 82// CHECK-NEXT: 0xed 0xf8 ; push {r3-r7, lr} 83// CHECK-NEXT: 0xbd 0x50 ; push.w {r4, r6, r8, r10-r12, lr} 84// CHECK-NEXT: 0xd7 ; push {r4-r7, lr} 85// CHECK-NEXT: 0xdd ; push.w {r4-r9, lr} 86// CHECK-NEXT: 0xfa 0x01 0x00 0x00 ; sub.w sp, sp, #(65536 * 4) 87// CHECK-NEXT: 0xfc ; nop.w 88// CHECK-NEXT: 0xfc ; nop.w 89// CHECK-NEXT: 0xf9 0x04 0x00 ; sub.w sp, sp, #(1024 * 4) 90// CHECK-NEXT: 0xe8 0x80 ; sub.w sp, #(128 * 4) 91// CHECK-NEXT: 0xe8 0x80 ; sub.w sp, #(128 * 4) 92// CHECK-NEXT: 0x06 ; sub sp, #(6 * 4) 93// CHECK-NEXT: ] 94// CHECK-NEXT: Epilogue [ 95// CHECK-NEXT: 0xfc ; nop.w 96// CHECK-NEXT: 0xf7 0x00 0x80 ; add sp, sp, #(128 * 4) 97// CHECK-NEXT: 0xfc ; nop.w 98// CHECK-NEXT: 0xfc ; nop.w 99// CHECK-NEXT: 0xf8 0x01 0x00 0x00 ; add sp, sp, #(65536 * 4) 100// CHECK-NEXT: 0x06 ; add sp, #(6 * 4) 101// CHECK-NEXT: 0xef 0x04 ; ldr.w lr, [sp], #16 102// CHECK-NEXT: 0xfd ; bx <reg> 103// CHECK-NEXT: ] 104// CHECK-NEXT: ExceptionHandler [ 105// CHECK-NEXT: Routine: __C_specific_handler 106// CHECK-NEXT: Parameter: 0x0 107// CHECK-NEXT: ] 108// CHECK-NEXT: } 109// CHECK-NEXT: } 110// CHECK-NEXT: RuntimeFunction { 111// CHECK-NEXT: Function: func2 112// CHECK: Prologue [ 113// CHECK-NEXT: 0xd3 ; push {r4-r7} 114// CHECK-NEXT: ] 115// CHECK-NEXT: Epilogue [ 116// CHECK-NEXT: 0xd2 ; pop {r4-r6} 117// CHECK-NEXT: 0xfe ; b.w <target> 118// CHECK-NEXT: ] 119// CHECK-NEXT: } 120// CHECK-NEXT: } 121// CHECK-NEXT: RuntimeFunction { 122// CHECK-NEXT: Function: func3 123// CHECK: FunctionLength: 8 124// CHECK: EpilogueOffset: 2 125// CHECK: Prologue [ 126// CHECK-NEXT: 0xd5 ; push {r4-r5, lr} 127// CHECK-NEXT: ] 128// CHECK-NEXT: Epilogue [ 129// CHECK-NEXT: 0xd6 ; pop {r4-r6, pc} 130// CHECK-NEXT: ] 131// CHECK-NEXT: } 132// CHECK-NEXT: } 133// CHECK-NEXT: RuntimeFunction { 134// CHECK-NEXT: Function: fragment 135// CHECK: FunctionLength: 6 136// CHECK: Fragment: Yes 137// CHECK: Prologue [ 138// CHECK-NEXT: 0xcb ; mov r11, sp 139// CHECK-NEXT: 0x10 ; sub sp, #(16 * 4) 140// CHECK-NEXT: 0xd5 ; push {r4-r5, lr} 141// CHECK-NEXT: ] 142// CHECK-NEXT: Epilogue [ 143// CHECK-NEXT: 0x10 ; add sp, #(16 * 4) 144// CHECK-NEXT: 0xd5 ; pop {r4-r5, pc} 145// CHECK-NEXT: ] 146// CHECK-NEXT: } 147// CHECK-NEXT: } 148// CHECK-NEXT: RuntimeFunction { 149// CHECK-NEXT: Function: condepilog 150// CHECK: FunctionLength: 8 151// CHECK: Prologue [ 152// CHECK-NEXT: 0xd5 ; push {r4-r5, lr} 153// CHECK-NEXT: ] 154// CHECK-NEXT: EpilogueScopes [ 155// CHECK-NEXT: EpilogueScope { 156// CHECK-NEXT: StartOffset: 3 157// CHECK-NEXT: Condition: 10 158// CHECK-NEXT: EpilogueStartIndex: 0 159// CHECK-NEXT: Opcodes [ 160// CHECK-NEXT: 0xd5 ; pop {r4-r5, pc} 161// CHECK-NEXT: ] 162// CHECK-NEXT: } 163// CHECK-NEXT: ] 164// CHECK-NEXT: } 165// CHECK-NEXT: } 166// CHECK-NEXT: ] 167 168 .text 169 .syntax unified 170 .globl func 171 .def func 172 .scl 2 173 .type 32 174 .endef 175 .seh_proc func 176func: 177 sub sp, sp, #24 178 .seh_stackalloc 24 179 sub sp, sp, #512 180 .seh_stackalloc_w 512 181 sub sp, sp, #512 182 .seh_stackalloc_w 512 183 sub sp, sp, #4096 184 .seh_stackalloc_w 4096 185 movw r7, #0 186 .seh_nop_w 187 movt r7, #0x4 // 0x40000 188 .seh_nop_w 189 sub sp, sp, r7 190 .seh_stackalloc_w 0x40000 191 push {r4-r8,lr} 192 .seh_save_regs_w {r4-r9,lr} 193 push {r4-r7,lr} 194 .seh_save_regs {r4-r7,lr} 195 push {r4,r6,r8,r10,r11,r12,lr} 196 .seh_save_regs_w {r4,r6,r8,r10,r11,r12,lr} 197 push {r3-r7,lr} 198 .seh_save_regs {r3-r7,lr} 199 vpush {d8-d14} 200 .seh_save_fregs {d8-d14} 201 vpush {q4-q5} 202 .seh_save_fregs {q4-q5} 203 mov lr, sp 204 .seh_save_sp lr 205 nop 206 .seh_nop 207 vpush {d7-d14} 208 .seh_save_fregs {d7-d14} 209 vpush {d18-d23} 210 .seh_save_fregs {d18-d23} 211 push {r3-r7,lr} 212 .seh_custom 0xed, 0xf8 213 .seh_endprologue 214 nop 215 .seh_startepilogue 216 mov r7, #512 217 .seh_nop_w 218 add sp, sp, r7 219 .seh_stackalloc 512 220 movw r7, #0 221 .seh_nop_w 222 movt r7, #0x4 // 0x40000 223 .seh_nop_w 224 add sp, sp, r7 225 .seh_stackalloc 0x40000 226 add sp, sp, #24 227 .seh_stackalloc 24 228 ldr lr, [sp], #16 229 .seh_save_lr 16 230 bx lr 231 .seh_nop 232 .seh_endepilogue 233 .seh_handler __C_specific_handler, %except 234 .seh_handlerdata 235 .long 0 236 .text 237 .seh_endproc 238 239 .seh_proc func2 240func2: 241 push {r4-r7} 242 .seh_save_regs {r4-r7} 243 .seh_endprologue 244 nop 245 .seh_startepilogue 246 pop {r4-r6} 247 .seh_save_regs {r4-r6} 248 b.w tailcall 249 .seh_nop_w 250 .seh_endepilogue 251 .seh_endproc 252 253 .seh_proc func3 254func3: 255 push {r4-r5,lr} 256 .seh_save_regs {r4-r5,lr} 257 .seh_endprologue 258 nop 259 // The p2align causes the length of the function to be unknown. 260 .p2align 1 261 nop 262 .seh_startepilogue 263 pop {r4-r6,pc} 264 .seh_save_regs {r4-r6,pc} 265 .seh_endepilogue 266 .seh_endproc 267 268 .seh_proc fragment 269fragment: 270 // Prologue opcodes without matching instructions 271 .seh_save_regs {r4-r5,lr} 272 .seh_stackalloc 64 273 .seh_save_sp r11 274 .seh_endprologue_fragment 275 nop 276 .seh_startepilogue 277 add sp, sp, #64 278 .seh_stackalloc 64 279 pop {r4-r5,pc} 280 .seh_save_regs {r4-r5,pc} 281 .seh_endepilogue 282 .seh_endproc 283 284 .seh_proc condepilog 285condepilog: 286 push {r4-r5,lr} 287 .seh_save_regs {r4-r5,lr} 288 .seh_endprologue 289 nop 290 it ge 291 .seh_startepilogue_cond ge 292 popge {r4-r5,pc} 293 .seh_save_regs {r4-r5,pc} 294 .seh_endepilogue 295 .seh_endproc 296 297 // Function with no .seh directives; no pdata/xdata entries are 298 // generated. 299 .globl smallFunc 300 .def smallFunc 301 .scl 2 302 .type 32 303 .endef 304 .seh_proc smallFunc 305smallFunc: 306 bx lr 307 .seh_endproc 308 309 // Function with no .seh directives, but with .seh_handlerdata. 310 // No xdata/pdata entries are generated, but the custom handler data 311 // (the .long after .seh_handlerdata) is left orphaned in the xdata 312 // section. 313 .globl handlerFunc 314 .def handlerFunc 315 .scl 2 316 .type 32 317 .endef 318 .seh_proc handlerFunc 319handlerFunc: 320 bx lr 321 .seh_handler __C_specific_handler, %except 322 .seh_handlerdata 323 .long 0 324 .text 325 .seh_endproc 326