diff options
author | Qinkun Bao <qinkun@google.com> | 2025-09-10 18:04:34 -0700 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2025-09-10 18:04:34 -0700 |
commit | 1af2c42252c0dbc3f5c5e519f1378882ccf8d9a0 (patch) | |
tree | 88ad91756610c282ceb4a244696fa7988b3f3a75 | |
parent | ceca63dce9bf61599b9df1f124219f5391c1c5da (diff) | |
parent | 1c3ec87337de204b651953da8df731c90fef26c9 (diff) | |
download | llvm-users/pcc/spr/implement-a-simple-e2e-test-for-pfp.zip llvm-users/pcc/spr/implement-a-simple-e2e-test-for-pfp.tar.gz llvm-users/pcc/spr/implement-a-simple-e2e-test-for-pfp.tar.bz2 |
Created using spr 1.3.6-beta.1
-rw-r--r-- | libcxx/docs/CodingGuidelines.rst | 13 | ||||
-rw-r--r-- | libcxx/include/__config | 10 | ||||
-rw-r--r-- | libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp | 18 | ||||
-rw-r--r-- | libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp | 71 | ||||
-rw-r--r-- | libcxx/utils/libcxx/test/params.py | 1 | ||||
-rw-r--r-- | libcxxabi/include/__cxxabi_config.h | 8 | ||||
-rw-r--r-- | libcxxabi/test/CMakeLists.txt | 4 | ||||
-rw-r--r-- | llvm/docs/LangRef.rst | 12 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 3 | ||||
-rw-r--r-- | llvm/test/Assembler/invalid-ptrauth-const6.ll | 6 | ||||
-rw-r--r-- | llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll (renamed from llvm/test/Transforms/Util/phi-protected-field-ptr.ll) | 0 |
13 files changed, 86 insertions, 64 deletions
diff --git a/libcxx/docs/CodingGuidelines.rst b/libcxx/docs/CodingGuidelines.rst index ff312d1..0a1ab13 100644 --- a/libcxx/docs/CodingGuidelines.rst +++ b/libcxx/docs/CodingGuidelines.rst @@ -195,3 +195,16 @@ prevent compilers from generating said debug information. Aliases inside type tr should be annotated for the same reason. This is enforced by the clang-tidy check ``libcpp-nodebug-on-aliases``. + +Pointer field protection +======================== + +To improve the effectiveness of Clang's `pointer field protection +<https://clang.llvm.org/docs/StructureProtection.html>`_ feature, +commonly used vocabulary types with pointer fields are marked with the +``_LIBCPP_PFP`` attribute, to give Clang permission to use PFP to protect +their pointer fields. Newly added vocabulary types should be marked with +this attribute if they contain pointer fields. + +For the time being, PFP is an experimental feature, so our criteria for +marking types with ``_LIBCPP_PFP`` may change. diff --git a/libcxx/include/__config b/libcxx/include/__config index 5f6dc79..a54eba27 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1275,12 +1275,16 @@ typedef __char32_t char32_t; # define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 0 # endif +# if __has_cpp_attribute(_Clang::__no_field_protection__) +# define _LIBCPP_NO_PFP [[_Clang::__no_field_protection__]] +# else +# define _LIBCPP_NO_PFP +# endif + # if defined(__POINTER_FIELD_PROTECTION__) -# define _LIBCPP_PFP [[clang::pointer_field_protection]] -# define _LIBCPP_NO_PFP [[clang::no_field_protection]] +# define _LIBCPP_PFP [[_Clang::__pointer_field_protection__]] # else # define _LIBCPP_PFP -# define _LIBCPP_NO_PFP # endif #endif // __cplusplus diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp index a7db822..592bacf 100644 --- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp +++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp @@ -24,6 +24,9 @@ // This test doesn't work as such on Windows. // UNSUPPORTED: windows +// GDB doesn't know how to read PFP fields correctly yet. +// UNSUPPORTED: pfp + // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags} // Ensure locale-independence for unicode tests. // RUN: env LANG=en_US.UTF-8 %{gdb} -nx -batch -iex "set autoload off" -ex "source %S/../../../utils/gdb/libcxx/printers.py" -ex "python register_libcxx_printer_loader()" -ex "source %S/gdb_pretty_printer_test.py" %t.exe @@ -256,12 +259,9 @@ 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() { @@ -357,8 +357,6 @@ 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"); @@ -374,7 +372,6 @@ 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() { @@ -447,8 +444,6 @@ 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"); @@ -456,7 +451,6 @@ void multiset_test() { ComparePrettyPrintToChars(one_two_three, "std::multiset with 4 elements = {" R"("1:one", "1:one", "2:two", "3:three"})"); -#endif } void vector_test() { @@ -490,13 +484,10 @@ 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() { @@ -667,11 +658,8 @@ 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() { diff --git a/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp index 847ef6f..97a0e67 100644 --- a/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp +++ b/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp @@ -6,6 +6,9 @@ // //===----------------------------------------------------------------------===// +// With PFP we return different values for __libcpp_is_trivially_relocatable. +// UNSUPPORTED: pfp + #include <__type_traits/is_trivially_relocatable.h> #include <array> #include <deque> @@ -26,12 +29,6 @@ # 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, ""); @@ -74,8 +71,8 @@ static_assert(!std::__libcpp_is_trivially_relocatable<NonTrivialDestructor>::val // ---------------------- // __split_buffer -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> >::value, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value, ""); static_assert(!std::__libcpp_is_trivially_relocatable<std::__split_buffer<int, test_allocator<int> > >::value, ""); // standard library types @@ -88,7 +85,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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value, ""); // basic_string #if !__has_feature(address_sanitizer) || !_LIBCPP_INSTRUMENTED_WITH_ASAN @@ -103,17 +100,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 == pfp_disabled, + std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value, ""); static_assert(std::__libcpp_is_trivially_relocatable< - std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value == pfp_disabled, + std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value, ""); static_assert(std::__libcpp_is_trivially_relocatable< - std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled, + std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value, ""); static_assert( std::__libcpp_is_trivially_relocatable< - std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled, + std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value, ""); static_assert(!std::__libcpp_is_trivially_relocatable< std::basic_string<char, std::char_traits<char>, test_allocator<char> > >::value, @@ -125,21 +122,21 @@ static_assert( #endif // deque -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> >::value, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value, ""); 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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value, ""); #endif // expected #if TEST_STD_VER >= 23 -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, 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, NotTriviallyCopyable>>::value); static_assert(!std::__libcpp_is_trivially_relocatable<std::expected<NotTriviallyCopyable, int>>::value); @@ -149,42 +146,42 @@ static_assert( // locale #ifndef TEST_HAS_NO_LOCALIZATION -static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value, ""); #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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::optional<std::unique_ptr<int>>>::value, ""); #endif // TEST_STD_VER >= 17 // pair -static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value, ""); 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 == pfp_disabled, +static_assert(std::__libcpp_is_trivially_relocatable<std::pair<std::unique_ptr<int>, std::unique_ptr<int> > >::value, ""); // shared_ptr -static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviallyCopyable> >::value == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviallyCopyable> >::value, ""); // 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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value, ""); 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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<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<int, int> >::value, ""); 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 == pfp_disabled, +static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int>, std::unique_ptr<int> > >::value, ""); #endif // TEST_STD_VER >= 11 @@ -209,9 +206,9 @@ struct NotTriviallyRelocatablePointer { void operator()(T*); }; -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> >::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, NotTriviallyRelocatableDeleter> >::value, ""); static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], NotTriviallyRelocatableDeleter> >::value, @@ -225,23 +222,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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int> > >::value, ""); 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 == pfp_disabled, +static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int>, std::unique_ptr<int> > >::value, ""); #endif // TEST_STD_VER >= 17 // vector -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> >::value, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::vector<NotTriviallyCopyable> >::value, ""); 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 == pfp_disabled, ""); +static_assert(std::__libcpp_is_trivially_relocatable<std::weak_ptr<NotTriviallyCopyable> >::value, ""); // TODO: Mark all the trivially relocatable STL types as such diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 13315b4..2bf4f70 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -355,6 +355,7 @@ DEFAULT_PARAMETERS = [ AddCompileFlag("--rtlib=compiler-rt"), AddLinkFlag("--rtlib=compiler-rt"), AddLinkFlag("--unwindlib=libunwind"), + AddFeature("pfp"), ], ), Parameter( diff --git a/libcxxabi/include/__cxxabi_config.h b/libcxxabi/include/__cxxabi_config.h index 925cc41..c8c3b18 100644 --- a/libcxxabi/include/__cxxabi_config.h +++ b/libcxxabi/include/__cxxabi_config.h @@ -109,12 +109,8 @@ # 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 +#if defined(__POINTER_FIELD_PROTECTION__) +# define _LIBCXXABI_NO_PFP [[_Clang::__no_field_protection__]] #else # define _LIBCXXABI_NO_PFP #endif diff --git a/libcxxabi/test/CMakeLists.txt b/libcxxabi/test/CMakeLists.txt index 447b0fc..9a87a90 100644 --- a/libcxxabi/test/CMakeLists.txt +++ b/libcxxabi/test/CMakeLists.txt @@ -80,7 +80,9 @@ if (LLVM_USE_SANITIZER) serialize_lit_string_param(SERIALIZED_LIT_PARAMS use_sanitizer "${LLVM_USE_SANITIZER}") endif() -serialize_lit_string_param(SERIALIZED_LIT_PARAMS pfp "${LIBCXX_PFP}") +if (DEFINED LIBCXX_PFP) + serialize_lit_string_param(SERIALIZED_LIT_PARAMS pfp "${LIBCXX_PFP}") +endif() if (CMAKE_CXX_COMPILER_TARGET) serialize_lit_string_param(SERIALIZED_LIT_PARAMS target_triple "${CMAKE_CXX_COMPILER_TARGET}") diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 094e5f0..e49d7bb 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -3092,13 +3092,16 @@ A "convergencectrl" operand bundle is only valid on a ``convergent`` operation. When present, the operand bundle must contain exactly one value of token type. See the :doc:`ConvergentOperations` document for details. +.. _deactivationsymbol: + Deactivation Symbol Operand Bundles ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A ``"deactivation-symbol"`` operand bundle is valid on the following instructions (AArch64 only): -- Call to a normal function with ``notail`` attribute. +- Call to a normal function with ``notail`` attribute and a first argument and + return value of type ``ptr``. - Call to ``llvm.ptrauth.sign`` or ``llvm.ptrauth.auth`` intrinsics. This operand bundle specifies that if the deactivation symbol is defined @@ -5148,7 +5151,7 @@ need to refer to the actual function body. Pointer Authentication Constants -------------------------------- -``ptrauth (ptr CST, i32 KEY[, i64 DISC[, ptr ADDRDISC]?]?)`` +``ptrauth (ptr CST, i32 KEY[, i64 DISC[, ptr ADDRDISC[, ptr DS]?]?]?)`` A '``ptrauth``' constant represents a pointer with a cryptographic authentication signature embedded into some bits, as described in the @@ -5177,6 +5180,11 @@ Otherwise, the expression is equivalent to: %tmp2 = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr CST to i64), i32 KEY, i64 %tmp1) %val = inttoptr i64 %tmp2 to ptr +If the deactivation symbol operand ``DS`` has a non-null value, +the semantics are as if a :ref:`deactivation-symbol operand bundle +<deactivationsymbol>` were added to the ``llvm.ptrauth.sign`` intrinsic +calls above, with ``DS`` as the only operand. + .. _constantexprs: Constant Expressions diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 045ed20..a7fce4f 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1613,6 +1613,9 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID, ConstOps.size() > 4 ? ConstOps[4] : ConstantPointerNull::get(cast<PointerType>( ConstOps[3]->getType())); + if (!DeactivationSymbol->getType()->isPointerTy()) + return error( + "ptrauth deactivation symbol operand must be a pointer"); C = ConstantPtrAuth::get(ConstOps[0], Key, Disc, ConstOps[3], DeactivationSymbol); diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 5eacc7a..53b292f 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2082,6 +2082,7 @@ ConstantPtrAuth::ConstantPtrAuth(Constant *Ptr, ConstantInt *Key, assert(Key->getBitWidth() == 32); assert(Disc->getBitWidth() == 64); assert(AddrDisc->getType()->isPointerTy()); + assert(DeactivationSymbol->getType()->isPointerTy()); setOperand(0, Ptr); setOperand(1, Key); setOperand(2, Disc); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 9e44dfb..a53ba17 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2632,6 +2632,9 @@ void Verifier::visitConstantPtrAuth(const ConstantPtrAuth *CPA) { Check(CPA->getDiscriminator()->getBitWidth() == 64, "signed ptrauth constant discriminator must be i64 constant integer"); + Check(CPA->getDeactivationSymbol()->getType()->isPointerTy(), + "signed ptrauth constant deactivation symbol must be a pointer"); + Check(isa<GlobalValue>(CPA->getDeactivationSymbol()) || CPA->getDeactivationSymbol()->isNullValue(), "signed ptrauth constant deactivation symbol must be a global value " diff --git a/llvm/test/Assembler/invalid-ptrauth-const6.ll b/llvm/test/Assembler/invalid-ptrauth-const6.ll new file mode 100644 index 0000000..6e8e1d3 --- /dev/null +++ b/llvm/test/Assembler/invalid-ptrauth-const6.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as < %s 2>&1 | FileCheck %s + +@var = global i32 0 + +; CHECK: error: constant ptrauth deactivation symbol must be a pointer +@ptr = global ptr ptrauth (ptr @var, i32 0, i64 65535, ptr null, i64 0) diff --git a/llvm/test/Transforms/Util/phi-protected-field-ptr.ll b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll index bf60de44..bf60de44 100644 --- a/llvm/test/Transforms/Util/phi-protected-field-ptr.ll +++ b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll |