Skip to content

Commit 983632d

Browse files
committed
[lldb] Read swift metadata from symbol rich binary
In cases where Swift metadata is present in the symbol rich binary, read swift metadata from it instead of from the main binary or the process. This patch essentially re-uses the functionality implemented to read metadata from the file-cache to achieve this.
1 parent 0b8c8c6 commit 983632d

File tree

7 files changed

+181
-26
lines changed

7 files changed

+181
-26
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class TargetProperties : public Properties {
172172
bool GetSwiftReadMetadataFromFileCache() const;
173173

174174
bool GetSwiftUseReflectionSymbols() const;
175+
176+
bool GetSwiftReadMetadataFromDSYM() const;
175177

176178
bool GetEnableAutoImportClangModules() const;
177179

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

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address,
245245

246246
LLDB_LOGV(log, "[MemoryReader] asked to read {0} bytes at address {1:x}",
247247
size, address.getAddressData());
248+
if (readBytesFromSymbolObjectFile(address.getAddressData(), dest, size))
249+
return true;
248250

249251
llvm::Optional<Address> maybeAddr =
250252
resolveRemoteAddress(address.getAddressData());
@@ -349,10 +351,15 @@ void LLDBMemoryReader::popLocalBuffer() {
349351
}
350352

351353
llvm::Optional<std::pair<uint64_t, uint64_t>>
352-
LLDBMemoryReader::addModuleToAddressMap(ModuleSP module) {
354+
LLDBMemoryReader::addModuleToAddressMap(ModuleSP module, bool register_symbol_obj_file) {
353355
if (!readMetadataFromFileCacheEnabled())
354356
return {};
355357

358+
assert(register_symbol_obj_file <=
359+
m_process.GetTarget().GetSwiftReadMetadataFromDSYM() &&
360+
"Trying to register symbol object file, but reading from it is "
361+
"disabled!");
362+
356363
// The first available address is the mask, since subsequent images are mapped
357364
// in ascending order, all of them will contain this mask.
358365
uint64_t module_start_address = LLDB_FILE_ADDRESS_BIT;
@@ -374,7 +381,20 @@ LLDBMemoryReader::addModuleToAddressMap(ModuleSP module) {
374381
"LLDB file address bit clashes with an obj-c bit!");
375382
#endif
376383

377-
SectionList *section_list = module->GetObjectFile()->GetSectionList();
384+
ObjectFile *object_file;
385+
if (register_symbol_obj_file) {
386+
auto *symbol_file = module->GetSymbolFile();
387+
if (!symbol_file)
388+
return {};
389+
object_file = symbol_file->GetObjectFile();
390+
} else {
391+
object_file = module->GetObjectFile();
392+
}
393+
394+
if (!object_file)
395+
return {};
396+
397+
SectionList *section_list = object_file->GetSectionList();
378398

379399
auto section_list_size = section_list->GetSize();
380400
if (section_list_size == 0)
@@ -391,22 +411,27 @@ LLDBMemoryReader::addModuleToAddressMap(ModuleSP module) {
391411
// available after the end of the current image.
392412
uint64_t next_module_start_address = llvm::alignTo(module_end_address, 8);
393413
m_range_module_map.emplace_back(next_module_start_address, module);
414+
415+
if (register_symbol_obj_file)
416+
m_modules_with_metadata_in_symbol_obj_file.insert(module);
417+
394418
return {{module_start_address, module_end_address}};
395419
}
396420

397-
llvm::Optional<Address>
398-
LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
399-
Log *log = GetLog(LLDBLog::Types);
421+
llvm::Optional<std::pair<uint64_t, lldb::ModuleSP>>
422+
LLDBMemoryReader::getFileAddressAndModuleForTaggedAddress(
423+
uint64_t tagged_address) const {
424+
Log *log(GetLog(LLDBLog::Types));
400425

401426
if (!readMetadataFromFileCacheEnabled())
402-
return Address(address);
427+
return {};
403428

404429
// If the address contains our mask, this is an image we registered.
405-
if (!(address & LLDB_FILE_ADDRESS_BIT))
406-
return Address(address);
430+
if (!(tagged_address & LLDB_FILE_ADDRESS_BIT))
431+
return {};
407432

408433
// Dummy pair with the address we're looking for.
409-
auto comparison_pair = std::make_pair(address, ModuleSP());
434+
auto comparison_pair = std::make_pair(tagged_address, ModuleSP());
410435

411436
// Explicitly compare only the addresses, never the modules in the pairs.
412437
auto pair_iterator = std::lower_bound(
@@ -418,7 +443,7 @@ LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
418443
LLDB_LOG(log,
419444
"[MemoryReader] Address {0:x} is larger than the upper bound "
420445
"address of the mapped in modules",
421-
address);
446+
tagged_address);
422447
return {};
423448
}
424449

@@ -427,15 +452,31 @@ LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
427452
if (pair_iterator == m_range_module_map.begin())
428453
// Since this is the first registered module,
429454
// clearing the tag bit will give the virtual file address.
430-
file_address = address & ~LLDB_FILE_ADDRESS_BIT;
455+
file_address = tagged_address & ~LLDB_FILE_ADDRESS_BIT;
431456
else
432457
// The end of the previous section is the start of the current one.
433-
file_address = address - std::prev(pair_iterator)->first;
458+
file_address = tagged_address - std::prev(pair_iterator)->first;
434459

435460
LLDB_LOGV(log,
436461
"[MemoryReader] Successfully resolved mapped address {0:x} into "
437462
"file address {1:x}",
438-
address, file_address);
463+
tagged_address, file_address);
464+
return {{file_address, module}};
465+
}
466+
467+
llvm::Optional<Address>
468+
LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
469+
Log *log(GetLog(LLDBLog::Types));
470+
auto maybe_pair = getFileAddressAndModuleForTaggedAddress(address);
471+
if (!maybe_pair)
472+
return Address(address);
473+
474+
uint64_t file_address = maybe_pair->first;
475+
ModuleSP module = maybe_pair->second;
476+
477+
if (m_modules_with_metadata_in_symbol_obj_file.count(module))
478+
return Address(address);
479+
439480
auto *object_file = module->GetObjectFile();
440481
if (!object_file)
441482
return {};
@@ -456,6 +497,47 @@ LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
456497
return resolved;
457498
}
458499

