239 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 | 
						|
; RUN: llc -mtriple x86_64-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86_64
 | 
						|
; RUN: llc -mtriple i386-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86
 | 
						|
 | 
						|
; The MacOS tripples are used to get trapping behavior on the "unreachable" IR
 | 
						|
; instruction, so that the placement of the ud2 instruction could be verified.
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
;; The IR was created using the following C code:
 | 
						|
;; typedef ptr jmp_buf;
 | 
						|
;; jmp_buf buf;
 | 
						|
;;
 | 
						|
;; __attribute__((noinline)) int bar(int i) {
 | 
						|
;;   int j = i - 111;
 | 
						|
;;   __builtin_longjmp(&buf, 1);
 | 
						|
;;   return j;
 | 
						|
;; }
 | 
						|
;;
 | 
						|
;; int foo(int i) {
 | 
						|
;;   int j = i * 11;
 | 
						|
;;   if (!__builtin_setjmp(&buf)) {
 | 
						|
;;     j += 33 + bar(j);
 | 
						|
;;   }
 | 
						|
;;   return j + i;
 | 
						|
;; }
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
@buf = common local_unnamed_addr global ptr null, align 8
 | 
						|
 | 
						|
; Functions that use LongJmp should fix the Shadow Stack using previosuly saved
 | 
						|
; ShadowStackPointer in the input buffer.
 | 
						|
; The fix requires unwinding the shadow stack to the last SSP.
 | 
						|
