-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Prepare libcxx and libcxxabi for pointer field protection. #151651
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
base: users/pcc/spr/main.prepare-libcxx-and-libcxxabi-for-pointer-field-protection
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -484,8 +484,21 @@ typedef __char32_t char32_t; | |
# define _LIBCPP_EXCEPTIONS_SIG e | ||
# endif | ||
|
||
# if !_LIBCPP_HAS_EXCEPTIONS | ||
# define _LIBCPP_EXCEPTIONS_SIG n | ||
# else | ||
# define _LIBCPP_EXCEPTIONS_SIG e | ||
# endif | ||
|
||
# if defined(__POINTER_FIELD_PROTECTION__) | ||
# define _LIBCPP_PFP_SIG p | ||
# else | ||
# define _LIBCPP_PFP_SIG | ||
# endif | ||
|
||
# define _LIBCPP_ODR_SIGNATURE \ | ||
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_EXCEPTIONS_SIG), _LIBCPP_VERSION) | ||
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_EXCEPTIONS_SIG), _LIBCPP_PFP_SIG), \ | ||
_LIBCPP_VERSION) | ||
|
||
// This macro marks a symbol as being hidden from libc++'s ABI. This is achieved | ||
// on two levels: | ||
|
@@ -1262,6 +1275,14 @@ typedef __char32_t char32_t; | |
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 0 | ||
# endif | ||
|
||
# if defined(__POINTER_FIELD_PROTECTION__) | ||
# define _LIBCPP_PFP [[clang::pointer_field_protection]] | ||
# define _LIBCPP_NO_PFP [[clang::no_field_protection]] | ||
|
||
# else | ||
# define _LIBCPP_PFP | ||
# define _LIBCPP_NO_PFP | ||
# endif | ||
|
||
#endif // __cplusplus | ||
|
||
#endif // _LIBCPP___CONFIG |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -256,9 +256,12 @@ void unique_ptr_test() { | |
ComparePrettyPrintToRegex(std::move(forty_two), | ||
R"(std::unique_ptr<int> containing = {__ptr_ = 0x[a-f0-9]+})"); | ||
|
||
#if !defined(__POINTER_FIELD_PROTECTION__) | ||
// GDB doesn't know how to read PFP fields correctly yet. | ||
|
||
std::unique_ptr<int> this_is_null; | ||
ComparePrettyPrintToChars(std::move(this_is_null), | ||
R"(std::unique_ptr is nullptr)"); | ||
#endif | ||
} | ||
|
||
void bitset_test() { | ||
|
@@ -354,6 +357,8 @@ void map_test() { | |
} | ||
|
||
void multimap_test() { | ||
#if !defined(__POINTER_FIELD_PROTECTION__) | ||
// GDB doesn't know how to read PFP fields correctly yet. | ||
std::multimap<int, int> i_am_empty{}; | ||
ComparePrettyPrintToChars(i_am_empty, "std::multimap is empty"); | ||
|
||
|
@@ -369,6 +374,7 @@ void multimap_test() { | |
"std::multimap with 6 elements = " | ||
R"({[1] = "one", [1] = "ein", [1] = "bir", )" | ||
R"([2] = "two", [2] = "zwei", [3] = "three"})"); | ||
#endif | ||
} | ||
|
||
void queue_test() { | ||
|
@@ -441,13 +447,16 @@ void stack_test() { | |
} | ||
|
||
void multiset_test() { | ||
#if !defined(__POINTER_FIELD_PROTECTION__) | ||
// GDB doesn't know how to read PFP fields correctly yet. | ||
std::multiset<int> i_am_empty; | ||
ComparePrettyPrintToChars(i_am_empty, "std::multiset is empty"); | ||
|
||
std::multiset<std::string> one_two_three {"1:one", "2:two", "3:three", "1:one"}; | ||
ComparePrettyPrintToChars(one_two_three, | ||
"std::multiset with 4 elements = {" | ||
R"("1:one", "1:one", "2:two", "3:three"})"); | ||
#endif | ||
} | ||
|
||
void vector_test() { | ||
|
@@ -481,10 +490,13 @@ void vector_test() { | |
"std::vector of length " | ||
"3, capacity 3 = {5, 6, 7}"); | ||
|
||
#if !defined(__POINTER_FIELD_PROTECTION__) | ||
// GDB doesn't know how to read PFP fields correctly yet. | ||
std::vector<int, UncompressibleAllocator<int>> test3({7, 8}); | ||
ComparePrettyPrintToChars(std::move(test3), | ||
"std::vector of length " | ||
"2, capacity 2 = {7, 8}"); | ||
#endif | ||
} | ||
|
||
void set_iterator_test() { | ||
|
@@ -655,8 +667,11 @@ void shared_ptr_test() { | |
test0, | ||
R"(std::shared_ptr<int> count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); | ||
|
||
#if !defined(__POINTER_FIELD_PROTECTION__) | ||
// GDB doesn't know how to read PFP fields correctly yet. | ||
std::shared_ptr<const int> test3; | ||
ComparePrettyPrintToChars(test3, "std::shared_ptr is nullptr"); | ||
#endif | ||
} | ||
|
||
void streampos_test() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,12 @@ | |
# include <locale> | ||
#endif | ||
|
||
#if defined(__POINTER_FIELD_PROTECTION__) | ||
constexpr bool pfp_disabled = false; | ||
#else | ||
constexpr bool pfp_disabled = true; | ||
#endif | ||
|
||
|
||
static_assert(std::__libcpp_is_trivially_relocatable<char>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<int>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<double>::value, ""); | ||
|
@@ -68,8 +74,8 @@ static_assert(!std::__libcpp_is_trivially_relocatable<NonTrivialDestructor>::val | |
// ---------------------- | ||
|
||
// __split_buffer | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<int> >::value == pfp_disabled, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::__split_buffer<int, test_allocator<int> > >::value, ""); | ||
|
||
// standard library types | ||
|
@@ -82,7 +88,7 @@ static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr< | |
|
||
static_assert(std::__libcpp_is_trivially_relocatable<std::array<int, 1> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::array<NotTriviallyCopyable, 1> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value == pfp_disabled, ""); | ||
|
||
// basic_string | ||
#if !__has_feature(address_sanitizer) || !_LIBCPP_INSTRUMENTED_WITH_ASAN | ||
|
@@ -97,17 +103,17 @@ struct NotTriviallyRelocatableCharTraits : constexpr_char_traits<T> { | |
}; | ||
|
||
static_assert(std::__libcpp_is_trivially_relocatable< | ||
std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value, | ||
std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value == pfp_disabled, | ||
""); | ||
static_assert(std::__libcpp_is_trivially_relocatable< | ||
std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value, | ||
std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value == pfp_disabled, | ||
""); | ||
static_assert(std::__libcpp_is_trivially_relocatable< | ||
std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value, | ||
std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled, | ||
""); | ||
static_assert( | ||
std::__libcpp_is_trivially_relocatable< | ||
std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value, | ||
std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled, | ||
""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable< | ||
std::basic_string<char, std::char_traits<char>, test_allocator<char> > >::value, | ||
|
@@ -119,21 +125,21 @@ static_assert( | |
#endif | ||
|
||
// deque | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<int> >::value == pfp_disabled, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::deque<int, test_allocator<int> > >::value, ""); | ||
|
||
// exception_ptr | ||
#ifndef _LIBCPP_ABI_MICROSOFT // FIXME: Is this also the case on windows? | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value == pfp_disabled, ""); | ||
#endif | ||
|
||
// expected | ||
#if TEST_STD_VER >= 23 | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, int> >::value); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, int>>::value); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, std::unique_ptr<int>>>::value); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, std::unique_ptr<int>>>::value); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, int> >::value == pfp_disabled); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, int>>::value == pfp_disabled); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, std::unique_ptr<int>>>::value == pfp_disabled); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, std::unique_ptr<int>>>::value == pfp_disabled); | ||
|
||
static_assert(!std::__libcpp_is_trivially_relocatable<std::expected<int, NotTriviallyCopyable>>::value); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::expected<NotTriviallyCopyable, int>>::value); | ||
|
@@ -143,42 +149,42 @@ static_assert( | |
|
||
// locale | ||
#ifndef TEST_HAS_NO_LOCALIZATION | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value == pfp_disabled, ""); | ||
#endif | ||
|
||
// optional | ||
#if TEST_STD_VER >= 17 | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::optional<int>>::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::optional<NotTriviallyCopyable>>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::optional<std::unique_ptr<int>>>::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::optional<std::unique_ptr<int>>>::value == pfp_disabled, ""); | ||
#endif // TEST_STD_VER >= 17 | ||
|
||
// pair | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, int> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<int, NotTriviallyCopyable> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, NotTriviallyCopyable> >::value, | ||
""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<std::unique_ptr<int>, std::unique_ptr<int> > >::value, | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<std::unique_ptr<int>, std::unique_ptr<int> > >::value == pfp_disabled, | ||
""); | ||
|
||
// shared_ptr | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
|
||
// tuple | ||
#if TEST_STD_VER >= 11 | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<> >::value, ""); | ||
|
||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int> > >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int> > >::value == pfp_disabled, ""); | ||
|
||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int, int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int, int> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, int> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<int, NotTriviallyCopyable> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, NotTriviallyCopyable> >::value, | ||
""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int>, std::unique_ptr<int> > >::value, | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int>, std::unique_ptr<int> > >::value == pfp_disabled, | ||
""); | ||
#endif // TEST_STD_VER >= 11 | ||
|
||
|
@@ -203,9 +209,9 @@ struct NotTriviallyRelocatablePointer { | |
void operator()(T*); | ||
}; | ||
|
||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[]> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int> >::value == pfp_disabled, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[]> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int, NotTriviallyRelocatableDeleter> >::value, | ||
""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], NotTriviallyRelocatableDeleter> >::value, | ||
|
@@ -219,23 +225,23 @@ static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], Not | |
#if TEST_STD_VER >= 17 | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<int> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int> > >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int> > >::value == pfp_disabled, ""); | ||
|
||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<int, int> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable, int> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<int, NotTriviallyCopyable> >::value, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable, NotTriviallyCopyable> >::value, | ||
""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int>, std::unique_ptr<int> > >::value, | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int>, std::unique_ptr<int> > >::value == pfp_disabled, | ||
""); | ||
#endif // TEST_STD_VER >= 17 | ||
|
||
// vector | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::vector<int> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::vector<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::vector<int> >::value == pfp_disabled, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::vector<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
static_assert(!std::__libcpp_is_trivially_relocatable<std::vector<int, test_allocator<int> > >::value, ""); | ||
|
||
// weak_ptr | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::weak_ptr<NotTriviallyCopyable> >::value, ""); | ||
static_assert(std::__libcpp_is_trivially_relocatable<std::weak_ptr<NotTriviallyCopyable> >::value == pfp_disabled, ""); | ||
|
||
// TODO: Mark all the trivially relocatable STL types as such |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,4 +109,14 @@ | |
# define _LIBCXXABI_NOEXCEPT noexcept | ||
#endif | ||
|
||
#if defined(_LIBCXXABI_COMPILER_CLANG) | ||
# if defined(__POINTER_FIELD_PROTECTION__) | ||
# define _LIBCXXABI_NO_PFP [[clang::no_field_protection]] | ||
# else | ||
# define _LIBCXXABI_NO_PFP | ||
# endif | ||
#else | ||
# define _LIBCXXABI_NO_PFP | ||
#endif | ||
|
||
|
||
#endif // ____CXXABI_CONFIG_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that pfp changes the layout of certain types? Why should there be an ABI tag for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the in-memory pointer format changes so it's effectively a layout (ABI) change. Therefore we need an ABI tag change to detect/prevent linking against mismatching ABIs. This was requested by @mordante in #133538.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's only for ceses where we want different TUs to link together. Since PFP changes the layout of types that's not something we want users to do, which in turn means that we don't want to make it visible in the ABI tag. We should instead change the whole inline namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I removed this logic and added CMake logic to modify the namespace name if PFP is enabled.