diff --git a/compiler-rt/lib/cfi/CMakeLists.txt b/compiler-rt/lib/cfi/CMakeLists.txt index cf8479d39c25e09a0fbdac54ea9b029d28d717ae..2a69b455bba9bcc2648d746ffb259b6d950f8889 100644 --- a/compiler-rt/lib/cfi/CMakeLists.txt +++ b/compiler-rt/lib/cfi/CMakeLists.txt @@ -5,6 +5,10 @@ if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetB cfi.cpp ) + set(CFI_FAIL_REPORT_SOURCES + cfi_fail_report.cpp + ) + include_directories(..) set(CFI_CFLAGS @@ -40,6 +44,12 @@ if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetB RTUbsan CFLAGS ${CFI_CFLAGS} ${CFI_DIAG_CFLAGS} PARENT_TARGET cfi) + add_compiler_rt_runtime(clang_rt.cfi_fail_report + STATIC + ARCHS ${arch} + SOURCES ${CFI_FAIL_REPORT_SOURCES} + CFLAGS ${CFI_CFLAGS} + PARENT_TARGET cfi) endforeach() endif() diff --git a/compiler-rt/lib/cfi/cfi_fail_report.cpp b/compiler-rt/lib/cfi/cfi_fail_report.cpp new file mode 100644 index 0000000000000000000000000000000000000000..083707da3a24c1534e06dfdfce5638b11ef504f3 --- /dev/null +++ b/compiler-rt/lib/cfi/cfi_fail_report.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#if defined(__aarch64__) && defined(__OHOS__) +#include + +extern "C" _Noreturn void __cfi_fail_report(void); +/** + * @brief Retrieves the current value of the x1 register on AArch64. + * + * This function is used in CFI checks to obtain the function address + * stored in the x1 register during calls involving function pointers, + * virtual calls (vcall), and non-virtual calls (nvcall) using vtable addresses. + * + * @return Value of the x1 register. + */ +uint64_t fetch_function_address(void) { + uint64_t val; + __asm__ __volatile__( + "mov %0, x1" + : "=r" (val) + : + : "memory" + ); + return val; +} + +_Noreturn void __cfi_fail_report(void) { + uint64_t function_address = fetch_function_address(); + char message[512]; + snprintf(message, sizeof(message), + "CFI check failed. Function Address: 0x%" PRIx64, function_address); + set_fatal_message(message); + abort(); +} +#else +extern "C" _Noreturn void __cfi_fail_report(void) { + abort(); +} +#endif