Skip to content

[DebugInfo] Emit alternative module name in debug info #9563

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

Open
wants to merge 3 commits into
base: stable/20240723
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lldb/include/lldb/Symbol/SymbolFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Statistics.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/XcodeSDK.h"
#include "lldb/lldb-private.h"
Expand Down Expand Up @@ -498,7 +499,7 @@ class SymbolFile : public PluginInterface {
Type::EncodingDataType encoding_uid_type, const Declaration &decl,
const CompilerType &compiler_qual_type,
Type::ResolveState compiler_type_resolve_state,
uint32_t opaque_payload = 0) = 0;
uint32_t opaque_payload = 0, ConstString alternative_module_name = ConstString()) = 0;

virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0;

Expand Down Expand Up @@ -604,11 +605,11 @@ class SymbolFileCommon : public SymbolFile {
const Declaration &decl,
const CompilerType &compiler_qual_type,
Type::ResolveState compiler_type_resolve_state,
uint32_t opaque_payload = 0) override {
uint32_t opaque_payload = 0, ConstString alternative_module_name = ConstString()) override {
lldb::TypeSP type_sp (new Type(
uid, this, name, byte_size, context, encoding_uid,
encoding_uid_type, decl, compiler_qual_type,
compiler_type_resolve_state, opaque_payload));
compiler_type_resolve_state, opaque_payload, alternative_module_name));
m_type_list.Insert(type_sp);
return type_sp;
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Symbol/SymbolFileOnDemand.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile {
const Declaration &decl,
const CompilerType &compiler_qual_type,
Type::ResolveState compiler_type_resolve_state,
uint32_t opaque_payload = 0) override {
uint32_t opaque_payload = 0, ConstString alternative_module_name = ConstString()) override {
return m_sym_file_impl->MakeType(
uid, name, byte_size, context, encoding_uid, encoding_uid_type, decl,
compiler_qual_type, compiler_type_resolve_state, opaque_payload);
Expand Down
24 changes: 22 additions & 2 deletions lldb/include/lldb/Symbol/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ FLAGS_ENUM(TypeQueryOptions){
/// When true, the find types call should stop the query as soon as a single
/// matching type is found. When false, the type query should find all
/// matching types.
e_find_one = (1u << 2),
e_find_one = (1u << 4),
// If set, treat TypeQuery::m_name as a mangled name that should be
// searched.
e_search_by_mangled_name = (1u << 5),
};
LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions)

Expand Down Expand Up @@ -280,6 +283,19 @@ class TypeQuery {
m_options &= (e_exact_match | e_find_one);
}

/// Returns true if the type query is supposed to treat the name to be
/// searched as a mangled name.
bool GetSearchByMangledName() const {
return (m_options & e_search_by_mangled_name) != 0;
}

void SetSearchByMangledName(bool b) {
if (b)
m_options |= e_search_by_mangled_name;
else
m_options &= ~e_search_by_mangled_name;
}