define i32 @bar(i32 %i) local_unnamed_addr {
 | 
						|
; X86_64-LABEL: bar:
 | 
						|
; X86_64:       ## %bb.0: ## %entry
 | 
						|
; X86_64-NEXT:    pushq %rbp
 | 
						|
; X86_64-NEXT:    .cfi_def_cfa_offset 16
 | 
						|
; X86_64-NEXT:    .cfi_offset %rbp, -16
 | 
						|
; X86_64-NEXT:    movq _buf@GOTPCREL(%rip), %rax
 | 
						|
; X86_64-NEXT:    movq (%rax), %rax
 | 
						|
; X86_64-NEXT:    xorl %edx, %edx
 | 
						|
; X86_64-NEXT:    rdsspq %rdx
 | 
						|
; X86_64-NEXT:    testq %rdx, %rdx
 | 
						|
; X86_64-NEXT:    je LBB0_5
 | 
						|
; X86_64-NEXT:  ## %bb.1: ## %entry
 | 
						|
; X86_64-NEXT:    movq 24(%rax), %rcx
 | 
						|
; X86_64-NEXT:    subq %rdx, %rcx
 | 
						|
; X86_64-NEXT:    jbe LBB0_5
 | 
						|
; X86_64-NEXT:  ## %bb.2: ## %entry
 | 
						|
; X86_64-NEXT:    shrq $3, %rcx
 | 
						|
; X86_64-NEXT:    incsspq %rcx
 | 
						|
; X86_64-NEXT:    shrq $8, %rcx
 | 
						|
; X86_64-NEXT:    je LBB0_5
 | 
						|
; X86_64-NEXT:  ## %bb.3: ## %entry
 | 
						|
; X86_64-NEXT:    shlq %rcx
 | 
						|
; X86_64-NEXT:    movq $128, %rdx
 | 
						|
; X86_64-NEXT:  LBB0_4: ## %entry
 | 
						|
; X86_64-NEXT:    ## =>This Inner Loop Header: Depth=1
 | 
						|
; X86_64-NEXT:    incsspq %rdx
 | 
						|
; X86_64-NEXT:    decq %rcx
 | 
						|
; X86_64-NEXT:    jne LBB0_4
 | 
						|
; X86_64-NEXT:  LBB0_5: ## %entry
 | 
						|
; X86_64-NEXT:    movq (%rax), %rbp
 | 
						|
; X86_64-NEXT:    movq 8(%rax), %rcx
 | 
						|
; X86_64-NEXT:    movq 16(%rax), %rsp
 | 
						|
; X86_64-NEXT:    jmpq *%rcx
 | 
						|
;
 | 
						|
; X86-LABEL: bar:
 | 
						|
; X86:       ## %bb.0: ## %entry
 | 
						|
; X86-NEXT:    pushl %ebp
 | 
						|
; X86-NEXT:    .cfi_def_cfa_offset 8
 | 
						|
; X86-NEXT:    .cfi_offset %ebp, -8
 | 
						|
; X86-NEXT:    movl L_buf$non_lazy_ptr, %eax
 | 
						|
; X86-NEXT:    movl (%eax), %eax
 | 
						|
; X86-NEXT:    xorl %edx, %edx
 | 
						|
; X86-NEXT:    rdsspd %edx
 | 
						|
; X86-NEXT:    testl %edx, %edx
 | 
						|
; X86-NEXT:    je LBB0_5
 | 
						|
; X86-NEXT:  ## %bb.1: ## %entry
 | 
						|
; X86-NEXT:    movl 12(%eax), %ecx
 | 
						|
; X86-NEXT:    subl %edx, %ecx
 | 
						|
; X86-NEXT:    jbe LBB0_5
 | 
						|
; X86-NEXT:  ## %bb.2: ## %entry
 | 
						|
; X86-NEXT:    shrl $2, %ecx
 | 
						|
; X86-NEXT:    incsspd %ecx
 | 
						|
; X86-NEXT:    shrl $8, %ecx
 | 
						|
; X86-NEXT:    je LBB0_5
 | 
						|
; X86-NEXT:  ## %bb.3: ## %entry
 | 
						|
; X86-NEXT:    shll %ecx
 | 
						|
; X86-NEXT:    movl $128, %edx
 | 
						|
; X86-NEXT:  LBB0_4: ## %entry
 | 
						|
; X86-NEXT:    ## =>This Inner Loop Header: Depth=1
 | 
						|
; X86-NEXT:    incsspd %edx
 | 
						|
; X86-NEXT:    decl %ecx
 | 
						|
; X86-NEXT:    jne LBB0_4
 | 
						|
; X86-NEXT:  LBB0_5: ## %entry
 | 
						|
; X86-NEXT:    movl (%eax), %ebp
 | 
						|
; X86-NEXT:    movl 4(%eax), %ecx
 | 
						|
; X86-NEXT:    movl 8(%eax), %esp
 | 
						|
; X86-NEXT:    jmpl *%ecx
 | 
						|
entry:
 | 
						|
  %0 = load ptr, ptr @buf, align 8
 | 
						|
  tail call void @llvm.eh.sjlj.longjmp(ptr %0)
 | 
						|
  unreachable
 | 
						|
}
 | 
						|
 | 
						|
declare void @llvm.eh.sjlj.longjmp(ptr)
 | 
						|
 | 
						|
; Functions that call SetJmp should save the current ShadowStackPointer for
 | 
						|
; future fixing of the Shadow Stack.
 | 
						|
