Skip to content
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

[PAC][lldb][Dwarf] Support __ptrauth-qualified types in user expressions #84387

Merged
merged 9 commits into from
Apr 30, 2024

Conversation

kovdan01
Copy link
Contributor

@kovdan01 kovdan01 commented Mar 7, 2024

Depends on #84384 and #90329

This adds support for DW_TAG_LLVM_ptrauth_type entries corresponding
to explicitly signed types (e.g. free function pointers) in lldb user
expressions. Applies PR apple#8239 from
Apple's downstream and also adds tests and related code.

Co-authored-by: Jonas Devlieghere jonas@devlieghere.com

Copy link

github-actions bot commented Mar 7, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 7, 2024

@llvm/pr-subscribers-lldb

Author: Daniil Kovalev (kovdan01)

Changes

Depends on #84384

This adds support for DW_TAG_LLVM_ptrauth_type entries corresponding
to explicitly signed types (e.g. free function pointers) in lldb user
expressions. Applies PR apple#8239 from
Apple's downstream and also adds tests and related code.

Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>


Full diff: https://github.com/llvm/llvm-project/pull/84387.diff

10 Files Affected:

  • (modified) lldb/include/lldb/Symbol/CompilerType.h (+13)
  • (modified) lldb/include/lldb/Symbol/Type.h (+3-1)
  • (modified) lldb/include/lldb/Symbol/TypeSystem.h (+17)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+57)
  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+47)
  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h (+8)
  • (modified) lldb/source/Symbol/CompilerType.cpp (+32)
  • (modified) lldb/source/Symbol/Type.cpp (+7-1)
  • (modified) lldb/source/Symbol/TypeSystem.cpp (+7)
  • (modified) lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp (+135)
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/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/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/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 54d06b1115a229..1e13962aadd43e 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::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());
+    break;
+  }
   case DW_TAG_atomic_type:
     encoding_data_type = Type::eEncodingIsAtomicUID;
     break;
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/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;
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();
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;

@kovdan01
Copy link
Contributor Author

A kind reminder regarding the PR - would be glad to see feedback from everyone interested.

@@ -664,6 +685,17 @@ CompilerType CompilerType::GetPointerType() const {
return CompilerType();
}

CompilerType
CompilerType::AddPtrAuthModifier(unsigned key, bool isAddressDiscriminated,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an API test that tests this API? E.g., running frame var/expr on ptrauth types?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, whose this user of this API? Presumably there's a separate PR out there that makes use of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, whose this user of this API?

I've updated this PR with eecbb37 which implements lazy resolve of ptrauth types. Since then, CompilerType::AddPtrAuthModifier is used in Type::ResolveCompilerType. So, this API is "indirectly" tested in DWARFASTParserClangTests.TestPtrAuthParsing unit test.

Can we add an API test that tests this API? E.g., running frame var/expr on ptrauth types?

Probably later, when __ptrauth qualifier support in upstream llvm is more complete. As far as I see from existing API tests (e.g. API/lang/c/const_variables/TestConstVariables.py), we need to compile code with desired features first, and then run it under debugger and test stuff that we want to. Since the compiler does not seem to fully support __ptrauth-related features yet, implementing the corresponding API test does not currently seem viable.

Comment on lines 219 to 220
// TODO: are we allowed to insert virtual functions in the middle of the class
// interface and break ABI?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer: Yes, there's no ABI stability for lldb_private.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, deleted TODOs in ced59fd

@@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to put all of this in a helper function, in order to not bloat the size of ParseTypeModifier. But feel free to ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks, see eecbb37

kovdan01 added a commit that referenced this pull request Apr 26, 2024
…Mode` (#84384)

This brings declarations of `PointerAuthQualifier` class and
`PointerAuthenticationMode` enum and related functions required for
PAuth support in lldb (see #84387) from downstream Apple's code. See
#84387 for tests as well.

Co-authored-by: Ahmed Bougacha <ahmed@bougacha.org>
Co-authored-by: John McCall <rjmccall@apple.com>

---------

Co-authored-by: John McCall <rjmccall@apple.com>
Co-authored-by: Ahmed Bougacha <ahmed@bougacha.org>
@kovdan01
Copy link
Contributor Author

Merging this previously approved PR since prerequisites are now met

@kovdan01 kovdan01 merged commit 64248d7 into llvm:main Apr 30, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[PAC][LLDB][Dwarf] Support __ptrauth-qualified types in user expressions
4 participants