/// Access the internal compiler context array.
///
/// Clients can use this to populate the context manually.
Expand Down Expand Up @@ -539,6 +555,8 @@ class Type : public std::enable_shared_from_this<Type>, public UserID {
/// Return the language-specific payload.
void SetPayload(Payload opaque_payload) { m_payload = opaque_payload; }

ConstString GetAlternativeModuleName() const { return m_alternative_module_name; }

protected:
ConstString m_name;
SymbolFile *m_symbol_file = nullptr;
Expand All @@ -555,6 +573,8 @@ class Type : public std::enable_shared_from_this<Type>, public UserID {
/// Language-specific flags.
Payload m_payload;

ConstString m_alternative_module_name;

Type *GetEncodingType();

bool ResolveCompilerType(ResolveState compiler_type_resolve_state);
Expand All @@ -569,7 +589,7 @@ class Type : public std::enable_shared_from_this<Type>, public UserID {
std::optional<uint64_t> byte_size, SymbolContextScope *context,
lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type,
const Declaration &decl, const CompilerType &compiler_qual_type,
ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0);
ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0, ConstString alternative_module_name = ConstString());

// This makes an invalid type. Used for functions that return a Type when
// they get an error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "LLDBMemoryReader.h"
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
#include "ReflectionContextInterface.h"
#include "SwiftLanguageRuntime.h"
#include "SwiftLanguageRuntimeImpl.h"
Expand All @@ -21,6 +22,7 @@
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "Plugins/TypeSystem/Swift/SwiftDemangle.h"
#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ProcessStructReader.h"
Expand All @@ -31,7 +33,9 @@
#include "lldb/Utility/Timer.h"
#include "lldb/ValueObject/ValueObjectMemory.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"

#include "lldb/lldb-private-enumerations.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTWalker.h"
Expand Down Expand Up @@ -2976,6 +2980,167 @@ SwiftLanguageRuntimeImpl::GetTypeRef(CompilerType type,
return type_ref;
}

CompilerType SwiftLanguageRuntimeImpl::AdjustTypeForOriginallyDefinedInModule(
CompilerType type) {
if (!type)
return type;

auto ts = type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
assert(ts);
if (!ts)
return type;

auto &tss = ts->GetTypeSystemSwiftTypeRef();

swift::Demangle::Demangler dem;
auto *node = dem.demangleSymbol(type.GetMangledTypeName());

auto type_node = node->getFirstChild()->getFirstChild();
assert(node && node->hasChildren());
if (!node || !node->hasChildren()) {
LLDB_LOG(GetLog(LLDBLog::Types),
"[AdjustTypeForOriginallyDefinedInModule] Unexpected node for "
"type with mangled name {0}",
type.GetMangledTypeName());

return type;
}

bool did_transform = false;
std::function<NodePointer(NodePointer)> transform_all_module_nodes =
[&](NodePointer node) -> NodePointer {
auto compiler_type = tss.RemangleAsType(dem, node);
if (!compiler_type) {
LLDB_LOG(GetLog(LLDBLog::Types),
"[AdjustTypeForOriginallyDefinedInModule] Unexpected mangling "
"error when mangling adjusted node for type with mangled name "
"{0}",
type.GetMangledTypeName());

return node;
}

lldb::TypeSP lldb_type =
tss.GetCachedType(compiler_type.GetMangledTypeName());

if (!lldb_type || true) {
TypeQuery query(compiler_type.GetMangledTypeName(), e_find_one | e_search_by_mangled_name);
TypeResults results;
ModuleList &module_list = m_process.GetTarget().GetImages();
module_list.FindTypes(tss.GetModule(), query, results);
lldb_type = results.GetFirstType();

if (!lldb_type) {
TypeQuery query(compiler_type.GetMangledTypeName(), e_find_one);
TypeResults results;
ModuleList &module_list = m_process.GetTarget().GetImages();
module_list.FindTypes(tss.GetModule(), query, results);
lldb_type = results.GetFirstType();

if (!lldb_type) {

LLDB_LOGV(
GetLog(LLDBLog::Types),
"[AdjustTypeForOriginallyDefinedInModule] Could not find lldb "
"type for type with mangled name {0}",
type.GetMangledTypeName());

return node;
}
}
}

StringRef alternative_module_name;
if (!lldb_type->GetAlternativeModuleName().IsEmpty()) {
alternative_module_name = lldb_type->GetAlternativeModuleName();
} else {
auto context = lldb_type->GetDeclContext();
if (context.size() <= 1)
return node;

for (auto it = context.rbegin() + 1; it != context.rend(); ++it) {
if (it->kind != CompilerContextKind::ClassOrStruct)
return node;

TypeQuery query(it->name, e_find_one | e_search_by_mangled_name);
TypeResults results;
ModuleList &module_list = m_process.GetTarget().GetImages();
module_list.FindTypes(tss.GetModule(), query, results);
auto parent_type = results.GetFirstType();

if (!parent_type) {
TypeQuery query(it->name, e_find_one);
TypeResults results;
ModuleList &module_list = m_process.GetTarget().GetImages();
module_list.FindTypes(tss.GetModule(), query, results);
parent_type = results.GetFirstType();

if (!parent_type)
return node;
}
if (!parent_type->GetAlternativeModuleName().IsEmpty()) {
alternative_module_name = parent_type->GetAlternativeModuleName();
break;
}
}
}

bool did_transform_module = false;
auto module_tranformer =
[&](NodePointer module_node,
llvm::StringRef module_name) -> NodePointer {
if (did_transform_module)
return module_node;
if (module_node->getText() == swift::MANGLING_MODULE_OBJC)
return module_node;

// If the mangled name's module and module context module match then
// there's nothing to do.
if (module_node->getText() == module_name)
return module_node;

// Otherwise this is a type who is originally defined in a separate
// module. Adjust the module name.
auto *adjusted_module_node = dem.createNodeWithAllocatedText(
Node::Kind::Module, module_name);
did_transform_module = true;
return adjusted_module_node;
};

// NodePointer transformed = TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer module_node) {
// return module_tranformer(module_node, module_context);
// });
NodePointer transformed = TypeSystemSwiftTypeRef::TransformModuleName(
node, dem, [&](NodePointer module_node) {
return module_tranformer(module_node, alternative_module_name);
});

NodePointer t2 = TypeSystemSwiftTypeRef::TransformBoundGenericTypes(dem,
transformed, transform_all_module_nodes);
return t2;
};
// First transform the module of the type.

type_node = transform_all_module_nodes(type_node);
node->getFirstChild()->replaceChild(0, type_node);
// if (!did_transform)
// return type;

auto mangling = mangleNode(node);
assert(mangling.isSuccess());
if (!mangling.isSuccess()) {
LLDB_LOG(GetLog(LLDBLog::Types),
"[AdjustTypeForOriginallyDefinedInModule] Unexpected mangling "
"error when mangling adjusted node for type with mangled name {0}",
type.GetMangledTypeName());

return type;
}

auto str = mangling.result();
return ts->GetTypeFromMangledTypename(ConstString(str));
}

const swift::reflection::TypeInfo *
SwiftLanguageRuntimeImpl::GetSwiftRuntimeTypeInfo(
CompilerType type, ExecutionContextScope *exe_scope,
Expand Down Expand Up @@ -3006,6 +3171,8 @@ SwiftLanguageRuntimeImpl::GetSwiftRuntimeTypeInfo(
type = BindGenericTypeParameters(*frame, type);
}


type = AdjustTypeForOriginallyDefinedInModule(type);
// BindGenericTypeParameters imports the type into the scratch
// context, but we need to resolve (any DWARF links in) the typeref
// in the original module.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,12 @@ class SwiftLanguageRuntimeImpl {
CompilerType m_box_metadata_type;

private:
/// Types with the @_originallyDefinedIn attribute are serialized with with
/// the original module name in reflection metadata. At the same time the type
/// is serialized with the swiftmodule name in debug info, but with a parent
/// module with the original module name. This function adjusts \type to look
/// up the type in reflection metadata if necessary.
CompilerType AdjustTypeForOriginallyDefinedInModule(CompilerType type);
/// Don't call these directly.
/// \{
/// There is a global variable \p _swift_classIsSwiftMask that is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "lldb/Utility/Status.h"

#include "clang/AST/DeclObjC.h"
#include "llvm/BinaryFormat/Dwarf.h"

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -67,6 +68,7 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
Declaration decl;
ConstString mangled_name;
ConstString name;
ConstString alternative_module_name;
ConstString preferred_name;

std::optional<uint64_t> dwarf_byte_size;
Expand Down Expand Up @@ -109,6 +111,9 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
return ParseTypeFromDWARF(sc, die.GetReferencedDIE(attr),
type_is_new_ptr);
break;
case DW_AT_LLVM_alternative_module_name:
alternative_module_name.SetCString(form_value.AsCString());
break;
default:
break;
}
Expand Down Expand Up @@ -198,7 +203,7 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
// We don't have an exe_scope here by design, so we need to
// read the size from DWARF.
dwarf_byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl,
compiler_type, Type::ResolveState::Full);
compiler_type, Type::ResolveState::Full, 0, alternative_module_name);
}

// Cache this type.
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const {
return result;
}

const char *DWARFDIE::GetMangledName() const {
const char *DWARFDIE::GetMangledName(bool substitute_name_allowed) const {
if (IsValid())
return m_die->GetMangledName(m_cu);
return m_die->GetMangledName(m_cu, substitute_name_allowed);
else
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class DWARFDIE : public DWARFBaseDIE {
// Accessors

// Accessing information about a DIE
const char *GetMangledName() const;
const char *GetMangledName(bool substitute_name_allowed = true) const;

bool IsGenericTrampoline() const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
#include "lldb/Core/Module.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>

using namespace lldb_private;
Expand Down Expand Up @@ -157,11 +159,6 @@ bool DebugNamesDWARFIndex::ProcessEntry(
DWARFDIE die = GetDIE(entry);
if (!die)
return true;
// Clang used to erroneously emit index entries for declaration DIEs in case
// when the definition is in a type unit (llvm.org/pr77696).
if (die.IsStructUnionOrClass() &&
die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
return true;
return callback(die);
}

Expand Down
Loading