[Lldb-commits] [clang] [lldb] [PAC][lldb][Dwarf] Support `__ptrauth`-qualified types in user expressions (PR #84387)

Daniil Kovalev via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 28 03:04:49 PDT 2024


https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/84387

>From 728f5644aebfafd2114e7e47a9b83ef057423997 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Tue, 20 Feb 2024 10:57:54 -0800
Subject: [PATCH 01/10] Upstream ptrauth changes to DWARFASTParserClang

---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 54d06b1115a229..67fe830e1aa70d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -495,6 +495,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
   case DW_TAG_const_type:
   case DW_TAG_restrict_type:
   case DW_TAG_volatile_type:
+  case DW_TAG_LLVM_ptrauth_type:
   case DW_TAG_atomic_type:
   case DW_TAG_unspecified_type: {
     type_sp = ParseTypeModifier(sc, die, attrs);
@@ -676,6 +677,62 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
   case DW_TAG_volatile_type:
     encoding_data_type = Type::eEncodingIsVolatileUID;
     break;
+  case DW_TAG_LLVM_ptrauth_type: {
+    DWARFDIE ptr_die = die.GetReferencedDIE(DW_AT_type);
+    // FIXME: Fully resolving the type here may affect performance.
+    Type *res_type = dwarf->ResolveType(ptr_die);
+    if (!res_type)
+      break;
+    attrs.type.Clear();
+    encoding_data_type = Type::eEncodingIsUID;
+    resolve_state = Type::ResolveState::Full;
+
+    // Apply the ptrauth qualifier to the resolved type.
+    auto *ptr_type =
+        (clang::Type *)res_type->GetForwardCompilerType().GetOpaqueQualType();
+    auto getAttr = [&](llvm::dwarf::Attribute Attr, unsigned defaultValue = 0) {
+      return die.GetAttributeValueAsUnsigned(Attr, defaultValue);
+    };
+    const unsigned key = getAttr(DW_AT_LLVM_ptrauth_key);
+    const bool addr_disc = getAttr(DW_AT_LLVM_ptrauth_address_discriminated);
+    const unsigned extra = getAttr(DW_AT_LLVM_ptrauth_extra_discriminator);
+    const bool isapointer = getAttr(DW_AT_LLVM_ptrauth_isa_pointer);
+    const bool authenticates_null_values =
+        getAttr(DW_AT_LLVM_ptrauth_authenticates_null_values, 0);
+    const bool is_restricted_integral = !ptr_type->isPointerType();
+    const unsigned authentication_mode_int = getAttr(
+        DW_AT_LLVM_ptrauth_authentication_mode,
+        static_cast<unsigned>(clang::PointerAuthenticationMode::SignAndAuth));
+    clang::PointerAuthenticationMode authentication_mode =
+        clang::PointerAuthenticationMode::SignAndAuth;
+    if (authentication_mode_int >=
+            static_cast<unsigned>(clang::PointerAuthenticationMode::None) &&
+        authentication_mode_int <=
+            static_cast<unsigned>(
+                clang::PointerAuthenticationMode::SignAndAuth)) {
+      authentication_mode = static_cast<clang::PointerAuthenticationMode>(
+          authentication_mode_int);
+    } else {
+      dwarf->GetObjectFile()->GetModule()->ReportError(
+          "[{0:x16}]: invalid pointer authentication mode method {1:x4}",
+          die.GetOffset(), authentication_mode_int);
+    }
+
+    // FIXME: Use these variables when PointerAuthQualifier is more complete
+    // upstream.
+    (void)is_restricted_integral;
+
+    clang::Qualifiers qualifiers;
+    auto ptr_auth = clang::PointerAuthQualifier::Create(
+        key, addr_disc, extra, authentication_mode, isapointer,
+        authenticates_null_values);
+    qualifiers.setPointerAuth(ptr_auth);
+    auto &ctx = m_ast.getASTContext();
+    auto qual_type = ctx.getQualifiedType(ptr_type, qualifiers);
+    clang_type =
+        CompilerType(m_ast.weak_from_this(), qual_type.getAsOpaquePtr());
+    break;
+  }
   case DW_TAG_atomic_type:
     encoding_data_type = Type::eEncodingIsAtomicUID;
     break;

>From 8aa1ba0b05362b8960faac1945bb25c68ecb4b98 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 16:34:09 +0300
Subject: [PATCH 02/10] [PAC][lldb] Use `eEncodingIsLLVMPtrAuthUID` for
 `__ptrauth`-qualified types

---
 lldb/include/lldb/Symbol/Type.h                           | 4 +++-
 .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp      | 2 +-
 lldb/source/Symbol/Type.cpp                               | 8 +++++++-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index acd1a769f13cd6..d55280b58bc4f7 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -401,7 +401,9 @@ class Type : public std::enable_shared_from_this<Type>, public UserID {
     /// This type is the type whose UID is m_encoding_uid as an atomic type.
     eEncodingIsAtomicUID,
     /// This type is the synthetic type whose UID is m_encoding_uid.
-    eEncodingIsSyntheticUID
+    eEncodingIsSyntheticUID,
+    /// This type is a signed pointer.
+    eEncodingIsLLVMPtrAuthUID
   };
 
   enum class ResolveState : unsigned char {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 67fe830e1aa70d..1e13962aadd43e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -684,7 +684,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
     if (!res_type)
       break;
     attrs.type.Clear();
-    encoding_data_type = Type::eEncodingIsUID;
+    encoding_data_type = Type::eEncodingIsLLVMPtrAuthUID;
     resolve_state = Type::ResolveState::Full;
 
     // Apply the ptrauth qualifier to the resolved type.
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 6069d066eaf66b..60ad7bc029eb17 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -355,6 +355,9 @@ void Type::GetDescription(Stream *s, lldb::DescriptionLevel level,
     case eEncodingIsSyntheticUID:
       s->PutCString(" (synthetic type)");
       break;
+    case eEncodingIsLLVMPtrAuthUID:
+      s->PutCString(" (ptrauth type)");
+      break;
     }
   }
 }
@@ -416,6 +419,8 @@ void Type::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
     case eEncodingIsSyntheticUID:
       s->PutCString(" (synthetic type)");
       break;
+    case eEncodingIsLLVMPtrAuthUID:
+      s->PutCString(" (ptrauth type)");
     }
   }
 