define i32 @foo(i32 %i) local_unnamed_addr {
 | 
						|
; X86_64-LABEL: foo:
 | 
						|
; X86_64:       ## %bb.0: ## %entry
 | 
						|
; X86_64-NEXT:    pushq %rbp
 | 
						|
; X86_64-NEXT:    .cfi_def_cfa_offset 16
 | 
						|
; X86_64-NEXT:    .cfi_offset %rbp, -16
 | 
						|
; X86_64-NEXT:    movq %rsp, %rbp
 | 
						|
; X86_64-NEXT:    .cfi_def_cfa_register %rbp
 | 
						|
; X86_64-NEXT:    pushq %r15
 | 
						|
; X86_64-NEXT:    pushq %r14
 | 
						|
; X86_64-NEXT:    pushq %r13
 | 
						|
; X86_64-NEXT:    pushq %r12
 | 
						|
; X86_64-NEXT:    pushq %rbx
 | 
						|
; X86_64-NEXT:    pushq %rax
 | 
						|
; X86_64-NEXT:    .cfi_offset %rbx, -56
 | 
						|
; X86_64-NEXT:    .cfi_offset %r12, -48
 | 
						|
; X86_64-NEXT:    .cfi_offset %r13, -40
 | 
						|
; X86_64-NEXT:    .cfi_offset %r14, -32
 | 
						|
; X86_64-NEXT:    .cfi_offset %r15, -24
 | 
						|
; X86_64-NEXT:    ## kill: def $edi killed $edi def $rdi
 | 
						|
; X86_64-NEXT:    movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill
 | 
						|
; X86_64-NEXT:    movq _buf@GOTPCREL(%rip), %rax
 | 
						|
; X86_64-NEXT:    movq (%rax), %rax
 | 
						|
; X86_64-NEXT:    movq %rbp, (%rax)
 | 
						|
; X86_64-NEXT:    movq %rsp, 16(%rax)
 | 
						|
; X86_64-NEXT:    leaq LBB1_4(%rip), %rcx
 | 
						|
; X86_64-NEXT:    movq %rcx, 8(%rax)
 | 
						|
; X86_64-NEXT:    xorq %rcx, %rcx
 | 
						|
; X86_64-NEXT:    rdsspq %rcx
 | 
						|
; X86_64-NEXT:    movq %rcx, 24(%rax)
 | 
						|
; X86_64-NEXT:    #EH_SjLj_Setup LBB1_4
 | 
						|
; X86_64-NEXT:  ## %bb.1: ## %entry
 | 
						|
; X86_64-NEXT:    xorl %eax, %eax
 | 
						|
; X86_64-NEXT:    jmp LBB1_2
 | 
						|
; X86_64-NEXT:  LBB1_4: ## Block address taken
 | 
						|
; X86_64-NEXT:    ## %entry
 | 
						|
; X86_64-NEXT:    movl $1, %eax
 | 
						|
; X86_64-NEXT:  LBB1_2: ## %entry
 | 
						|
; X86_64-NEXT:    testl %eax, %eax
 | 
						|
; X86_64-NEXT:    je LBB1_5
 | 
						|
; X86_64-NEXT:  ## %bb.3: ## %if.end
 | 
						|
; X86_64-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload
 | 
						|
; X86_64-NEXT:    shll $2, %eax
 | 
						|
; X86_64-NEXT:    leal (%rax,%rax,2), %eax
 | 
						|
; X86_64-NEXT:    addq $8, %rsp
 | 
						|
; X86_64-NEXT:    popq %rbx
 | 
						|
; X86_64-NEXT:    popq %r12
 | 
						|
; X86_64-NEXT:    popq %r13
 | 
						|
; X86_64-NEXT:    popq %r14
 | 
						|
; X86_64-NEXT:    popq %r15
 | 
						|
; X86_64-NEXT:    popq %rbp
 | 
						|
; X86_64-NEXT:    retq
 | 
						|
; X86_64-NEXT:  LBB1_5: ## %if.then
 | 
						|
; X86_64-NEXT:    callq _bar
 | 
						|
; X86_64-NEXT:    ud2
 | 
						|
;
 | 
						|
; X86-LABEL: foo:
 | 
						|
; X86:       ## %bb.0: ## %entry
 | 
						|
; X86-NEXT:    pushl %ebp
 | 
						|
; X86-NEXT:    .cfi_def_cfa_offset 8
 | 
						|
; X86-NEXT:    .cfi_offset %ebp, -8
 | 
						|
; X86-NEXT:    movl %esp, %ebp
 | 
						|
; X86-NEXT:    .cfi_def_cfa_register %ebp
 | 
						|
; X86-NEXT:    pushl %ebx
 | 
						|
; X86-NEXT:    pushl %edi
 | 
						|
; X86-NEXT:    pushl %esi
 | 
						|
; X86-NEXT:    subl $12, %esp
 | 
						|
; X86-NEXT:    .cfi_offset %esi, -20
 | 
						|
; X86-NEXT:    .cfi_offset %edi, -16
 | 
						|
; X86-NEXT:    .cfi_offset %ebx, -12
 | 
						|
; X86-NEXT:    movl L_buf$non_lazy_ptr, %eax
 | 
						|
; X86-NEXT:    movl (%eax), %eax
 | 
						|
; X86-NEXT:    movl %ebp, (%eax)
 | 
						|
; X86-NEXT:    movl %esp, 16(%eax)
 | 
						|
; X86-NEXT:    movl $LBB1_4, 4(%eax)
 | 
						|
; X86-NEXT:    xorl %ecx, %ecx
 | 
						|
; X86-NEXT:    rdsspd %ecx
 | 
						|
; X86-NEXT:    movl %ecx, 12(%eax)
 | 
						|
; X86-NEXT:    #EH_SjLj_Setup LBB1_4
 | 
						|
; X86-NEXT:  ## %bb.1: ## %entry
 | 
						|
; X86-NEXT:    xorl %eax, %eax
 | 
						|
; X86-NEXT:    jmp LBB1_2
 | 
						|
; X86-NEXT:  LBB1_4: ## Block address taken
 | 
						|
; X86-NEXT:    ## %entry
 | 
						|
; X86-NEXT:    movl $1, %eax
 | 
						|
; X86-NEXT:  LBB1_2: ## %entry
 | 
						|
; X86-NEXT:    testl %eax, %eax
 | 
						|
; X86-NEXT:    je LBB1_5
 | 
						|
; X86-NEXT:  ## %bb.3: ## %if.end
 | 
						|
; X86-NEXT:    movl 8(%ebp), %eax
 | 
						|
; X86-NEXT:    shll $2, %eax
 | 
						|
; X86-NEXT:    leal (%eax,%eax,2), %eax
 | 
						|
; X86-NEXT:    addl $12, %esp
 | 
						|
; X86-NEXT:    popl %esi
 | 
						|
; X86-NEXT:    popl %edi
 | 
						|
; X86-NEXT:    popl %ebx
 | 
						|
; X86-NEXT:    popl %ebp
 | 
						|
; X86-NEXT:    retl
 | 
						|
; X86-NEXT:  LBB1_5: ## %if.then
 | 
						|
; X86-NEXT:    calll _bar
 | 
						|
; X86-NEXT:    ud2
 | 
						|
entry:
 | 
						|
  %0 = load ptr, ptr @buf, align 8
 | 
						|
  %1 = tail call ptr @llvm.frameaddress(i32 0)
 | 
						|
  store ptr %1, ptr %0, align 8
 | 
						|
  %2 = tail call ptr @llvm.stacksave()
 | 
						|
  %3 = getelementptr inbounds i8, ptr %0, i64 16
 | 
						|
  store ptr %2, ptr %3, align 8
 | 
						|
  %4 = tail call i32 @llvm.eh.sjlj.setjmp(ptr %0)
 | 
						|
  %tobool = icmp eq i32 %4, 0
 | 
						|
  br i1 %tobool, label %if.then, label %if.end
 | 
						|
 | 
						|
if.then:                                          ; preds = %entry
 | 
						|
  %call = tail call i32 @bar(i32 undef)
 | 
						|
  unreachable
 | 
						|
 | 
						|
if.end:                                           ; preds = %entry
 | 
						|
  %add2 = mul nsw i32 %i, 12
 | 
						|
  ret i32 %add2
 | 
						|
}
 | 
						|
 | 
						|
declare ptr @llvm.frameaddress(i32)
 | 
						|
declare ptr @llvm.stacksave()
 | 
						|
declare i32 @llvm.eh.sjlj.setjmp(ptr)
 | 
						|
 | 
						|
!llvm.module.flags = !{!0}
 | 
						|
 | 
						|
!0 = !{i32 4, !"cf-protection-return", i32 1}
 |