119 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -O2 -mtriple=x86_64-unknown-unknown -x86-indirect-branch-tracking | FileCheck %s3 4; This test is for CET enhancement.5;6; ENDBR32 and ENDBR64 have specific opcodes:7; ENDBR32: F3 0F 1E FB8; ENDBR64: F3 0F 1E FA9; And we want that attackers won’t find unintended ENDBR32/6410; opcode matches in the binary11; Here’s an example:12; If the compiler had to generate asm for the following code:13; a = 0xF30F1EFA14; it could, for example, generate:15; mov 0xF30F1EFA, dword ptr[a]16; In such a case, the binary would include a gadget that starts17; with a fake ENDBR64 opcode. Therefore, we split such generation18; into multiple operations, let it not shows in the binary.19 20; 0xF30F1EFA == -217112838 ~0xF30F1EFA == 217112837 (0xCF0E105)21; 0x000123F32E0F1EFA == 32100233347865022; ~0x000123F32E0F1EFA == -321002333478651 (0XFFFEDC0CD1F0E105)23 24; test for MOV64ri25define dso_local i64 @foo(ptr %azx) #0 {26; CHECK-LABEL: foo:27; CHECK: # %bb.0: # %entry28; CHECK-NEXT: endbr6429; CHECK-NEXT: movq %rdi, -{{[0-9]+}}(%rsp)30; CHECK-NEXT: movabsq $-321002333478651, %rax # imm = 0xFFFEDC0CD1F0E10531; CHECK-NEXT: notq %rax32; CHECK-NEXT: andq %rax, (%rdi)33; CHECK-NEXT: movq -{{[0-9]+}}(%rsp), %rax34; CHECK-NEXT: movq (%rax), %rax35; CHECK-NEXT: retq36entry:37 %azx.addr = alloca ptr, align 838 store ptr %azx, ptr %azx.addr, align 839 %0 = load ptr, ptr %azx.addr, align 840 %1 = load i64, ptr %0, align 841 %and = and i64 %1, 32100233347865042 %2 = load ptr, ptr %azx.addr, align 843 store i64 %and, ptr %2, align 844 %3 = load ptr, ptr %azx.addr, align 845 %4 = load i64, ptr %3, align 846 ret i64 %447}48 49@bzx = dso_local local_unnamed_addr global i32 -217112837, align 450 51; test for AND32ri52define dso_local i32 @foo2() local_unnamed_addr #0 {53; CHECK-LABEL: foo2:54; CHECK: # %bb.0: # %entry55; CHECK-NEXT: endbr6456; CHECK-NEXT: movl bzx(%rip), %ecx57; CHECK-NEXT: addl %ecx, %ecx58; CHECK-NEXT: movl $217112837, %eax # imm = 0xCF0E10559; CHECK-NEXT: notl %eax60; CHECK-NEXT: andl %ecx, %eax61; CHECK-NEXT: retq62entry:63 %0 = load i32, ptr @bzx, align 464 %mul = shl nsw i32 %0, 165 %and = and i32 %mul, -21711283866 ret i32 %and67}68 69 70@czx = dso_local global i32 -217112837, align 471 72; test for AND32mi73define dso_local nonnull ptr @foo3() local_unnamed_addr #0 {74; CHECK-LABEL: foo3:75; CHECK: # %bb.0: # %entry76; CHECK-NEXT: endbr6477; CHECK-NEXT: movl $217112837, %eax # imm = 0xCF0E10578; CHECK-NEXT: notl %eax79; CHECK-NEXT: andl %eax, czx(%rip)80; CHECK-NEXT: movl $czx, %eax81; CHECK-NEXT: retq82entry:83 %0 = load i32, ptr @czx, align 484 %and = and i32 %0, -21711283885 store i32 %and, ptr @czx, align 486 ret ptr @czx87}88 89; test for MOV32mi90define dso_local i32 @foo4() #0 {91; CHECK-LABEL: foo4:92; CHECK: # %bb.0: # %entry93; CHECK-NEXT: endbr6494; CHECK-NEXT: movl $217112837, %eax # imm = 0xCF0E10595; CHECK-NEXT: notl %eax96; CHECK-NEXT: movl %eax, -{{[0-9]+}}(%rsp)97; CHECK-NEXT: retq98entry:99 %dzx = alloca i32, align 4100 store i32 -217112838, ptr %dzx, align 4101 %0 = load i32, ptr %dzx, align 4102 ret i32 %0103}104 105define dso_local i64 @foo5() #0 {106; CHECK-LABEL: foo5:107; CHECK: # %bb.0: # %entry108; CHECK-NEXT: endbr64109; CHECK-NEXT: movabsq $-4077854459, %rax # imm = 0xFFFFFFFF0CF0E105110; CHECK-NEXT: notq %rax111; CHECK-NEXT: movq %rax, -{{[0-9]+}}(%rsp)112; CHECK-NEXT: retq113entry:114 %ezx = alloca i64, align 8115 store i64 4077854458, ptr %ezx, align 8116 %0 = load i64, ptr %ezx, align 8117 ret i64 %0118}119