Skip to content

Commit b26f763

Browse files
committed
Add support for 32-bit reflection contexts.
This patch introduces a wrapper ReflectionContextInterface that encapsulates all traffic to ReflectionContext and abstracts the detail that ReflectionContext is a template that needs to be specialized for a specific pointer width. This fixes various TypeSystemSwiftTypeRef issues when debugging on an arm64_32 Apple Watch. rdar://83959667
1 parent f0f0299 commit b26f763

File tree

3 files changed

+226
-65
lines changed

3 files changed

+226
-65
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ static bool HasReflectionInfo(ObjectFile *obj_file) {
412412
return hasReflectionSection;
413413
}
414414

415-
SwiftLanguageRuntimeImpl::NativeReflectionContext *
415+
SwiftLanguageRuntimeImpl::ReflectionContextInterface *
416416
SwiftLanguageRuntimeImpl::GetReflectionContext() {
417417
if (!m_initialized_reflection_ctx)
418418
SetupReflection();
@@ -438,7 +438,21 @@ void SwiftLanguageRuntimeImpl::SetupReflection() {
438438
if (m_initialized_reflection_ctx)
439439
return;
440440

441-
m_reflection_ctx.reset(new NativeReflectionContext(this->GetMemoryReader()));
441+
auto &target = m_process.GetTarget();
442+
if (auto exe_module = target.GetExecutableModule()) {
443+
auto &triple = exe_module->GetArchitecture().GetTriple();
444+
if (triple.isArch64Bit())
445+
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64(
446+
this->GetMemoryReader());
447+
else if (triple.isArch32Bit())
448+
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32(
449+
this->GetMemoryReader());
450+
else {
451+
LLDB_LOGF(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
452+
"Could not initialize reflection context for \"%s\"",
453+
triple.str().c_str());
454+
}
455+
}
442456
m_initialized_reflection_ctx = true;
443457

444458
// Add all defered modules to reflection context that were added to

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 150 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,142 @@ lldb::addr_t SwiftLanguageRuntime::MaybeMaskNonTrivialReferencePointer(
250250
return addr;
251251
}
252252

253+
namespace {
254+
255+
/// An implementation of the generic ReflectionContextInterface that
256+
/// is templatized on target pointer width and specialized to either
257+
/// 32-bit or 64-bit pointers.
258+
template <unsigned PointerSize>
259+
class TargetReflectionContext
260+
: public SwiftLanguageRuntimeImpl::ReflectionContextInterface {
261+
using ReflectionContext = swift::reflection::ReflectionContext<
262+
swift::External<swift::RuntimeTarget<PointerSize>>>;
263+
ReflectionContext m_reflection_ctx;
264+
265+
public:
266+
TargetReflectionContext(
267+
std::shared_ptr<swift::reflection::MemoryReader> reader)
268+
: m_reflection_ctx(reader) {}
269+
270+
bool addImage(
271+
llvm::function_ref<std::pair<swift::remote::RemoteRef<void>, uint64_t>(
272+
swift::ReflectionSectionKind)>
273+
find_section) override {
274+
return m_reflection_ctx.addImage(find_section);
275+
}
276+
277+
bool addImage(swift::remote::RemoteAddress image_start) override {
278+
return m_reflection_ctx.addImage(image_start);
279+
}
280+
281+
bool readELF(swift::remote::RemoteAddress ImageStart,
282+
llvm::Optional<llvm::sys::MemoryBlock> FileBuffer) override {
283+
return m_reflection_ctx.readELF(ImageStart, FileBuffer);
284+
}
285+
286+
const swift::reflection::TypeInfo *
287+
getTypeInfo(const swift::reflection::TypeRef *type_ref,
288+
swift::remote::TypeInfoProvider *provider) override {
289+
return m_reflection_ctx.getTypeInfo(type_ref, provider);
290+
}
291+
292+
swift::reflection::MemoryReader &getReader() override {
293+
return m_reflection_ctx.getReader();
294+
}
295+
296+
bool ForEachSuperClassType(
297+
LLDBTypeInfoProvider *tip, lldb::addr_t pointer,
298+
std::function<bool(SwiftLanguageRuntimeImpl::SuperClassType)> fn)
299+
override {
300+
auto md_ptr = m_reflection_ctx.readMetadataFromInstance(pointer);
301+
if (!md_ptr)
302+
return false;
303+
304+
// Class object.
305+
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
306+
"found RecordTypeInfo for instance");
307+
while (md_ptr && *md_ptr) {
308+
// Reading metadata is potentially expensive since (in a remote
309+
// debugging scenario it may even incur network traffic) so we
310+
// just return closures that the caller can use to query details
311+
// if they need them.'
312+
auto metadata = *md_ptr;
313+
if (fn({[=]() -> const swift::reflection::RecordTypeInfo * {
314+
auto *ti = m_reflection_ctx.getMetadataTypeInfo(metadata, tip);
315+
return llvm::dyn_cast_or_null<
316+
swift::reflection::RecordTypeInfo>(ti);
317+
},
318+
[=]() -> const swift::reflection::TypeRef * {
319+
return m_reflection_ctx.readTypeFromMetadata(metadata);
320+
}}))
321+
return true;
322+
323+
// Continue with the base class.
324+
md_ptr = m_reflection_ctx.readSuperClassFromClassMetadata(metadata);
325+
}
326+
return false;
327+
}
328+
329+
llvm::Optional<std::pair<const swift::reflection::TypeRef *,
330+
swift::reflection::RemoteAddress>>
331+
projectExistentialAndUnwrapClass(
332+
swift::reflection::RemoteAddress existential_address,
333+
const swift::reflection::TypeRef &existential_tr) override {
334+
return m_reflection_ctx.projectExistentialAndUnwrapClass(
335+
existential_address, existential_tr);
336+
}
337+
338+
const swift::reflection::TypeRef *
339+
readTypeFromMetadata(lldb::addr_t metadata_address,
340+
bool skip_artificial_subclasses) override {
341+
return m_reflection_ctx.readTypeFromMetadata(metadata_address,
342+
skip_artificial_subclasses);
343+
}
344+
345+
const swift::reflection::TypeRef *
346+
readTypeFromInstance(lldb::addr_t instance_address,
347+
bool skip_artificial_subclasses) override {
348+
auto metadata_address =
349+
m_reflection_ctx.readMetadataFromInstance(instance_address);
350+
if (!metadata_address) {
351+
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
352+
"could not read heap metadata for object at %llu\n",
353+
instance_address);
354+
return nullptr;
355+
}
356+
357+
return m_reflection_ctx.readTypeFromMetadata(*metadata_address,
358+
skip_artificial_subclasses);
359+
}
360+
361+
swift::reflection::TypeRefBuilder &getBuilder() override {
362+
return m_reflection_ctx.getBuilder();
363+
}
364+
365+
llvm::Optional<bool> isValueInlinedInExistentialContainer(
366+
swift::remote::RemoteAddress existential_address) override {
367+
return m_reflection_ctx.isValueInlinedInExistentialContainer(
368+
existential_address);
369+
}
370+
};
371+
372+
} // namespace
373+
374+
std::unique_ptr<SwiftLanguageRuntimeImpl::ReflectionContextInterface>
375+
SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext32(
376+
std::shared_ptr<swift::remote::MemoryReader> reader) {
377+
return std::make_unique<TargetReflectionContext<4>>(reader);
378+
}
379+
380+
std::unique_ptr<SwiftLanguageRuntimeImpl::ReflectionContextInterface>
381+
SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext64(
382+
std::shared_ptr<swift::remote::MemoryReader> reader) {
383+
return std::make_unique<TargetReflectionContext<8>>(reader);
384+
}
385+
386+
SwiftLanguageRuntimeImpl::ReflectionContextInterface::
387+
~ReflectionContextInterface() {}
388+
253389
const CompilerType &SwiftLanguageRuntimeImpl::GetBoxMetadataType() {
254390
if (m_box_metadata_type.IsValid())
255391
return m_box_metadata_type;
@@ -634,6 +770,8 @@ class ASTVerifier : public swift::ASTWalker {
634770
}
635771
};
636772

