Skip to content

Commit 6cd2a78

Browse files
authored
Merge pull request #3960 from augusto2112/read-from-dsym-obj-file
[lldb] Read swift metadata from symbol rich binary
2 parents 552cbdb + 983632d commit 6cd2a78

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)