@@ -477,7 +482,8 @@ std::optional<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) {
     // If we are a pointer or reference, then this is just a pointer size;
     case eEncodingIsPointerUID:
     case eEncodingIsLValueReferenceUID:
-    case eEncodingIsRValueReferenceUID: {
+    case eEncodingIsRValueReferenceUID:
+    case eEncodingIsLLVMPtrAuthUID: {
       if (ArchSpec arch = m_symbol_file->GetObjectFile()->GetArchitecture()) {
         m_byte_size = arch.GetAddressByteSize();
         m_byte_size_has_value = true;

>From 013a85a11493057b632d4492dacb22d53dae4481 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 16:41:51 +0300
Subject: [PATCH 03/10] [PAC][lldb] Support `__ptrauth` types in `CompilerType`
 and `TypeSystemClang`

---
 lldb/include/lldb/Symbol/CompilerType.h       | 13 +++++
 lldb/include/lldb/Symbol/TypeSystem.h         | 17 +++++++
 .../TypeSystem/Clang/TypeSystemClang.cpp      | 47 +++++++++++++++++++
 .../TypeSystem/Clang/TypeSystemClang.h        |  8 ++++
 lldb/source/Symbol/CompilerType.cpp           | 32 +++++++++++++
 lldb/source/Symbol/TypeSystem.cpp             |  7 +++
 6 files changed, 124 insertions(+)

diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 414c44275aaafc..a0ed6999548f87 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -262,6 +262,12 @@ class CompilerType {
   size_t GetPointerByteSize() const;
   /// \}
 
+  unsigned GetPtrAuthKey() const;
+
+  unsigned GetPtrAuthDiscriminator() const;
+
+  bool GetPtrAuthAddressDiversity() const;
+
   /// Accessors.
   /// \{
 
@@ -369,6 +375,13 @@ class CompilerType {
 
   /// Create related types using the current type's AST
   CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const;
+
+  /// Return a new CompilerType adds a ptrauth modifier with given parameters to
+  /// this type if this type is valid and the type system supports ptrauth
+  /// modifiers, else return an invalid type. Note that this does not check if
+  /// this type is a pointer.
+  CompilerType AddPtrAuthModifier(unsigned key, bool isAddressDiscriminated,
+                                  unsigned extraDiscriminator) const;
   /// \}
 
   /// Exploring the type.
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 63829131556e87..ecb92c62821dcd 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -216,6 +216,16 @@ class TypeSystem : public PluginInterface,
 
   virtual uint32_t GetPointerByteSize() = 0;
 
+  // TODO: are we allowed to insert virtual functions in the middle of the class
+  // interface and break ABI?
+  virtual unsigned GetPtrAuthKey(lldb::opaque_compiler_type_t type) = 0;
+
+  virtual unsigned
+  GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) = 0;
+
+  virtual bool
+  GetPtrAuthAddressDiversity(lldb::opaque_compiler_type_t type) = 0;
+
   // Accessors
 
   virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type,
@@ -280,6 +290,13 @@ class TypeSystem : public PluginInterface,
 
   virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
 
+  // TODO: are we allowed to insert virtual functions in the middle of the class
+  // interface and break ABI?
+  virtual CompilerType AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
+                                          unsigned key,
+                                          bool isAddressDiscriminated,
+                                          unsigned extraDiscriminator);
+
   /// \param opaque_payload      The m_payload field of Type, which may
   /// carry TypeSystem-specific extra information.
   virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 51ab13108feb3a..3e8da08a915982 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2975,6 +2975,35 @@ bool TypeSystemClang::IsCStringType(lldb::opaque_compiler_type_t type,
   return false;
 }
 
+unsigned TypeSystemClang::GetPtrAuthKey(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    if (auto pointer_auth = qual_type.getPointerAuth())
+      return pointer_auth.getKey();
+  }
+  return 0;
+}
+
+unsigned
+TypeSystemClang::GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    if (auto pointer_auth = qual_type.getPointerAuth())
+      return pointer_auth.getExtraDiscriminator();
+  }
+  return 0;
+}
+
+bool TypeSystemClang::GetPtrAuthAddressDiversity(
+    lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    if (auto pointer_auth = qual_type.getPointerAuth())
+      return pointer_auth.isAddressDiscriminated();
+  }
+  return false;
+}
+
 bool TypeSystemClang::IsFunctionType(lldb::opaque_compiler_type_t type) {
   auto isFunctionType = [&](clang::QualType qual_type) {
     return qual_type->isFunctionType();
@@ -4560,6 +4589,24 @@ TypeSystemClang::AddConstModifier(lldb::opaque_compiler_type_t type) {
   return CompilerType();
 }
 
+CompilerType
+TypeSystemClang::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
+                                    unsigned key, bool isAddressDiscriminated,
+                                    unsigned extraDiscriminator) {
+  if (type) {
+    clang::ASTContext &clang_ast = getASTContext();
+    auto pauth = PointerAuthQualifier::Create(
+        key, isAddressDiscriminated, extraDiscriminator,
+        PointerAuthenticationMode::SignAndAuth,
+        /* isIsaPointer */ false,
+        /* authenticatesNullValues */ false);
+    clang::QualType result =
+        clang_ast.getPointerAuthType(GetQualType(type), pauth);
+    return GetType(result);
+  }
+  return CompilerType();
+}
+
 CompilerType
 TypeSystemClang::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
   if (type) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index a73164895baa80..f3598d0cb181c6 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -648,6 +648,10 @@ class TypeSystemClang : public TypeSystem {
   bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
                            bool &is_complex) override;
 
+  unsigned GetPtrAuthKey(lldb::opaque_compiler_type_t type) override;
+  unsigned GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) override;
+  bool GetPtrAuthAddressDiversity(lldb::opaque_compiler_type_t type) override;
+
   bool IsFunctionType(lldb::opaque_compiler_type_t type) override;
 
   uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