773+
} // namespace
774+
637775
class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
638776
SwiftLanguageRuntimeImpl &m_runtime;
639777
TypeSystemSwift &m_typesystem;
@@ -712,7 +850,8 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
712850
if (is_bitfield_ptr) {
713851
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
714852
if (log)
715-
log->Printf("[LLDBTypeInfoProvider] bitfield support is not yet implemented");
853+
log->Printf("[LLDBTypeInfoProvider] bitfield support is not yet "
854+
"implemented");
716855
continue;
717856
}
718857
swift::reflection::FieldInfo field_info = {
@@ -725,8 +864,6 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
725864
}
726865
};
727866

728-
} // namespace
729-
730867
llvm::Optional<const swift::reflection::TypeInfo *>
731868
SwiftLanguageRuntimeImpl::lookupClangTypeInfo(CompilerType clang_type) {
732869
std::lock_guard<std::recursive_mutex> locker(m_clang_type_info_mutex);
@@ -1574,35 +1711,9 @@ bool SwiftLanguageRuntimeImpl::ForEachSuperClassType(
15741711
if (!ts)
15751712
return false;
15761713

1714+
LLDBTypeInfoProvider tip(*this, *ts);
15771715
lldb::addr_t pointer = instance.GetPointerValue();
1578-
auto md_ptr = reflection_ctx->readMetadataFromInstance(pointer);
1579-
if (!md_ptr)
1580-
return false;
1581-
1582-
// Class object.
1583-
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
1584-
"found RecordTypeInfo for instance");
1585-
while (md_ptr && *md_ptr) {
1586-
// Reading metadata is potentially expensive since (in a remote
1587-
// debugging scenario it may even incur network traffic) so we
1588-
// just return closures that the caller can use to query details
1589-
// if they need them.
1590-
auto metadata = *md_ptr;
1591-
if (fn({[=]() -> const swift::reflection::RecordTypeInfo * {
1592-
LLDBTypeInfoProvider tip(*this, *ts);
1593-
auto *ti = reflection_ctx->getMetadataTypeInfo(metadata, &tip);
1594-
return llvm::dyn_cast_or_null<swift::reflection::RecordTypeInfo>(
1595-
ti);
1596-
},
1597-
[=]() -> const swift::reflection::TypeRef * {
1598-
return reflection_ctx->readTypeFromMetadata(metadata);
1599-
}}))
1600-
return true;
1601-
1602-
// Continue with the base class.
1603-
md_ptr = reflection_ctx->readSuperClassFromClassMetadata(metadata);
1604-
}
1605-
return false;
1716+
return reflection_ctx->ForEachSuperClassType(&tip, pointer, fn);
16061717
}
16071718

