From 5f931c3f146b330fc37c354e13dafa7c7235d3c9 Mon Sep 17 00:00:00 2001 From: Brian Favela Date: Fri, 30 Jun 2023 13:15:17 -0400 Subject: [PATCH] Add link-time detection of LLVM_ABI_BREAKING_CHECKS mismatch (#5380) The macro LLVM_ENABLE_ABI_BREAKING_CHECKS is moved to a new header abi-breaking.h, from llvm-config.h. Only headers that are using the macro are including this new header. LLVM will define a symbol, either EnableABIBreakingChecks or DisableABIBreakingChecks depending on the configuration setting for LLVM_ABI_BREAKING_CHECKS. The abi-breaking.h header will add weak references to these symbols in every clients that includes this header. This should ensure that a mismatch triggers a link failure (or a load time failure for DSO). On MSVC, the pragma "detect_mismatch" is used instead. Differential Revision: https://reviews.llvm.org/D26876 llvm-svn: 288082 Co-authored-by: Mehdi Amini --- CMakeLists.txt | 3 ++ include/llvm/ADT/EpochTracker.h | 1 + include/llvm/ADT/ilist_node.h | 2 ++ include/llvm/Config/abi-breaking.h.cmake | 39 ++++++++++++++++++++++++ include/llvm/Config/config.h.cmake | 4 --- include/llvm/Config/llvm-config.h.cmake | 4 --- include/llvm/Support/ErrorHandling.h | 1 + lib/Support/ErrorHandling.cpp | 15 +++++++++ 8 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 include/llvm/Config/abi-breaking.h.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 314fd6c557..c28b364fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -564,6 +564,9 @@ configure_file( configure_file( ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/llvm-config.h.cmake ${LLVM_INCLUDE_DIR}/llvm/Config/llvm-config.h) +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/abi-breaking.h.cmake + ${LLVM_INCLUDE_DIR}/llvm/Config/abi-breaking.h) configure_file( ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/DataTypes.h.cmake ${LLVM_INCLUDE_DIR}/llvm/Support/DataTypes.h) diff --git a/include/llvm/ADT/EpochTracker.h b/include/llvm/ADT/EpochTracker.h index 582d58179d..724d951768 100644 --- a/include/llvm/ADT/EpochTracker.h +++ b/include/llvm/ADT/EpochTracker.h @@ -16,6 +16,7 @@ #ifndef LLVM_ADT_EPOCH_TRACKER_H #define LLVM_ADT_EPOCH_TRACKER_H +#include "llvm/Config/abi-breaking.h" #include "llvm/Config/llvm-config.h" #include diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index f191139fec..01f0fd649c 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -15,6 +15,8 @@ #ifndef LLVM_ADT_ILIST_NODE_H #define LLVM_ADT_ILIST_NODE_H +#include "llvm/Config/abi-breaking.h" + namespace llvm { template diff --git a/include/llvm/Config/abi-breaking.h.cmake b/include/llvm/Config/abi-breaking.h.cmake new file mode 100644 index 0000000000..f923a1e2f4 --- /dev/null +++ b/include/llvm/Config/abi-breaking.h.cmake @@ -0,0 +1,39 @@ +/*===------- llvm/Config/abi-breaking.h - llvm configuration -------*- C -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +/* This file controls the C++ ABI break introduced in LLVM public header. */ + +#ifndef LLVM_ABI_BREAKING_CHECKS_H +#define LLVM_ABI_BREAKING_CHECKS_H + +/* Define to enable checks that alter the LLVM C++ ABI */ +#cmakedefine01 LLVM_ENABLE_ABI_BREAKING_CHECKS + +// ABI_BREAKING_CHECKS protection: provides link-time failure when clients build +// mismatch with LLVM +#if defined(_MSC_VER) +// Use pragma with MSVC +#define LLVM_XSTR(s) LLVM_STR(s) +#define LLVM_STR(s) #s +#pragma detect_mismatch("LLVM_ENABLE_ABI_BREAKING_CHECKS", LLVM_XSTR(LLVM_ENABLE_ABI_BREAKING_CHECKS)) +#undef LLVM_XSTR +#undef LLVM_STR +#elif defined(__cplusplus) +namespace llvm { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +extern int EnableABIBreakingChecks; +__attribute__((weak, visibility ("hidden"))) int *VerifyEnableABIBreakingChecks = &EnableABIBreakingChecks; +#else +extern int DisableABIBreakingChecks; +__attribute__((weak, visibility ("hidden"))) int *VerifyDisableABIBreakingChecks = &DisableABIBreakingChecks; +#endif +} +#endif // _MSC_VER + +#endif diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index b8294cf61c..047c8823d2 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -432,10 +432,6 @@ /* Installation directory for documentation */ #cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" -/* Define if LLVM is built with asserts and checks that change the layout of - client-visible data structures. */ -#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS - /* Define if threads enabled */ #cmakedefine01 LLVM_ENABLE_THREADS diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index e0f30678c0..d54003d993 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -29,10 +29,6 @@ /* Installation directory for documentation */ #cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" -/* Define if LLVM is built with asserts and checks that change the layout of - client-visible data structures. */ -#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS - /* Define if threads enabled */ #cmakedefine01 LLVM_ENABLE_THREADS diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index 6d89e57917..d7d9b6389e 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" +#include "llvm/Config/abi-breaking.h" #include namespace llvm { diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp index 19c47ffc08..5d715c4881 100644 --- a/lib/Support/ErrorHandling.cpp +++ b/lib/Support/ErrorHandling.cpp @@ -226,3 +226,18 @@ std::error_code llvm::mapWindowsError(unsigned EV) { } #endif + +#ifndef _MSC_VER +namespace llvm { + +// One of these two variables will be referenced by a symbol defined in +// llvm-config.h. We provide a link-time (or load time for DSO) failure when +// there is a mismatch in the build configuration of the API client and LLVM. +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +int EnableABIBreakingChecks; +#else +int DisableABIBreakingChecks; +#endif + +} // end namespace llvm +#endif