[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