-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Clang][kcfi] Sign extend KCFI typeid rather than zero extend #136734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The KCFI typeid may be negative, but will result in this type of
bitcode:
module asm ".weak __kcfi_typeid_func"
module asm ".set __kcfi_typeid_func, 2874394057"
// ...
define dso_local i32 @call_unsigned(ptr noundef %f) #0 !kcfi_type !6 {
// ...
%call = call i32 %0(i32 noundef 37) [ "kcfi"(i32 -1420573239) ]
ret i32 %call
}
declare !kcfi_type !7 noundef i32 @foo(i32 noundef)
// ...
!7 = !{i32 -1420573239}
The __kcfi_typeid_func value doesn't equal the metadata value.
Therefore, we sign extend the typeid value rather than zero extend.
This also reorganizes the testcase to remove the "-DAG" checks, which
are a bit confusing at first.
Signed-off-by: Bill Wendling <[email protected]>
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Bill Wendling (bwendling) ChangesThe KCFI typeid may be negative, but will result in this type of bitcode: The __kcfi_typeid_func value doesn't equal the metadata value. Therefore, we sign extend the typeid value rather than zero extend. This also reorganizes the testcase to remove the "-DAG" checks, which are a bit confusing at first. Full diff: https://github.com/llvm/llvm-project/pull/136734.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 83d8d4f758195..0422f4ab1cebb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2931,7 +2931,7 @@ void CodeGenModule::finalizeKCFITypes() {
continue;
std::string Asm = (".weak __kcfi_typeid_" + Name + "\n.set __kcfi_typeid_" +
- Name + ", " + Twine(Type->getZExtValue()) + "\n")
+ Name + ", " + Twine(Type->getSExtValue()) + "\n")
.str();
M.appendModuleInlineAsm(Asm);
}
diff --git a/clang/test/CodeGen/kcfi.c b/clang/test/CodeGen/kcfi.c
index 622843cedba50..058f3277a8119 100644
--- a/clang/test/CodeGen/kcfi.c
+++ b/clang/test/CodeGen/kcfi.c
@@ -8,18 +8,25 @@
/// Must emit __kcfi_typeid symbols for address-taken function declarations
// CHECK: module asm ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
// CHECK: module asm ".set __kcfi_typeid_[[F4]], [[#%d,HASH:]]"
+// CHECK: module asm ".weak __kcfi_typeid_[[F4_ARG:[a-zA-Z0-9_]+]]"
+// CHECK: module asm ".set __kcfi_typeid_[[F4_ARG]], [[#%d,ARG_HASH:]]"
+
/// Must not __kcfi_typeid symbols for non-address-taken declarations
// CHECK-NOT: module asm ".weak __kcfi_typeid_{{f6|_Z2f6v}}"
// C: @ifunc1 = ifunc i32 (i32), ptr @resolver1
// C: @ifunc2 = ifunc i64 (i64), ptr @resolver2
typedef int (*fn_t)(void);
+typedef int (*fn_u_t)(unsigned int);
-// CHECK: define dso_local{{.*}} i32 @{{f1|_Z2f1v}}(){{.*}} !kcfi_type ![[#TYPE:]]
-int f1(void) { return 0; }
+int f1(void);
-// CHECK: define dso_local{{.*}} i32 @{{f2|_Z2f2v}}(){{.*}} !kcfi_type ![[#TYPE2:]]
-unsigned int f2(void) { return 2; }
+unsigned int f2(void);
+
+static int f3(void);
+
+extern int f4(void);
+extern int f4_arg(unsigned int);
// CHECK-LABEL: define dso_local{{.*}} i32 @{{__call|_Z6__callPFivE}}(ptr{{.*}} %f)
int __call(fn_t f) __attribute__((__no_sanitize__("kcfi"))) {
@@ -27,17 +34,45 @@ int __call(fn_t f) __attribute__((__no_sanitize__("kcfi"))) {
return f();
}
-// CHECK: define dso_local{{.*}} i32 @{{call|_Z4callPFivE}}(ptr{{.*}} %f){{.*}}
+// CHECK-LABEL: define dso_local{{.*}} i32 @{{call|_Z4callPFivE}}(ptr{{.*}} %f)
int call(fn_t f) {
// CHECK: call{{.*}} i32 %{{.}}(){{.*}} [ "kcfi"(i32 [[#HASH]]) ]
return f();
}
-// CHECK-DAG: define internal{{.*}} i32 @{{f3|_ZL2f3v}}(){{.*}} !kcfi_type ![[#TYPE]]
+// CHECK-LABEL: define dso_local{{.*}} i32 @{{call_with_arg|_Z13call_with_argPFijE}}(ptr{{.*}} %f)
+int call_with_arg(fn_u_t f) {
+ // CHECK: call{{.*}} i32 %0(i32 {{.*}}) [ "kcfi"(i32 [[#ARG_HASH]]) ]
+ return f(42);
+}
+
+static int f5(void);
+
+extern int f6(void);
+
+int test(void) {
+ return call(f1) +
+ __call((fn_t)f2) +
+ call(f3) +
+ call(f4) +
+ call_with_arg(f4_arg) +
+ f5() +
+ f6();
+}
+
+// CHECK-LABEL: define dso_local{{.*}} i32 @{{f1|_Z2f1v}}(){{.*}} !kcfi_type ![[#TYPE:]]
+int f1(void) { return 0; }
+
+// CHECK-LABEL: define dso_local{{.*}} i32 @{{f2|_Z2f2v}}(){{.*}} !kcfi_type ![[#TYPE2:]]
+unsigned int f2(void) { return 2; }
+
+// CHECK: define internal{{.*}} i32 @{{f3|_ZL2f3v}}(){{.*}} !kcfi_type ![[#TYPE]]
static int f3(void) { return 1; }
-// CHECK-DAG: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @[[F4]]()
-extern int f4(void);
+// CHECK-LABEL: declare !kcfi_type
+// CHECK-SAME: ![[#TYPE]]{{.*}} i32 @[[F4]]
+// CHECK-LABEL: declare !kcfi_type
+// CHECK-SAME: ![[#ARG_TYPE:]]{{.*}} i32 @[[F4_ARG]]
/// Must not emit !kcfi_type for non-address-taken local functions
// CHECK: define internal{{.*}} i32 @{{f5|_ZL2f5v}}()
@@ -45,8 +80,7 @@ extern int f4(void);
// CHECK-SAME: {
static int f5(void) { return 2; }
-// CHECK-DAG: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @{{f6|_Z2f6v}}()
-extern int f6(void);
+// CHECK: declare !kcfi_type ![[#TYPE]]{{.*}} i32 @{{f6|_Z2f6v}}()
#ifndef __cplusplus
// C: define internal ptr @resolver1() #[[#]] !kcfi_type ![[#]] {
@@ -58,30 +92,26 @@ static void *resolver2(void) { return 0; }
long ifunc2(long) __attribute__((ifunc("resolver2")));
#endif
-int test(void) {
- return call(f1) +
- __call((fn_t)f2) +
- call(f3) +
- call(f4) +
- f5() +
- f6();
-}
-
#ifdef __cplusplus
struct A {
- // MEMBER-DAG: define{{.*}} void @_ZN1A1fEv(ptr{{.*}} %this){{.*}} !kcfi_type ![[#TYPE3:]]
void f() {}
};
void test_member_call(void) {
void (A::* p)() = &A::f;
- // MEMBER-DAG: call void %[[#]](ptr{{.*}} [ "kcfi"(i32 [[#%d,HASH3:]]) ]
+ // MEMBER: call void %[[#]](ptr{{.*}} [ "kcfi"(i32 [[#%d,HASH3:]]) ]
(A().*p)();
}
+
+// MEMBER: define{{.*}} void @_ZN1A1fEv(ptr{{.*}} %this){{.*}} !kcfi_type ![[#TYPE3:]]
#endif
-// CHECK-DAG: ![[#]] = !{i32 4, !"kcfi", i32 1}
-// OFFSET-DAG: ![[#]] = !{i32 4, !"kcfi-offset", i32 3}
-// CHECK-DAG: ![[#TYPE]] = !{i32 [[#HASH]]}
-// CHECK-DAG: ![[#TYPE2]] = !{i32 [[#%d,HASH2:]]}
-// MEMBER-DAG: ![[#TYPE3]] = !{i32 [[#HASH3]]}
+// CHECK: ![[#]] = !{i32 4, !"kcfi", i32 1}
+//
+// OFFSET: ![[#]] = !{i32 4, !"kcfi-offset", i32 3}
+//
+// CHECK: ![[#TYPE]] = !{i32 [[#HASH]]}
+// CHECK: ![[#TYPE2]] = !{i32 [[#%d,HASH2:]]}
+// CHECK: ![[#ARG_TYPE]] = !{i32 [[#ARG_HASH]]}
+//
+// MEMBER: ![[#TYPE3]] = !{i32 [[#HASH3]]}
|
|
Unfortunately, the See the In hindsight, adding a test to LLVM about this real-world |
Okay, so what should we do about the testcase? I'm hitting it with the 'kcfi-salt' testcases, which are loosely based on |
You could hardcode the hash values in the test instead of just checking that they match? |
|
Okay, I'll leave the current |
The KCFI typeid may be negative, but will result in this type of bitcode:
The __kcfi_typeid_func value doesn't equal the metadata value. Therefore, we sign extend the typeid value rather than zero extend.
This also reorganizes the testcase to remove the "-DAG" checks, which are a bit confusing at first.