@@ -788,6 +792,10 @@ class TypeSystemClang : public TypeSystem {
 
   CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
 
+  CompilerType AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
+                                  unsigned key, bool isAddressDiscriminated,
+                                  unsigned extraDiscriminator) override;
+
   CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
 
   CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type) override;
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 76b79daa6ac154..b8fc6b1946a1a4 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -108,6 +108,27 @@ bool CompilerType::IsConst() const {
   return false;
 }
 
+unsigned CompilerType::GetPtrAuthKey() const {
+  if (IsValid())
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->GetPtrAuthKey(m_type);
+  return 0;
+}
+
+unsigned CompilerType::GetPtrAuthDiscriminator() const {
+  if (IsValid())
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->GetPtrAuthDiscriminator(m_type);
+  return 0;
+}
+
+bool CompilerType::GetPtrAuthAddressDiversity() const {
+  if (IsValid())
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->GetPtrAuthAddressDiversity(m_type);
+  return false;
+}
+
 bool CompilerType::IsFunctionType() const {
   if (IsValid())
     if (auto type_system_sp = GetTypeSystem())
@@ -664,6 +685,17 @@ CompilerType CompilerType::GetPointerType() const {
   return CompilerType();
 }
 
+CompilerType
+CompilerType::AddPtrAuthModifier(unsigned key, bool isAddressDiscriminated,
+                                 unsigned extraDiscriminator) const {
+  if (IsValid()) {
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->AddPtrAuthModifier(
+          m_type, key, isAddressDiscriminated, extraDiscriminator);
+  }
+  return CompilerType();
+}
+
 CompilerType CompilerType::GetLValueReferenceType() const {
   if (IsValid())
     if (auto type_system_sp = GetTypeSystem())
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 59b1b39e635ac5..80e3d62320278a 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -93,6 +93,13 @@ CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
   return CompilerType();
 }
 
+CompilerType TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
+                                            unsigned key,
+                                            bool isAddressDiscriminated,
+                                            unsigned extraDiscriminator) {
+  return CompilerType();
+}
+
 CompilerType
 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
   return CompilerType();

>From 4164b7e60c5f5feffce5b8d4c24937a28fbbe010 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 16:43:08 +0300
Subject: [PATCH 04/10] [PAC][lldb] Test parsing `__ptrauth`-qalified types in
 `DWARFASTParserClang`

---
 .../DWARF/DWARFASTParserClangTests.cpp        | 135 ++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 0c2a0d735dc837..f7a4b8f1ac59be 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -287,6 +287,141 @@ TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) {
   ASSERT_EQ(found_function_types, expected_function_types);
 }
 
+TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) {
+  // Tests parsing values with type DW_TAG_LLVM_ptrauth_type corresponding to
+  // explicitly signed raw function pointers
+
+  // This is Dwarf for the following C code:
+  // ```
+  // void (*__ptrauth(0, 0, 42) a)();
+  // ```
+
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_AARCH64
+DWARF:
+  debug_str:
+    - a
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x01
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x02
+          Tag:             DW_TAG_variable
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+        - Code:            0x03
+          Tag:             DW_TAG_LLVM_ptrauth_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_LLVM_ptrauth_key
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_LLVM_ptrauth_extra_discriminator
+              Form:            DW_FORM_data2
+        - Code:            0x04
+          Tag:             DW_TAG_pointer_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+        - Code:            0x05
+          Tag:             DW_TAG_subroutine_type
+          Children:        DW_CHILDREN_yes
+        - Code:            0x06
+          Tag:             DW_TAG_unspecified_parameters
+          Children:        DW_CHILDREN_no
+
+  debug_info:
+    - Version:         5
+      UnitType:        DW_UT_compile
+      AddrSize:        8
+      Entries:
+# 0x0c: DW_TAG_compile_unit
+#         DW_AT_language [DW_FORM_data2]    (DW_LANG_C99)
+        - AbbrCode:        0x01
+          Values:
+            - Value:           0x0c
+
+# 0x0f:   DW_TAG_variable
+#           DW_AT_name [DW_FORM_strp]       (\"a\")
+#           DW_AT_type [DW_FORM_ref4]       (0x00000018 \"void (*__ptrauth(0, 0, 0x02a)\")
+#           DW_AT_external [DW_FORM_flag_present]   (true)
+        - AbbrCode:        0x02
+          Values:
+            - Value:           0x00
+            - Value:           0x18
+
+# 0x18:   DW_TAG_LLVM_ptrauth_type
+#           DW_AT_type [DW_FORM_ref4]       (0x00000020 \"void (*)(...)\")
+#           DW_AT_LLVM_ptrauth_key [DW_FORM_data1]  (0x00)
+#           DW_AT_LLVM_ptrauth_extra_discriminator [DW_FORM_data2]  (0x002a)
+        - AbbrCode:        0x03
+          Values:
+            - Value:           0x20
+            - Value:           0x00
+            - Value:           0x2a
+
+# 0x20:   DW_TAG_pointer_type
+#           DW_AT_type [DW_AT_type [DW_FORM_ref4]       (0x00000025 \"void (...)\")
+        - AbbrCode:        0x04
+          Values:
+            - Value:           0x25
+
+# 0x25:   DW_TAG_subroutine_type
+        - AbbrCode:        0x05
+
+# 0x26:     DW_TAG_unspecified_parameters
+        - AbbrCode:        0x06
+
+        - AbbrCode:        0x00 # end of child tags of 0x25
+        - AbbrCode:        0x00 # end of child tags of 0x0c
+...
+)";
+  YAMLModuleTester t(yamldata);
+
+  DWARFUnit *unit = t.GetDwarfUnit();
+  ASSERT_NE(unit, nullptr);
+  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
+  DWARFDIE cu_die(unit, cu_entry);
+
+  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
+  auto &ast_ctx = *holder->GetAST();
+  DWARFASTParserClangStub ast_parser(ast_ctx);
+
+  DWARFDIE ptrauth_variable = cu_die.GetFirstChild();
+  ASSERT_EQ(ptrauth_variable.Tag(), DW_TAG_variable);
+  DWARFDIE ptrauth_type =
+      ptrauth_variable.GetAttributeValueAsReferenceDIE(DW_AT_type);
+  ASSERT_EQ(ptrauth_type.Tag(), DW_TAG_LLVM_ptrauth_type);
+
+  SymbolContext sc;
+  bool new_type = false;
+  lldb::TypeSP type_sp =
+      ast_parser.ParseTypeFromDWARF(sc, ptrauth_type, &new_type);
+  CompilerType compiler_type = type_sp->GetForwardCompilerType();
+  ASSERT_EQ(compiler_type.GetPtrAuthKey(), 0);
+  ASSERT_EQ(compiler_type.GetPtrAuthAddressDiversity(), false);
+  ASSERT_EQ(compiler_type.GetPtrAuthDiscriminator(), 42);
+}
+
 struct ExtractIntFromFormValueTest : public testing::Test {
   SubsystemRAII<FileSystem, HostInfo> subsystems;
   clang_utils::TypeSystemClangHolder holder;

>From 8ef23c0c4bd0294fdf956f3db52fc305734e701a Mon Sep 17 00:00:00 2001
From: John McCall <rjmccall at apple.com>
Date: Mon, 16 Dec 2019 20:31:25 -0500
Subject: [PATCH 05/10] Abstract serialization fixes for the Apple Clang
 changes.

---
 clang/include/clang/AST/AbstractBasicReader.h | 4 ++--
 clang/include/clang/AST/AbstractBasicWriter.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h
index 1f2797cc701458..ab036f1d445acc 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -213,9 +213,9 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
   }
 
   Qualifiers readQualifiers() {
-    static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
+    static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
                   "update this if the value size changes");
