Skip to content

Commit c075079

Browse files
committed
Move the TLS code to the DYLD
1 parent 1d28563 commit c075079

File tree

4 files changed

+98
-67
lines changed

4 files changed

+98
-67
lines changed

lldb/include/lldb/Target/DynamicLoader.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "lldb/lldb-forward.h"
1919
#include "lldb/lldb-private-enumerations.h"
2020
#include "lldb/lldb-types.h"
21+
#include "lldb/Target/CoreFileMemoryRanges.h"
2122

2223
#include <cstddef>
2324
#include <cstdint>
@@ -337,6 +338,13 @@ class DynamicLoader : public PluginInterface {
337338
return std::nullopt;
338339
}
339340

341+
/// Returns a list of memory ranges that should be saved in the core file,
342+
/// specific for this dßynamic loader.
343+
///
344+
/// By default, this returns an empty list, but for POSIX/ELF it will return
345+
/// the link map, and the TLS data.
346+
virtual void CalculateDynamicSaveCoreRanges(lldb_private::Process &process, std::vector<lldb_private::MemoryRegionInfo> &ranges, std::function<bool(const lldb_private::Thread&)> save_thread_predicate) {};
347+
340348
protected:
341349
// Utility methods for derived classes
342350

lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "lldb/Symbol/ObjectFile.h"
1919
#include "lldb/Target/MemoryRegionInfo.h"
2020
#include "lldb/Target/Platform.h"
21+
#include "lldb/Target/RegisterContext.h"
2122
#include "lldb/Target/Target.h"
2223
#include "lldb/Target/Thread.h"
2324
#include "lldb/Target/ThreadPlanRunToAddress.h"
@@ -866,3 +867,77 @@ bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(
866867
bool DynamicLoaderPOSIXDYLD::IsCoreFile() const {
867868
return !m_process->IsLiveDebugSession();
868869
}
870+
871+
// For our ELF/POSIX builds save off the fs_base/gs_base regions
872+
static void AddSegmentRegisterSections(Process &process, ThreadSP &thread_sp,
873+
std::vector<MemoryRegionInfo> &ranges) {
874+
lldb::RegisterContextSP reg_ctx = thread_sp->GetRegisterContext();
875+
if (!reg_ctx)
876+
return;
877+
878+
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
879+
lldb::RegisterKind::eRegisterKindGeneric, LLDB_REGNUM_GENERIC_TP);
880+
if (!reg_info)
881+
return;
882+
883+
lldb_private::RegisterValue thread_local_register_value;
884+
bool success = reg_ctx->ReadRegister(reg_info, thread_local_register_value);
885+
if (!success)
886+
return;
887+
888+
const uint64_t fail_value = UINT64_MAX;
889+
bool readSuccess = false;
890+
const lldb::addr_t reg_value_addr =
891+
thread_local_register_value.GetAsUInt64(fail_value, &readSuccess);
892+
if (!readSuccess || reg_value_addr == fail_value)
893+
return;
894+
895+
MemoryRegionInfo thread_local_region;
896+
Status err = process.GetMemoryRegionInfo(reg_value_addr, thread_local_region);
897+
if (err.Fail())
898+
return;
899+
900+
ranges.push_back(thread_local_region);
901+
}
902+
903+
// Save off the link map for core files.
904+
static void AddLinkMapSections(Process &process, std::vector<MemoryRegionInfo> &ranges) {
905+
ModuleList &module_list = process.GetTarget().GetImages();
906+
Target *target = &process.GetTarget();
907+
for (size_t idx = 0; idx < module_list.GetSize(); idx++) {
908+
ModuleSP module_sp = module_list.GetModuleAtIndex(idx);
909+
if (!module_sp)
910+
continue;
911+
912+
ObjectFile *obj = module_sp->GetObjectFile();
913+
if (!obj)
914+
continue;
915+
Address addr = obj->GetImageInfoAddress(target);
916+
addr_t load_addr = addr.GetLoadAddress(target);
917+
if (load_addr == LLDB_INVALID_ADDRESS)
918+
continue;
919+
920+
MemoryRegionInfo link_map_section;
921+
Status err = process.GetMemoryRegionInfo(load_addr, link_map_section);
922+
if (err.Fail())
923+
continue;
924+
925+
ranges.push_back(link_map_section);
926+
}
927+
}
928+
929+
void DynamicLoaderPOSIXDYLD::CalculateDynamicSaveCoreRanges(lldb_private::Process &process, std::vector<lldb_private::MemoryRegionInfo> &ranges, std::function<bool(const lldb_private::Thread&)> save_thread_predicate) {
930+
ThreadList &thread_list = process.GetThreadList();
931+
for (size_t idx = 0; idx < thread_list.GetSize(); idx++) {
932+
ThreadSP thread_sp = thread_list.GetThreadAtIndex(idx);
933+
if (!thread_sp)
934+
continue;
935+
936+
if (!save_thread_predicate(*thread_sp.get()))
937+
continue;
938+
939+
AddSegmentRegisterSections(process, thread_sp, ranges);
940+
}
941+
942+
AddLinkMapSections(process, ranges);
943+
}

lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader {
6060
lldb::addr_t base_addr,
6161
bool base_addr_is_offset) override;
6262

63+
void CalculateDynamicSaveCoreRanges(lldb_private::Process &process, std::vector<lldb_private::MemoryRegionInfo> &ranges, std::function<bool(const lldb_private::Thread&)> save_thread_predicate) override;
64+
6365
protected:
6466
/// Runtime linker rendezvous structure.
6567
DYLDRendezvous m_rendezvous;

