2222#include " lldb/Symbol/Variable.h"
2323#include " lldb/Symbol/VariableList.h"
2424#include " lldb/Target/ProcessStructReader.h"
25+ #include " lldb/Target/SectionLoadList.h"
2526#include " lldb/Target/Target.h"
2627#include " lldb/Utility/LLDBLog.h"
2728#include " lldb/Utility/Log.h"
3940#include " swift/Remote/MemoryReader.h"
4041#include " swift/RemoteAST/RemoteAST.h"
4142#include " swift/Runtime/Metadata.h"
43+ #include " swift/Strings.h"
4244
4345#include < sstream>
4446
@@ -2941,6 +2943,80 @@ SwiftLanguageRuntimeImpl::GetValueType(ValueObject &in_value,
29412943 return Value::ValueType::Scalar;
29422944}
29432945
2946+ namespace {
2947+ struct SwiftNominalType {
2948+ std::string module ;
2949+ std::string identifier;
2950+ };
2951+
2952+ // Find the Swift class that backs an ObjC type.
2953+ //
2954+ // A Swift class that uses the @objc(<ClassName>) attribute will emit ObjC
2955+ // metadata into the binary. Typically, ObjC classes have a symbol in the form
2956+ // of OBJC_CLASS_$_<ClassName>, however for Swift classes, there are two symbols
2957+ // that both point to the ObjC class metadata, where the second symbol is a
2958+ // Swift mangled name.
2959+ std::optional<SwiftNominalType> GetSwiftClass (ValueObject &valobj,
2960+ AppleObjCRuntime &objc_runtime) {
2961+ // To find the Swift symbol, the following preparation steps are taken:
2962+ // 1. Get the value's ISA pointer
2963+ // 2. Resolve the ISA load address into an Address instance
2964+ // 3. Get the Module that contains the Address
2965+ auto descriptor_sp = objc_runtime.GetClassDescriptor (valobj);
2966+ if (!descriptor_sp)
2967+ return {};
2968+
2969+ auto isa_load_addr = descriptor_sp->GetISA ();
2970+ Address isa;
2971+ const auto §ions = objc_runtime.GetTargetRef ().GetSectionLoadList ();
2972+ if (!sections.ResolveLoadAddress (isa_load_addr, isa))
2973+ return {};
2974+
2975+ // Next, iterate over the Module's symbol table, looking for a symbol with
2976+ // following criteria:
2977+ // 1. The symbol address is the ISA address
2978+ // 2. The symbol name is a Swift mangled name
2979+ std::optional<StringRef> swift_symbol;
2980+ auto find_swift_symbol_for_isa = [&](Symbol *symbol) {
2981+ if (symbol->GetAddress () == isa) {
2982+ StringRef symbol_name =
2983+ symbol->GetMangled ().GetMangledName ().GetStringRef ();
2984+ if (SwiftLanguageRuntime::IsSwiftMangledName (symbol_name)) {
2985+ swift_symbol = symbol_name;
2986+ return false ;
2987+ }
2988+ }
2989+ return true ;
2990+ };
2991+
2992+ isa.GetModule ()->GetSymtab ()->ForEachSymbolContainingFileAddress (
2993+ isa.GetFileAddress (), find_swift_symbol_for_isa);
2994+ if (!swift_symbol)
2995+ return {};
2996+
2997+ // Once the Swift symbol is found, demangle it into a node tree. The node tree
2998+ // provides the final data, the name of the class and the name of its module.
2999+ swift::Demangle::Context ctx;
3000+ auto *global = ctx.demangleSymbolAsNode (*swift_symbol);
3001+ using Kind = Node::Kind;
3002+ auto *class_node = swift_demangle::nodeAtPath (
3003+ global, {Kind::TypeMetadata, Kind::Type, Kind::Class});
3004+ if (class_node && class_node->getNumChildren () == 2 ) {
3005+ auto module_node = class_node->getFirstChild ();
3006+ auto ident_node = class_node->getLastChild ();
3007+ if (module_node->getKind () == Kind::Module && module_node->hasText () &&
3008+ ident_node->getKind () == Kind::Identifier && ident_node->hasText ()) {
3009+ auto module_name = module_node->getText ();
3010+ auto class_name = ident_node->getText ();
3011+ return SwiftNominalType{module_name.str (), class_name.str ()};
3012+ }
3013+ }
3014+
3015+ return {};
3016+ }
3017+
3018+ } // namespace
3019+
29443020bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_ClangType (
29453021 ValueObject &in_value, lldb::DynamicValueType use_dynamic,
29463022 TypeAndOrName &class_type_or_name, Address &address,
@@ -2967,9 +3043,22 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_ClangType(
29673043 dyn_name.startswith (" __NS" ))
29683044 return false ;
29693045
3046+ SwiftNominalType swift_class;
3047+
3048+ if (auto maybe_swift_class = GetSwiftClass (in_value, *objc_runtime)) {
3049+ swift_class = *maybe_swift_class;
3050+ std::string type_name =
3051+ (llvm::Twine (swift_class.module ) + " ." + swift_class.identifier ).str ();
3052+ dyn_class_type_or_name.SetName (type_name.data ());
3053+ address.SetRawAddress (in_value.GetPointerValue ());
3054+ } else {
3055+ swift_class.module = swift::MANGLING_MODULE_OBJC;
3056+ swift_class.identifier = dyn_name;
3057+ }
3058+
29703059 std::string remangled;
29713060 {
2972- // Create a mangle tree for __C.dyn_name?.
3061+ // Create a mangle tree for Swift.Optional<$module.$class>
29733062 using namespace swift ::Demangle;
29743063 NodeFactory factory;
29753064 NodePointer global = factory.createNode (Node::Kind::Global);
@@ -2980,7 +3069,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_ClangType(
29803069 NodePointer ety = factory.createNode (Node::Kind::Type);
29813070 bge->addChild (ety, factory);
29823071 NodePointer e = factory.createNode (Node::Kind::Enum);
2983- e->addChild (factory.createNode (Node::Kind::Module, " Swift" ), factory);
3072+ e->addChild (factory.createNode (Node::Kind::Module, swift::STDLIB_NAME),
3073+ factory);
29843074 e->addChild (factory.createNode (Node::Kind::Identifier, " Optional" ),
29853075 factory);
29863076 ety->addChild (e, factory);
@@ -2989,8 +3079,11 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_ClangType(
29893079 NodePointer cty = factory.createNode (Node::Kind::Type);
29903080 list->addChild (cty, factory);
29913081 NodePointer c = factory.createNode (Node::Kind::Class);
2992- c->addChild (factory.createNode (Node::Kind::Module, " __C" ), factory);
2993- c->addChild (factory.createNode (Node::Kind::Identifier, dyn_name), factory);
3082+ c->addChild (factory.createNode (Node::Kind::Module, swift_class.module ),
3083+ factory);
3084+ c->addChild (
3085+ factory.createNode (Node::Kind::Identifier, swift_class.identifier ),
3086+ factory);
29943087 cty->addChild (c, factory);
29953088
29963089 auto mangling = mangleNode (global);
0 commit comments