-    uint32_t value = asImpl().readUInt32();
+    uint64_t value = asImpl().readUInt64();
     return Qualifiers::fromOpaqueValue(value);
   }
 
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h
index 07afa388de2c17..8e42fcaad1d388 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -196,9 +196,9 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
   }
 
   void writeQualifiers(Qualifiers value) {
-    static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
+    static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
                   "update this if the value size changes");
-    asImpl().writeUInt32(value.getAsOpaqueValue());
+    asImpl().writeUInt64(value.getAsOpaqueValue());
   }
 
   void writeExceptionSpecInfo(

>From f448a380dbc6710e4eb9447b6a562ff24e68386a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 15:34:24 +0300
Subject: [PATCH 06/10] Define `PointerAuthenticationMode` enum

---
 clang/include/clang/Basic/LangOptions.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 24b109e32cdd3e..692b90dc9b9ec8 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -57,6 +57,13 @@ enum class ShaderStage {
   Invalid,
 };
 
+enum class PointerAuthenticationMode : unsigned {
+  None,
+  Strip,
+  SignAndStrip,
+  SignAndAuth
+};
+
 /// Bitfields of LangOptions, split out from LangOptions in order to ensure that
 /// this large collection of bitfields is a trivial class type.
 class LangOptionsBase {

>From 9f97ed4b0b90ffbc3422ced47966bb742bd743b6 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 15:31:03 +0300
Subject: [PATCH 07/10] Define `PointerAuthQualifier` class

Includes changes from the following commits from the branch
https://github.com/ahmedbougacha/llvm-project/tree/eng/arm64e-upstream-llvmorg

- Initial support  https://github.com/ahmedbougacha/llvm-project/commit/cc7ba7eb1814e9b254c7d94aa0b78cb0e21acfc5
- ObjC isa signing https://github.com/ahmedbougacha/llvm-project/commit/c9ce0d408f1d9aeffc7b86256334220aec6de5a3

Also applies a fix from https://github.com/access-softek/llvm-project/pull/75

Co-authored-by: Ahmed Bougacha <ahmed at bougacha.org>
---
 clang/include/clang/AST/Type.h                | 215 +++++++++++++++++-
 .../include/clang/Basic/PointerAuthOptions.h  |  23 ++
 2 files changed, 227 insertions(+), 11 deletions(-)
 create mode 100644 clang/include/clang/Basic/PointerAuthOptions.h

diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index b3bf23227a47f2..df370146293cbc 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -25,8 +25,10 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Linkage.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/PointerAuthOptions.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/Visibility.h"
@@ -139,6 +141,165 @@ using CanQualType = CanQual<Type>;
 #define TYPE(Class, Base) class Class##Type;
 #include "clang/AST/TypeNodes.inc"
 
+/// Pointer-authentication qualifiers.
+class PointerAuthQualifier {
+  enum : uint32_t {
+    EnabledShift = 0,
+    EnabledBits = 1,
+    EnabledMask = 1 << EnabledShift,
+    AddressDiscriminatedShift = EnabledShift + EnabledBits,
+    AddressDiscriminatedBits = 1,
+    AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
+    AuthenticationModeShift =
+        AddressDiscriminatedShift + AddressDiscriminatedBits,
+    AuthenticationModeBits = 2,
+    AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
+                             << AuthenticationModeShift,
+    IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
+    IsaPointerBits = 1,
+    IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
+    AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
+    AuthenticatesNullValuesBits = 1,
+    AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
+                                  << AuthenticatesNullValuesShift,
+    KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
+    KeyBits = 10,
+    KeyMask = ((1 << KeyBits) - 1) << KeyShift,
+    DiscriminatorShift = KeyShift + KeyBits,
+    DiscriminatorBits = 16,
+    DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
+  };
+
+  // bits:     |0      |1      |2..3              |4          |
+  //           |Enabled|Address|AuthenticationMode|ISA pointer|
+  // bits:     |5                |6..15|   16...31   |
+  //           |AuthenticatesNull|Key  |Discriminator|
+  uint32_t Data;
+
+  static_assert((EnabledBits + AddressDiscriminatedBits +
+                 AuthenticationModeBits + IsaPointerBits +
+                 AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
+                    32,
+                "PointerAuthQualifier should be exactly 32 bits");
+  static_assert((EnabledMask + AddressDiscriminatedMask +
+                 AuthenticationModeMask + IsaPointerMask +
+                 AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
+                    0xFFFFFFFF,
+                "All masks should cover the entire bits");
+  static_assert((EnabledMask ^ AddressDiscriminatedMask ^
+                 AuthenticationModeMask ^ IsaPointerMask ^
+                 AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
+                    0xFFFFFFFF,
+                "All masks should cover the entire bits");
+
+  PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
+                       unsigned extraDiscriminator,
+                       PointerAuthenticationMode authenticationMode,
+                       bool isIsaPointer, bool authenticatesNullValues)
+      : Data(EnabledMask |
+             (isAddressDiscriminated
+                  ? static_cast<uint32_t>(AddressDiscriminatedMask)
+                  : 0) |
+             (key << KeyShift) |
+             (unsigned(authenticationMode) << AuthenticationModeShift) |
+             (extraDiscriminator << DiscriminatorShift) |
+             (isIsaPointer << IsaPointerShift) |
+             (authenticatesNullValues << AuthenticatesNullValuesShift)) {
+    assert(key <= KeyNoneInternal);
+    assert(extraDiscriminator <= MaxDiscriminator);
+  }
+
+public:
+  enum {
+    KeyNoneInternal = (1u << KeyBits) - 1,
+
+    /// The maximum supported pointer-authentication key.
+    MaxKey = KeyNoneInternal - 1,
+
+    /// The maximum supported pointer-authentication discriminator.
+    MaxDiscriminator = (1u << DiscriminatorBits) - 1
+  };
+
+public:
+  PointerAuthQualifier() : Data(0) {}
+
+  static PointerAuthQualifier
+  Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
+         PointerAuthenticationMode authenticationMode, bool isIsaPointer,
+         bool authenticatesNullValues) {
+    if (key == PointerAuthKeyNone)
+      key = KeyNoneInternal;
+    assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
+    return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator,
+                                authenticationMode, isIsaPointer,
+                                authenticatesNullValues);
+  }
+
+  bool isPresent() const {
+    return getAuthenticationMode() != PointerAuthenticationMode::None;
+  }
+
+  explicit operator bool() const { return isPresent(); }
+
+  unsigned getKey() const {
+    assert(isPresent());
+    return (Data & KeyMask) >> KeyShift;
+  }
+
+  bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; }
+
+  bool isAddressDiscriminated() const {
+    assert(isPresent());
+    return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
+  }
+
+  unsigned getExtraDiscriminator() const {
+    assert(isPresent());
+    return (Data >> DiscriminatorShift);
+  }
+
+  PointerAuthenticationMode getAuthenticationMode() const {
+    return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
+                                     AuthenticationModeShift);
+  }
+
+  bool isIsaPointer() const {
+    assert(isPresent());
+    return (Data & IsaPointerMask) >> IsaPointerShift;
+  }
+
+  bool authenticatesNullValues() const {
+    assert(isPresent());
+    return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;
+  }
+
+  PointerAuthQualifier withoutKeyNone() const {
+    return hasKeyNone() ? PointerAuthQualifier() : *this;
+  }
+
+  friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+    return Lhs.Data == Rhs.Data;
+  }
+  friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+    return Lhs.Data != Rhs.Data;
+  }
+
+  bool isEquivalent(PointerAuthQualifier Other) const {
+    return withoutKeyNone() == Other.withoutKeyNone();
+  }
+
+  uint32_t getAsOpaqueValue() const { return Data; }
+
+  // Deserialize pointer-auth qualifiers from an opaque representation.
+  static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) {
+    PointerAuthQualifier result;
+    result.Data = opaque;
+    return result;
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
+};
+
 /// The collection of all-type qualifiers we support.
 /// Clang supports five independent qualifiers:
 /// * C99: const, volatile, and restrict