500+
bool LLDBMemoryReader::readBytesFromSymbolObjectFile(uint64_t address, uint8_t *dest,
501+
uint64_t size) const {
502+
Log *log(GetLog(LLDBLog::Types));
503+
504+
if (!m_process.GetTarget().GetSwiftReadMetadataFromDSYM())
505+
return false;
506+
507+
auto maybe_pair = getFileAddressAndModuleForTaggedAddress(address);
508+
if (!maybe_pair)
509+
return false;
510+
511+
uint64_t file_address = maybe_pair->first;
512+
ModuleSP module = maybe_pair->second;
513+
514+
if (!m_modules_with_metadata_in_symbol_obj_file.count(module))
515+
return false;
516+
517+
auto *symbol_file = module->GetSymbolFile();
518+
if (!symbol_file)
519+
return false;
520+
521+
auto *object_file = symbol_file->GetObjectFile();
522+
if (!object_file)
523+
return false;
524+
525+
Address resolved(file_address, object_file->GetSectionList());
526+
if (!resolved.IsSectionOffset()) {
527+
LLDB_LOG(log,
528+
"[MemoryReader] Could not make a real address out of file address "
529+
"{0:x} and object file {1}",
530+
file_address, object_file->GetFileSpec().GetFilename());
531+
return false;
532+
}
533+
534+
LLDB_LOGV(log, "[MemoryReader] Reading memory from symbol rich binary");
535+
536+
auto section = resolved.GetSection();
537+
return object_file->ReadSectionData(section.get(), resolved.GetOffset(),
538+
dest, size);
539+
}
540+
459541
bool LLDBMemoryReader::readMetadataFromFileCacheEnabled() const {
460542
auto &triple = m_process.GetTarget().GetArchitecture().GetTriple();
461543

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,17 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
4545
/// \return a pair of addresses indicating the start and end of this image in
4646
/// the tagged address space. None on failure.
4747
llvm::Optional<std::pair<uint64_t, uint64_t>>
48-
addModuleToAddressMap(lldb::ModuleSP module);
49-
48+
addModuleToAddressMap(lldb::ModuleSP module, bool register_symbol_obj_file);
49+
5050
/// Returns whether the filecache optimization is enabled or not.
5151
bool readMetadataFromFileCacheEnabled() const;
5252

5353
private:
54+
/// Gets the file address and module that were mapped to a given tagged
55+
/// address.
56+
llvm::Optional<std::pair<uint64_t, lldb::ModuleSP>>
57+
getFileAddressAndModuleForTaggedAddress(uint64_t tagged_address) const;
58+
5459
/// Resolves the address by either mapping a tagged address back to an LLDB
5560
/// Address with section + offset, or, in case the address is not tagged,
5661
/// constructing an LLDB address with just the offset.
@@ -60,6 +65,11 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
6065
/// Address.
6166
llvm::Optional<Address> resolveRemoteAddress(uint64_t address) const;
6267

68+
/// Reads memory from the symbol rich binary from the address into dest.
69+
/// \return true if it was able to successfully read memory.
70+
bool readBytesFromSymbolObjectFile(uint64_t address, uint8_t *dest,
71+
uint64_t size) const;
72+
6373
private:
6474
Process &m_process;
6575
size_t m_max_read_amount;
@@ -77,6 +87,10 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
7787
/// module's virtual address space.
7888
std::vector<std::pair<uint64_t, lldb::ModuleSP>> m_range_module_map;
7989

90+
/// The set of modules where we should read memory from the symbol file's
91+
/// object file instead of the main object file.
92+
std::unordered_set<lldb::ModuleSP> m_modules_with_metadata_in_symbol_obj_file;
93+
8094
/// The bit used to tag LLDB's virtual addresses as such. See \c
8195
/// m_range_module_map.
8296
const static uint64_t LLDB_FILE_ADDRESS_BIT = 0x2000000000000000;

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

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -644,30 +644,74 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext(
644644
}
645645

646646
bool SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext(
647-
ModuleSP module, ObjectFile &obj_file) {
647+
ModuleSP module) {
648648
auto obj_format_type =
649-
module->GetArchitecture().GetTriple().getObjectFormat();
649+
module->GetArchitecture().GetTriple().getObjectFormat();
650650

651651
auto obj_file_format = GetObjectFileFormat(obj_format_type);
652652
if (!obj_file_format)
653653
return false;
654654

655-
llvm::Optional<llvm::StringRef> maybe_segment_name =
656-
obj_file_format->getSegmentName();
655+
bool should_register_with_symbol_obj_file = [&]() -> bool {
656+
if (!m_process.GetTarget().GetSwiftReadMetadataFromDSYM())
657+
return false;
658+
auto *symbol_file = module->GetSymbolFile();
659+
if (!symbol_file)
660+
return false;
661+
auto *sym_obj_file = symbol_file->GetObjectFile();
662+
if (!sym_obj_file)
663+
return false;
664+
665+
llvm::Optional<llvm::StringRef> maybe_segment_name =
666+
obj_file_format->getSymbolRichSegmentName();
667+
if (!maybe_segment_name)
668+
return false;
669+
670+
llvm::StringRef segment_name = *maybe_segment_name;
671+
672+
auto *section_list = sym_obj_file->GetSectionList();
673+
auto segment_iter = llvm::find_if(*section_list, [&](auto segment) {
674+
return segment->GetName() == segment_name.begin();
675+
});
676+
677+
if (segment_iter == section_list->end())
678+
return false;
679+
680+
auto *segment = segment_iter->get();
681+
682+
auto section_iter =
683+
llvm::find_if(segment->GetChildren(), [&](auto section) {
684+
return obj_file_format->sectionContainsReflectionData(
685+
section->GetName().GetStringRef());
686+
});
687+
return section_iter != segment->GetChildren().end();
688+
}();
689+
690+
llvm::Optional<llvm::StringRef> maybe_segment_name;
691+
ObjectFile *object_file;
692+
if (should_register_with_symbol_obj_file) {
693+
maybe_segment_name = obj_file_format->getSymbolRichSegmentName();
694+
object_file = module->GetSymbolFile()->GetObjectFile();
695+
} else {
696+
maybe_segment_name = obj_file_format->getSegmentName();
697+
object_file = module->GetObjectFile();
698+
}
699+
657700
if (!maybe_segment_name)
658701
return false;
659702

660703
llvm::StringRef segment_name = *maybe_segment_name;
704+
661705
auto lldb_memory_reader = GetMemoryReader();
662-
auto maybe_start_and_end =
663-
lldb_memory_reader->addModuleToAddressMap(module);
706+
auto maybe_start_and_end = lldb_memory_reader->addModuleToAddressMap(
707+
module, should_register_with_symbol_obj_file);
664708
if (!maybe_start_and_end)
665709
return false;
666710

667711
uint64_t start_address, end_address;
668712
std::tie(start_address, end_address) = *maybe_start_and_end;
669713

670-
auto *section_list = obj_file.GetSectionList();
714+
auto *section_list = object_file->GetSectionList();
671715
auto segment_iter = llvm::find_if(*section_list, [&](auto segment) {
672716
return segment->GetName() == segment_name.begin();
673717
});
@@ -680,8 +724,7 @@ bool SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext(
680724
return m_reflection_ctx->addImage(
681725
[&](swift::ReflectionSectionKind section_kind)
682726
-> std::pair<swift::remote::RemoteRef<void>, uint64_t> {
683-
auto section_name =
684-
obj_file_format->getSectionName(section_kind);
727+
auto section_name = obj_file_format->getSectionName(section_kind);
685728
for (auto section : segment->GetChildren()) {
686729
// Iterate over the sections until we find the reflection section we
687730
// need.
@@ -764,7 +807,7 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext(
764807
llvm::Optional<llvm::sys::MemoryBlock>(file_buffer));
765808
} else if (read_from_file_cache &&
766809
obj_file->GetPluginName().equals("mach-o")) {
767-
if (!AddObjectFileToReflectionContext(module_sp, *obj_file))
810+
if (!AddObjectFileToReflectionContext(module_sp))
768811
m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr));
769812
} else {
770813
m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr));

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ class SwiftLanguageRuntimeImpl {
393393
/// the directly from the object file.
394394
/// \return true on success.
395395
bool AddObjectFileToReflectionContext(
396-
lldb::ModuleSP module, ObjectFile &obj_file);
396+
lldb::ModuleSP module);
397397

398398
/// Cache for the debug-info-originating type infos.
399399
/// \{

lldb/source/Target/Target.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4194,6 +4194,17 @@ bool TargetProperties::GetSwiftUseReflectionSymbols() const {
41944194
return true;
41954195
}
41964196

4197+
bool TargetProperties::GetSwiftReadMetadataFromDSYM() const {
4198+
const Property *exp_property = m_collection_sp->GetPropertyAtIndex(
4199+
nullptr, false, ePropertyExperimental);
4200+
OptionValueProperties *exp_values =
4201+
exp_property->GetValue()->GetAsProperties();
4202+
if (exp_values)
4203+
return exp_values->GetPropertyAtIndexAsBoolean(
4204+
nullptr, ePropertySwiftReadMetadataFromDSYM, true);
4205+
4206+
return true;
4207+
}
41974208
ArchSpec TargetProperties::GetDefaultArchitecture() const {
41984209
OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(
41994210
nullptr, ePropertyDefaultArch);

lldb/source/Target/TargetProperties.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ let Definition = "target_experimental" in {
1010
def SwiftUseReflectionSymbols : Property<"swift-use-reflection-symbols", "Boolean">,
1111
Global, DefaultTrue,
1212
Desc<"if true, optimize the loading of Swift reflection metadata by making use of available symbols.">;
13+
def SwiftReadMetadataFromDSYM: Property<"swift-read-metadata-from-dsym", "Boolean">,
14+
DefaultFalse,
15+
Desc<"Read Swift reflection metadata from the dsym instead of the process when possible">;
1316
}
1417

1518
let Definition = "target" in {

0 commit comments

Comments
 (0)