lldb/source/Target/Process.cpp

Lines changed: 13 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6539,72 +6539,18 @@ static void AddRegion(const MemoryRegionInfo &region, bool try_dirty_pages,
65396539
CreateCoreFileMemoryRange(region));
65406540
}
65416541

6542-
static void AddSegmentRegisterSections(Process &process, ThreadSP &thread_sp,
6543-
CoreFileMemoryRanges &ranges,
6544-
lldb::addr_t range_end) {
6545-
lldb::RegisterContextSP reg_ctx = thread_sp->GetRegisterContext();
6546-
if (!reg_ctx)
6542+
static void SaveDynamicLoaderSections(Process &process, const SaveCoreOptions &options, CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
6543+
DynamicLoader *dyld = process.GetDynamicLoader();
6544+
if (!dyld)
65476545
return;
65486546

6549-
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
6550-
lldb::RegisterKind::eRegisterKindGeneric, LLDB_REGNUM_GENERIC_TP);
6551-
if (!reg_info)
6552-
return;
6553-
6554-
lldb_private::RegisterValue thread_local_register_value;
6555-
bool success = reg_ctx->ReadRegister(reg_info, thread_local_register_value);
6556-
if (!success)
6557-
return;
6558-
6559-
const uint64_t fail_value = UINT64_MAX;
6560-
bool readSuccess = false;
6561-
const lldb::addr_t reg_value_addr =
6562-
thread_local_register_value.GetAsUInt64(fail_value, &readSuccess);
6563-
if (!readSuccess || reg_value_addr == fail_value)
6564-
return;
6565-
6566-
MemoryRegionInfo thread_local_region;
6567-
Status err = process.GetMemoryRegionInfo(reg_value_addr, thread_local_region);
6568-
if (err.Fail())
6569-
return;
6570-
6571-
// We already saved off this truncated stack range.
6572-
if (thread_local_region.GetRange().GetRangeEnd() == range_end)
6573-
return;
6574-
6575-
// We don't need to worry about duplication because the CoreFileMemoryRanges
6576-
// will unique them
6577-
AddRegion(thread_local_region, true, ranges);
6578-
}
6579-
6580-
static void AddLinkMapSections(Process &process, CoreFileMemoryRanges &ranges,
6581-
std::set<addr_t> &stack_ends) {
6582-
ModuleList &module_list = process.GetTarget().GetImages();
6583-
Target *target = &process.GetTarget();
6584-
for (size_t idx = 0; idx < module_list.GetSize(); idx++) {
6585-
ModuleSP module_sp = module_list.GetModuleAtIndex(idx);
6586-
if (!module_sp)
6587-
continue;
6588-
6589-
ObjectFile *obj = module_sp->GetObjectFile();
6590-
if (!obj)
6591-
continue;
6592-
Address addr = obj->GetImageInfoAddress(target);
6593-
addr_t load_addr = addr.GetLoadAddress(target);
6594-
if (load_addr == LLDB_INVALID_ADDRESS)
6595-
continue;
6596-
6597-
MemoryRegionInfo link_map_section;
6598-
Status err = process.GetMemoryRegionInfo(load_addr, link_map_section);
6599-
if (err.Fail())
6600-
continue;
6601-
6602-
// Sometimes, the link map section is included in one of the stack memory
6603-
// ranges. In that case, we already saved a truncated version of that range
6604-
if (stack_ends.count(link_map_section.GetRange().GetRangeEnd()) == 0)
6605-
continue;
6606-
6607-
AddRegion(link_map_section, true, ranges);
6547+
std::vector<MemoryRegionInfo> dynamic_loader_mem_regions;
6548+
std::function<bool(const lldb_private::Thread&)> save_thread_predicate = [&](const lldb_private::Thread &t) -> bool { return options.ShouldThreadBeSaved(t.GetID()); };
6549+
dyld->CalculateDynamicSaveCoreRanges(process, dynamic_loader_mem_regions, save_thread_predicate);
6550+
for (const auto &region : dynamic_loader_mem_regions) {
6551+
// The Dynamic Loader can give us regions that could include a truncated stack
6552+
if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0)
6553+
AddRegion(region, true, ranges);
66086554
}
66096555
}
66106556

@@ -6645,7 +6591,6 @@ static void SaveOffRegionsWithStackPointers(Process &process,
66456591
// or contains the thread id from thread_sp.
66466592
if (core_options.ShouldThreadBeSaved(thread_sp->GetID())) {
66476593
AddRegion(sp_region, try_dirty_pages, ranges);
6648-
AddSegmentRegisterSections(process, thread_sp, ranges, range_end);
66496594
}
66506595
}
66516596
}
@@ -6759,8 +6704,9 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
67596704
options.HasSpecifiedThreads()) {
67606705
SaveOffRegionsWithStackPointers(*this, options, regions, ranges,
67616706
stack_ends);
6762-
// We need the link map for TLS data.
6763-
AddLinkMapSections(*this, ranges, stack_ends);
6707+
// Save off the dynamic loader sections, so if we are on an architecture that supports
6708+
// Thread Locals, that we include those as well.
6709+
SaveDynamicLoaderSections(*this, options, ranges, stack_ends);
67646710
}
67656711

67666712
switch (core_style) {

0 commit comments

Comments
 (0)