@@ -194,19 +355,27 @@ class Qualifiers {
     FastMask = (1 << FastWidth) - 1
   };
 
+  Qualifiers() : Mask(0), PtrAuth() {}
+
   /// Returns the common set of qualifiers while removing them from
   /// the given sets.
   static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
+    Qualifiers Q;
+    if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) {
+      Q.setPointerAuth(L.getPointerAuth().withoutKeyNone());
+      PointerAuthQualifier Empty;
+      L.setPointerAuth(Empty);
+      R.setPointerAuth(Empty);
+    }
+
     // If both are only CVR-qualified, bit operations are sufficient.
     if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
-      Qualifiers Q;
       Q.Mask = L.Mask & R.Mask;
       L.Mask &= ~Q.Mask;
       R.Mask &= ~Q.Mask;
       return Q;
     }
 
-    Qualifiers Q;
     unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
     Q.addCVRQualifiers(CommonCRV);
     L.removeCVRQualifiers(CommonCRV);
@@ -251,15 +420,16 @@ class Qualifiers {
   }
 
   // Deserialize qualifiers from an opaque representation.
-  static Qualifiers fromOpaqueValue(unsigned opaque) {
+  static Qualifiers fromOpaqueValue(uint64_t opaque) {
     Qualifiers Qs;
-    Qs.Mask = opaque;
+    Qs.Mask = uint32_t(opaque);
+    Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32));
     return Qs;
   }
 
   // Serialize these qualifiers into an opaque representation.
-  unsigned getAsOpaqueValue() const {
-    return Mask;
+  uint64_t getAsOpaqueValue() const {
+    return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32);
   }
 
   bool hasConst() const { return Mask & Const; }
@@ -407,6 +577,10 @@ class Qualifiers {
     setAddressSpace(space);
   }
 
+  PointerAuthQualifier getPointerAuth() const { return PtrAuth; }
+  void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; }
+  void removePtrAuth() { PtrAuth = PointerAuthQualifier(); }
+
   // Fast qualifiers are those that can be allocated directly
   // on a QualType object.
   bool hasFastQualifiers() const { return getFastQualifiers(); }