16081719
bool SwiftLanguageRuntime::IsSelf(Variable &variable) {
@@ -1673,16 +1784,16 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
16731784
lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name,
16741785
Address &address) {
16751786
AddressType address_type;
1676-
lldb::addr_t class_metadata_ptr = in_value.GetPointerValue(&address_type);
1677-
if (class_metadata_ptr == LLDB_INVALID_ADDRESS || class_metadata_ptr == 0)
1787+
lldb::addr_t instance_ptr = in_value.GetPointerValue(&address_type);
1788+
if (instance_ptr == LLDB_INVALID_ADDRESS || instance_ptr == 0)
16781789
return false;
16791790

16801791
CompilerType static_type = in_value.GetCompilerType();
16811792
auto *tss =
16821793
llvm::dyn_cast_or_null<TypeSystemSwift>(static_type.GetTypeSystem());
16831794
if (!tss)
16841795
return false;
1685-
address.SetRawAddress(class_metadata_ptr);
1796+
address.SetRawAddress(instance_ptr);
16861797
auto &ts = tss->GetTypeSystemSwiftTypeRef();
16871798
// Ask the Objective-C runtime about Objective-C types.
16881799
if (tss->IsImportedType(static_type.GetOpaqueQualType(), nullptr))
@@ -1712,19 +1823,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
17121823
}
17131824
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
17141825
auto *reflection_ctx = GetReflectionContext();
1715-
swift::remote::RemoteAddress instance_address(class_metadata_ptr);
1716-
auto metadata_address =
1717-
reflection_ctx->readMetadataFromInstance(class_metadata_ptr);
1718-
if (!metadata_address) {
1719-
if (log)
1720-
log->Printf("could not read heap metadata for object at %llu\n",
1721-
class_metadata_ptr);
1722-
return false;
1723-
}
1724-
1725-
const auto *typeref =
1726-
reflection_ctx->readTypeFromMetadata(*metadata_address,
1727-
/*skipArtificial=*/false);
1826+
const auto *typeref = reflection_ctx->readTypeFromInstance(instance_ptr);
17281827
if (!typeref)
17291828
return false;
17301829
swift::Demangle::Demangler dem;
@@ -1733,8 +1832,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
17331832

17341833
#ifndef NDEBUG
17351834
auto &remote_ast = GetRemoteASTContext(scratch_ctx);
1736-
auto remote_ast_metadata_address =
1737-
remote_ast.getHeapMetadataForObject(instance_address);
1835+
auto remote_ast_metadata_address = remote_ast.getHeapMetadataForObject(
1836+
swift::remote::RemoteAddress(instance_ptr));
17381837
if (remote_ast_metadata_address) {
17391838
auto instance_type = remote_ast.getTypeForRemoteTypeMetadata(
17401839
remote_ast_metadata_address.getValue(),
@@ -1748,9 +1847,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
17481847
<< "\n";
17491848
} else {
17501849
if (log) {
1751-
log->Printf(
1752-
"could not get type metadata from address %" PRIu64 " : %s\n",
1753-
*metadata_address, instance_type.getFailure().render().c_str());
1850+
log->Printf("could not get type metadata: %s\n",
1851+
instance_type.getFailure().render().c_str());
17541852
}
17551853
}
17561854
}

0 commit comments

Comments
 (0)