Skip to content

Commit dc2cd8f

Browse files
committed
Move the TLS code to the DYLD
1 parent 36a91b1 commit dc2cd8f

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
@@ -6528,72 +6528,18 @@ static void AddRegion(const MemoryRegionInfo &region, bool try_dirty_pages,
65286528
CreateCoreFileMemoryRange(region));
65296529
}
65306530

6531-
static void AddSegmentRegisterSections(Process &process, ThreadSP &thread_sp,
6532-
CoreFileMemoryRanges &ranges,
6533-
lldb::addr_t range_end) {
6534-
lldb::RegisterContextSP reg_ctx = thread_sp->GetRegisterContext();
6535-
if (!reg_ctx)
6531+
static void SaveDynamicLoaderSections(Process &process, const SaveCoreOptions &options, CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
6532+
DynamicLoader *dyld = process.GetDynamicLoader();
6533+
if (!dyld)
65366534
return;
65376535

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

@@ -6634,7 +6580,6 @@ static void SaveOffRegionsWithStackPointers(Process &process,
66346580
// or contains the thread id from thread_sp.
66356581
if (core_options.ShouldThreadBeSaved(thread_sp->GetID())) {
66366582
AddRegion(sp_region, try_dirty_pages, ranges);
6637-
AddSegmentRegisterSections(process, thread_sp, ranges, range_end);
66386583
}
66396584
}
66406585
}
@@ -6748,8 +6693,9 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
67486693
options.HasSpecifiedThreads()) {
67496694
SaveOffRegionsWithStackPointers(*this, options, regions, ranges,
67506695
stack_ends);
6751-
// We need the link map for TLS data.
6752-
AddLinkMapSections(*this, ranges, stack_ends);
6696+
// Save off the dynamic loader sections, so if we are on an architecture that supports
6697+
// Thread Locals, that we include those as well.
6698+
SaveDynamicLoaderSections(*this, options, ranges, stack_ends);
67536699
}
67546700

67556701
switch (core_style) {

0 commit comments

Comments
 (0)