@@ -429,7 +603,7 @@ class Qualifiers {
 
   /// Return true if the set contains any qualifiers which require an ExtQuals
   /// node to be allocated.
-  bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+  bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; }
   Qualifiers getNonFastQualifiers() const {
     Qualifiers Quals = *this;
     Quals.setFastQualifiers(0);
@@ -437,8 +611,8 @@ class Qualifiers {
   }
 
   /// Return true if the set contains any qualifiers.
-  bool hasQualifiers() const { return Mask; }
-  bool empty() const { return !Mask; }
+  bool hasQualifiers() const { return Mask || PtrAuth; }
+  bool empty() const { return !hasQualifiers(); }
 
   /// Add the qualifiers from the given set to this set.
   void addQualifiers(Qualifiers Q) {
@@ -455,6 +629,9 @@ class Qualifiers {
       if (Q.hasObjCLifetime())
         addObjCLifetime(Q.getObjCLifetime());
     }
+
+    if (Q.PtrAuth)
+      PtrAuth = Q.PtrAuth;
   }
 
   /// Remove the qualifiers from the given set from this set.
@@ -472,6 +649,9 @@ class Qualifiers {
       if (getAddressSpace() == Q.getAddressSpace())
         removeAddressSpace();
     }
+
+    if (PtrAuth == Q.PtrAuth)
+      PtrAuth = PointerAuthQualifier();
   }
 
   /// Add the qualifiers from the given set to this set, given that
@@ -483,7 +663,10 @@ class Qualifiers {
            !hasObjCGCAttr() || !qs.hasObjCGCAttr());
     assert(getObjCLifetime() == qs.getObjCLifetime() ||
            !hasObjCLifetime() || !qs.hasObjCLifetime());
+    assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth);
     Mask |= qs.Mask;
+    if (qs.PtrAuth)
+      PtrAuth = qs.PtrAuth;
   }
 
   /// Returns true if address space A is equal to or a superset of B.
@@ -536,6 +719,8 @@ class Qualifiers {
            // be changed.
            (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
             !other.hasObjCGCAttr()) &&
+           // Pointer-auth qualifiers must match exactly.
+           PtrAuth == other.PtrAuth &&
            // ObjC lifetime qualifiers must match exactly.
            getObjCLifetime() == other.getObjCLifetime() &&
            // CVR qualifiers may subset.
@@ -568,8 +753,12 @@ class Qualifiers {
   /// another set of qualifiers, not considering qualifier compatibility.
   bool isStrictSupersetOf(Qualifiers Other) const;
 
-  bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
-  bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+  bool operator==(Qualifiers Other) const {
+    return Mask == Other.Mask && PtrAuth == Other.PtrAuth;
+  }
+  bool operator!=(Qualifiers Other) const {
+    return Mask != Other.Mask || PtrAuth != Other.PtrAuth;
+  }
 
   explicit operator bool() const { return hasQualifiers(); }
 
@@ -607,6 +796,7 @@ class Qualifiers {
 
   void Profile(llvm::FoldingSetNodeID &ID) const {
     ID.AddInteger(Mask);
+    PtrAuth.Profile(ID);
   }
 
 private:
@@ -614,6 +804,9 @@ class Qualifiers {
   //           |C R V|U|GCAttr|Lifetime|AddressSpace|
   uint32_t Mask = 0;
 
+  PointerAuthQualifier PtrAuth;
+  static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
+                "PointerAuthQualifier must be 32 bits");
   static const uint32_t UMask = 0x8;
   static const uint32_t UShift = 3;
   static const uint32_t GCAttrMask = 0x30;
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
new file mode 100644
index 00000000000000..c69847ac704a41
--- /dev/null
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -0,0 +1,23 @@
+//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines options for configuring pointer-auth technologies
+//  like ARMv8.3.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+
+namespace clang {
+
+constexpr int PointerAuthKeyNone = -1;
+
+} // end namespace clang
+
+#endif

>From f325fa9b8f57c78fe96ab84f62bf76848fc5c43c Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 17:54:20 +0300
Subject: [PATCH 08/10] Support `PointerAuthQualifier` in `QualType`

---
 clang/include/clang/AST/ASTContext.h | 10 ++++++++++
 clang/include/clang/AST/Type.h       |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 002f36ecbbaa3f..4fe27f1b6fa270 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2189,6 +2189,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
     return getQualifiedType(type.getUnqualifiedType(), Qs);
   }
 
+  /// \brief Return a type with the given __ptrauth qualifier.
+  QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) {
+    assert(!type.getPointerAuth());
+    assert(pointerAuth);
+
+    Qualifiers qs;
+    qs.setPointerAuth(pointerAuth);
+    return getQualifiedType(type, qs);
+  }
+
   unsigned char getFixedPointScale(QualType Ty) const;
   unsigned char getFixedPointIBits(QualType Ty) const;
   llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index df370146293cbc..fc666dd980e56c 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1435,6 +1435,10 @@ class QualType {
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
 
+  PointerAuthQualifier getPointerAuth() const {
+    return getQualifiers().getPointerAuth();
+  }
+
   enum PrimitiveDefaultInitializeKind {
     /// The type does not fall into any of the following categories. Note that
     /// this case is zero-valued so that values of this enum can be used as a

>From dd77587e49a89af77a2821cfa9c69b81f9dc8a42 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 26 Mar 2024 22:34:52 +0300
Subject: [PATCH 09/10] Delete TODOs

---
 lldb/include/lldb/Symbol/TypeSystem.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 085ac4a37feab7..ca92fa790d2614 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -216,8 +216,6 @@ class TypeSystem : public PluginInterface,
 
   virtual uint32_t GetPointerByteSize() = 0;
 
-  // TODO: are we allowed to insert virtual functions in the middle of the class
-  // interface and break ABI?
   virtual unsigned GetPtrAuthKey(lldb::opaque_compiler_type_t type) = 0;
 
   virtual unsigned
@@ -290,8 +288,6 @@ class TypeSystem : public PluginInterface,
 
   virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
 
-  // TODO: are we allowed to insert virtual functions in the middle of the class
-  // interface and break ABI?
   virtual CompilerType AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
                                           unsigned key,
                                           bool isAddressDiscriminated,

>From 2db295c9f26c3bf5408b23b4cf71850600e97380 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 28 Mar 2024 12:52:24 +0300
Subject: [PATCH 10/10] Implement lazy resolve of ptrauth types

---
 lldb/include/lldb/Symbol/CompilerType.h       | 11 +--
 lldb/include/lldb/Symbol/TypeSystem.h         |  4 +-
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 93 ++++++++-----------
 .../TypeSystem/Clang/TypeSystemClang.cpp      |  9 +-
 .../TypeSystem/Clang/TypeSystemClang.h        |  7 +-
 lldb/source/Symbol/CompilerType.cpp           | 10 +-
 lldb/source/Symbol/Type.cpp                   | 10 ++
 lldb/source/Symbol/TypeSystem.cpp             |  4 +-
 8 files changed, 63 insertions(+), 85 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index f9d3da5704454c..872066b8c73207 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -376,12 +376,11 @@ class CompilerType {
   /// Create related types using the current type's AST
   CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const;
 
-  /// Return a new CompilerType adds a ptrauth modifier with given parameters to
-  /// this type if this type is valid and the type system supports ptrauth
-  /// modifiers, else return an invalid type. Note that this does not check if
-  /// this type is a pointer.
-  CompilerType AddPtrAuthModifier(unsigned key, bool isAddressDiscriminated,
-                                  unsigned extraDiscriminator) const;
+  /// Return a new CompilerType adds a ptrauth modifier from the given 32-bit
+  /// opaque payload to this type if this type is valid and the type system
+  /// supports ptrauth modifiers, else return an invalid type. Note that this
+  /// does not check if this type is a pointer.
+  CompilerType AddPtrAuthModifier(uint32_t payload) const;
   /// \}
 
   /// Exploring the type.
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index ca92fa790d2614..03aa939ba6c7e0 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -289,9 +289,7 @@ class TypeSystem : public PluginInterface,
   virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
 
   virtual CompilerType AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
-                                          unsigned key,
-                                          bool isAddressDiscriminated,
-                                          unsigned extraDiscriminator);
+                                          uint32_t payload);
 
   /// \param opaque_payload      The m_payload field of Type, which may
   /// carry TypeSystem-specific extra information.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 1e13962aadd43e..5ff3f0d614e6e3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -570,6 +570,39 @@ ExtractDataMemberLocation(DWARFDIE const &die, DWARFFormValue const &form_value,
   return memberOffset.ResolveValue(nullptr).UInt();
 }
 
+static TypePayloadClang GetPtrAuthMofidierPayload(const DWARFDIE &die) {
+  auto getAttr = [&](llvm::dwarf::Attribute Attr, unsigned defaultValue = 0) {
+    return die.GetAttributeValueAsUnsigned(Attr, defaultValue);
+  };
+  const unsigned key = getAttr(DW_AT_LLVM_ptrauth_key);
+  const bool addr_disc = getAttr(DW_AT_LLVM_ptrauth_address_discriminated);
+  const unsigned extra = getAttr(DW_AT_LLVM_ptrauth_extra_discriminator);
+  const bool isapointer = getAttr(DW_AT_LLVM_ptrauth_isa_pointer);
+  const bool authenticates_null_values =
+      getAttr(DW_AT_LLVM_ptrauth_authenticates_null_values);
+  const unsigned authentication_mode_int = getAttr(
+      DW_AT_LLVM_ptrauth_authentication_mode,
+      static_cast<unsigned>(clang::PointerAuthenticationMode::SignAndAuth));
+  clang::PointerAuthenticationMode authentication_mode =
+      clang::PointerAuthenticationMode::SignAndAuth;
+  if (authentication_mode_int >=
+          static_cast<unsigned>(clang::PointerAuthenticationMode::None) &&
+      authentication_mode_int <=
+          static_cast<unsigned>(
+              clang::PointerAuthenticationMode::SignAndAuth)) {
+    authentication_mode =
+        static_cast<clang::PointerAuthenticationMode>(authentication_mode_int);
+  } else {
+    die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
+        "[{0:x16}]: invalid pointer authentication mode method {1:x4}",
+        die.GetOffset(), authentication_mode_int);
+  }
+  auto ptr_auth = clang::PointerAuthQualifier::Create(
+      key, addr_disc, extra, authentication_mode, isapointer,
+      authenticates_null_values);
+  return TypePayloadClang(ptr_auth.getAsOpaqueValue());
+}
+
 lldb::TypeSP
 DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
                                        const DWARFDIE &die,
