1 // RUN: %cheri_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-HYBRID 2 // RUN: %cheri_purecap_cc1 -mllvm -cheri-cap-table-abi=pcrel -emit-llvm %s -o - | %cheri_FileCheck %s -check-prefixes CHECK-PURECAP 3 // RUN: %cheri_cc1 -S %s -o - | FileCheck %s -check-prefix HYBRID-ASM 4 // RUN: %cheri_purecap_cc1 -S %s -o - | %cheri_FileCheck %s -check-prefix PURECAP-ASM 5 // RUN: %cheri_purecap_cc1 -S %s -o - | %cheri_FileCheck %s -check-prefix PURECAP-ASM 6 7 // We were miscompiling qhooks.cpp from QtBase: even in the purecap ABI we 8 // were emitting .8byte directives for the qtHookData members instead of 9 // capability sized elements. Because of this the qtHookData symbol only 10 // had a size of 7*8 which resulted in length violations on access for 11 // CHERI256 when trying to read the RemoveQObject hook. 12 13 typedef __UINTPTR_TYPE__ quintptr; 14 15 #define QT_VERSION 0x051000 16 namespace QHooks { 17 enum HookIndex { 18 HookDataVersion = 0, 19 HookDataSize = 1, 20 QtVersion = 2, 21 AddQObject = 3, 22 RemoveQObject = 4, 23 Startup = 5, 24 TypeInformationVersion = 6, 25 LastHookIndex 26 }; 27 } 28 quintptr qtHookData[] = { 29 3, // hook data version 30 QHooks::LastHookIndex, // size of qtHookData 31 QT_VERSION, 32 0, 33 0, 34 0, 35 16 36 }; 37 38 // CHECK-HYBRID: @qtHookData = global [7 x i64] [i64 3, i64 7, i64 331776, i64 0, i64 0, i64 0, i64 16], align 8 39 // CHECK-PURECAP: @qtHookData = addrspace(200) global [7 x i8 addrspace(200)*] 40 // CHECK-PURECAP-SAME: [i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 3), 41 // CHECK-PURECAP-SAME: i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 7), 42 // CHECK-PURECAP-SAME: i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 331776), 43 // CHECK-PURECAP-SAME: i8 addrspace(200)* null, i8 addrspace(200)* null, i8 addrspace(200)* null, 44 // CHECK-PURECAP-SAME: i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 16)], align [[#CAP_SIZE]] 45 46 // HYBRID-ASM-LABEL: qtHookData: 47 // HYBRID-ASM-NEXT: .8byte 3 48 // HYBRID-ASM-NEXT: .8byte 7 49 // HYBRID-ASM-NEXT: .8byte 331776 50 // HYBRID-ASM-NEXT: .8byte 0 51 // HYBRID-ASM-NEXT: .8byte 0 52 // HYBRID-ASM-NEXT: .8byte 0 53 // HYBRID-ASM-NEXT: .8byte 16 54 // HYBRID-ASM-NEXT: .size qtHookData, 56 55 56 // PURECAP-ASM-LABEL: qtHookData: 57 // PURECAP-ASM-NEXT: .chericap 3 58 // PURECAP-ASM-NEXT: .chericap 7 59 // PURECAP-ASM-NEXT: .chericap 331776 60 // PURECAP-ASM-NEXT: .chericap 0 61 // PURECAP-ASM-NEXT: .chericap 0 62 // PURECAP-ASM-NEXT: .chericap 0 63 // PURECAP-ASM-NEXT: .chericap 16 64 // PURECAP-ASM-NEXT: .size qtHookData, [[#CAP_SIZE * 7]] 65 66 67 // Some sanity check that this is actually a codegen problem and not a Sema one@ 68 static_assert(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]), ""); 69 static_assert(sizeof(void*) == sizeof(qtHookData[0]), ""); 70 static_assert(sizeof(qtHookData) == QHooks::LastHookIndex * sizeof(void*), ""); 71 72 #ifdef __CHERI_PURE_CAPABILITY__ 73 static_assert(sizeof(quintptr) == sizeof(void*), ""); 74 static_assert(sizeof(quintptr) == sizeof(__uintcap_t), ""); 75 #else 76 static_assert(sizeof(quintptr) == sizeof(long), ""); 77 #endif 78 79 80 // Check that it also works with an array filler 81 quintptr array2[4] = { 82 42, (quintptr)&array2, 83 }; 84 85 // CHECK-HYBRID: @array2 = global [4 x i64] [i64 42, i64 ptrtoint ([4 x i64]* @array2 to i64), i64 0, i64 0], align 8 86 // HYBRID-ASM-LABEL: array2: 87 // HYBRID-ASM-NEXT: .8byte 42 88 // HYBRID-ASM-NEXT: .8byte array2 89 // HYBRID-ASM-NEXT: .8byte 0 90 // HYBRID-ASM-NEXT: .8byte 0 91 // HYBRID-ASM-NEXT: .size array2, 32 92 93 // CHECK-PURECAP: @array2 = addrspace(200) global [4 x i8 addrspace(200)*] 94 // CHECK-PURECAP-SAME: [i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 42), 95 // CHECK-PURECAP-SAME: i8 addrspace(200)* bitcast ([4 x i8 addrspace(200)*] addrspace(200)* @array2 to i8 addrspace(200)*), 96 // CHECK-PURECAP-SAME: i8 addrspace(200)* null, 97 // CHECK-PURECAP-SAME: i8 addrspace(200)* null], align [[#CAP_SIZE]] 98 // PURECAP-ASM-LABEL: array2: 99 // PURECAP-ASM-NEXT: .chericap 42 100 // PURECAP-ASM-NEXT: .chericap array2 101 // PURECAP-ASM-NEXT: .chericap 0 102 // PURECAP-ASM-NEXT: .chericap 0 103 // PURECAP-ASM-NEXT: .size array2, [[#CAP_SIZE * 4]] 104 105 // Check arrays with run-time initializers: 106 quintptr extern_func(); 107 108 quintptr array3[4] = { 109 0, 110 extern_func(), 111 (quintptr)&extern_func, 112 1234567 113 }; 114 115 // CHECK-HYBRID: @array3 = global [4 x i64] zeroinitializer, align 8 116 // CHECK-HYBRID: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_qhooks_array.cpp, i8* null }] 117 // HYBRID-ASM-LABEL: array3: 118 // HYBRID-ASM-NEXT: .space 32 119 // HYBRID-ASM-NEXT: .size array3, 32 120 121 // CHECK-PURECAP: @array3 = addrspace(200) global [4 x i8 addrspace(200)*] zeroinitializer, align [[#CAP_SIZE]] 122 // CHECK-PURECAP: @llvm.global_ctors = appending addrspace(200) global [1 x { i32, void () addrspace(200)*, i8 addrspace(200)* }] [{ i32, void () addrspace(200)*, i8 addrspace(200)* } 123 // CHECK-PURECAP-SAME: { i32 65535, void () addrspace(200)* @_GLOBAL__sub_I_qhooks_array.cpp, i8 addrspace(200)* null }] 124 // PURECAP-ASM-LABEL: array3: 125 // PURECAP-ASM-NEXT: .space [[#CAP_SIZE * 4]] 126 // PURECAP-ASM-NEXT: .size array3, [[#CAP_SIZE * 4]] 127