@@ -580,6 +613,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
   LanguageType cu_language = SymbolFileDWARF::GetLanguage(*die.GetCU());
   Type::ResolveState resolve_state = Type::ResolveState::Unresolved;
   Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+  TypePayloadClang payload(GetOwningClangModule(die));
   TypeSP type_sp;
   CompilerType clang_type;
 
@@ -677,62 +711,10 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
   case DW_TAG_volatile_type:
     encoding_data_type = Type::eEncodingIsVolatileUID;
     break;
-  case DW_TAG_LLVM_ptrauth_type: {
-    DWARFDIE ptr_die = die.GetReferencedDIE(DW_AT_type);
-    // FIXME: Fully resolving the type here may affect performance.
-    Type *res_type = dwarf->ResolveType(ptr_die);
-    if (!res_type)
-      break;
-    attrs.type.Clear();
+  case DW_TAG_LLVM_ptrauth_type:
     encoding_data_type = Type::eEncodingIsLLVMPtrAuthUID;
-    resolve_state = Type::ResolveState::Full;
-
-    // Apply the ptrauth qualifier to the resolved type.
-    auto *ptr_type =
-        (clang::Type *)res_type->GetForwardCompilerType().GetOpaqueQualType();
-    auto getAttr = [&](llvm::dwarf::Attribute Attr, unsigned defaultValue = 0) {
-      return die.GetAttributeValueAsUnsigned(Attr, defaultValue);
-    };
-    const unsigned key = getAttr(DW_AT_LLVM_ptrauth_key);
-    const bool addr_disc = getAttr(DW_AT_LLVM_ptrauth_address_discriminated);
-    const unsigned extra = getAttr(DW_AT_LLVM_ptrauth_extra_discriminator);
-    const bool isapointer = getAttr(DW_AT_LLVM_ptrauth_isa_pointer);
-    const bool authenticates_null_values =
-        getAttr(DW_AT_LLVM_ptrauth_authenticates_null_values, 0);
-    const bool is_restricted_integral = !ptr_type->isPointerType();
-    const unsigned authentication_mode_int = getAttr(
-        DW_AT_LLVM_ptrauth_authentication_mode,
-        static_cast<unsigned>(clang::PointerAuthenticationMode::SignAndAuth));
-    clang::PointerAuthenticationMode authentication_mode =
-        clang::PointerAuthenticationMode::SignAndAuth;
-    if (authentication_mode_int >=
-            static_cast<unsigned>(clang::PointerAuthenticationMode::None) &&
-        authentication_mode_int <=
-            static_cast<unsigned>(
-                clang::PointerAuthenticationMode::SignAndAuth)) {
-      authentication_mode = static_cast<clang::PointerAuthenticationMode>(
-          authentication_mode_int);
-    } else {
-      dwarf->GetObjectFile()->GetModule()->ReportError(
-          "[{0:x16}]: invalid pointer authentication mode method {1:x4}",
-          die.GetOffset(), authentication_mode_int);
-    }
-
-    // FIXME: Use these variables when PointerAuthQualifier is more complete
-    // upstream.
-    (void)is_restricted_integral;
-
-    clang::Qualifiers qualifiers;
-    auto ptr_auth = clang::PointerAuthQualifier::Create(
-        key, addr_disc, extra, authentication_mode, isapointer,
-        authenticates_null_values);
-    qualifiers.setPointerAuth(ptr_auth);
-    auto &ctx = m_ast.getASTContext();
-    auto qual_type = ctx.getQualifiedType(ptr_type, qualifiers);
-    clang_type =
-        CompilerType(m_ast.weak_from_this(), qual_type.getAsOpaquePtr());
+    payload = GetPtrAuthMofidierPayload(die);
     break;
-  }
   case DW_TAG_atomic_type:
     encoding_data_type = Type::eEncodingIsAtomicUID;
     break;
@@ -842,8 +824,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
 
   type_sp = dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr,
                             attrs.type.Reference().GetID(), encoding_data_type,
-                            &attrs.decl, clang_type, resolve_state,
-                            TypePayloadClang(GetOwningClangModule(die)));
+                            &attrs.decl, clang_type, resolve_state, payload);
 
   dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
   return type_sp;
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 45d9e67c59a0b5..bcab4fbd0e7859 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -4593,15 +4593,10 @@ TypeSystemClang::AddConstModifier(lldb::opaque_compiler_type_t type) {
 
 CompilerType
 TypeSystemClang::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
-                                    unsigned key, bool isAddressDiscriminated,
-                                    unsigned extraDiscriminator) {
+                                    uint32_t payload) {
   if (type) {
     clang::ASTContext &clang_ast = getASTContext();
-    auto pauth = PointerAuthQualifier::Create(
-        key, isAddressDiscriminated, extraDiscriminator,
-        PointerAuthenticationMode::SignAndAuth,
-        /* isIsaPointer */ false,
-        /* authenticatesNullValues */ false);
+    auto pauth = PointerAuthQualifier::fromOpaqueValue(payload);
     clang::QualType result =
         clang_ast.getPointerAuthType(GetQualType(type), pauth);
     return GetType(result);
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 667c62bd263ea5..cf8b9f54ed5598 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -66,11 +66,13 @@ class OptionalClangModuleID {
 
 /// The implementation of lldb::Type's m_payload field for TypeSystemClang.
 class TypePayloadClang {
-  /// The Layout is as follows:
+  /// The payload is used for typedefs and ptrauth types.
+  /// For typedefs, the Layout is as follows:
   /// \verbatim
   /// bit 0..30 ... Owning Module ID.
   /// bit 31 ...... IsCompleteObjCClass.
   /// \endverbatim
+  /// For ptrauth types, we store the PointerAuthQualifier as an opaque value.
   Type::Payload m_payload = 0;
 
 public:
@@ -793,8 +795,7 @@ class TypeSystemClang : public TypeSystem {
   CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
 
   CompilerType AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
-                                  unsigned key, bool isAddressDiscriminated,
-                                  unsigned extraDiscriminator) override;
+                                  uint32_t payload) override;
 
   CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
 
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 88cd65bfaa6a45..af66856479223f 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -685,14 +685,10 @@ CompilerType CompilerType::GetPointerType() const {
   return CompilerType();
 }
 
-CompilerType
-CompilerType::AddPtrAuthModifier(unsigned key, bool isAddressDiscriminated,
-                                 unsigned extraDiscriminator) const {
-  if (IsValid()) {
+CompilerType CompilerType::AddPtrAuthModifier(uint32_t payload) const {
+  if (IsValid())
     if (auto type_system_sp = GetTypeSystem())
-      return type_system_sp->AddPtrAuthModifier(
-          m_type, key, isAddressDiscriminated, extraDiscriminator);
-  }
+      return type_system_sp->AddPtrAuthModifier(m_type, payload);
   return CompilerType();
 }
 
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 89e9a7a256e1bb..ca505981002f4b 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -627,6 +627,12 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) {
             encoding_type->GetForwardCompilerType().GetRValueReferenceType();
         break;
 
+      case eEncodingIsLLVMPtrAuthUID:
+        m_compiler_type =
+            encoding_type->GetForwardCompilerType().AddPtrAuthModifier(
+                m_payload);
+        break;
+
       default:
         llvm_unreachable("Unhandled encoding_data_type.");
       }
@@ -682,6 +688,10 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) {
           m_compiler_type = void_compiler_type.GetRValueReferenceType();
           break;
 
+        case eEncodingIsLLVMPtrAuthUID:
+          llvm_unreachable("Cannot handle eEncodingIsLLVMPtrAuthUID without "
+                           "valid encoding_type");
+
         default:
           llvm_unreachable("Unhandled encoding_data_type.");
         }
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 80e3d62320278a..3665771b188906 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -94,9 +94,7 @@ CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
 }
 
 CompilerType TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
-                                            unsigned key,
-                                            bool isAddressDiscriminated,
-                                            unsigned extraDiscriminator) {
+                                            uint32_t payload) {
   return CompilerType();
 }
 



More information about the lldb-commits mailing list