[lldb][ARM] Support thread local variables on ARM Linux - #181315
Conversation
|
@llvm/pr-subscribers-lldb Author: Igor Kudrin (igorkudrin) ChangesThis implements reading the thread pointer register ( Full diff: https://github.com/llvm/llvm-project/pull/181315.diff 12 Files Affected:
diff --git a/lldb/include/lldb/Host/linux/Ptrace.h b/lldb/include/lldb/Host/linux/Ptrace.h
index aabd3fd4fc557..233ef962782c7 100644
--- a/lldb/include/lldb/Host/linux/Ptrace.h
+++ b/lldb/include/lldb/Host/linux/Ptrace.h
@@ -38,9 +38,15 @@ typedef int __ptrace_request;
#ifndef PTRACE_SETREGSET
#define PTRACE_SETREGSET 0x4205
#endif
+
#ifndef PTRACE_GET_THREAD_AREA
+#ifdef __arm__
+#define PTRACE_GET_THREAD_AREA 22
+#else
#define PTRACE_GET_THREAD_AREA 25
-#endif
+#endif // __arm__
+#endif // PTRACE_GET_THREAD_AREA
+
#ifndef PTRACE_ARCH_PRCTL
#define PTRACE_ARCH_PRCTL 30
#endif
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 1a9c4593b1b4f..f9c29b95185dc 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -714,7 +714,8 @@ bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,
return false;
Address address = list[0].symbol->GetAddress();
- address.SetOffset(address.GetOffset() + field * sizeof(uint32_t));
+ int field_num = (field == eStructSize) ? 0 : field;
+ address.SetOffset(address.GetOffset() + field_num * sizeof(uint32_t));
// Read from target memory as this allows us to try process memory and
// fallback to reading from read only sections from the object files. Here we
@@ -737,6 +738,8 @@ const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {
if (!m_thread_info.valid) {
bool ok = true;
+ ok &= FindMetadata("_thread_db_sizeof_pthread", eStructSize,
+ m_thread_info.pthread_size);
ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
m_thread_info.dtv_offset);
ok &=
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index b8bdf78fbdfad..d13b8250cc314 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -133,6 +133,7 @@ class DYLDRendezvous {
// the per-thread state.
struct ThreadInfo {
bool valid; // whether we read valid metadata
+ uint32_t pthread_size; // size of struct pthread
uint32_t dtv_offset; // offset of DTV pointer within pthread
uint32_t dtv_slot_size; // size of one DTV slot
uint32_t modid_offset; // offset of module ID within link_map
@@ -345,7 +346,7 @@ class DYLDRendezvous {
/// supplied by the runtime linker.
bool TakeSnapshot(SOEntryList &entry_list);
- enum PThreadField { eSize, eNElem, eOffset };
+ enum PThreadField { eSize, eNElem, eOffset, eStructSize };
bool FindMetadata(const char *name, PThreadField field, uint32_t &value);
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 1d814f93484d8..270339dd74111 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -843,10 +843,11 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp,
LLDB_LOGF(log,
"GetThreadLocalData info: link_map=0x%" PRIx64
", thread info metadata: "
- "modid_offset=0x%" PRIx32 ", dtv_offset=0x%" PRIx32
- ", tls_offset=0x%" PRIx32 ", dtv_slot_size=%" PRIx32 "\n",
- link_map, metadata.modid_offset, metadata.dtv_offset,
- metadata.tls_offset, metadata.dtv_slot_size);
+ "modid_offset=0x%" PRIx32 ", pthread_size=0x%" PRIx32
+ ", dtv_offset=0x%" PRIx32 ", tls_offset=0x%" PRIx32
+ ", dtv_slot_size=%" PRIx32 "\n",
+ link_map, metadata.modid_offset, metadata.pthread_size,
+ metadata.dtv_offset, metadata.tls_offset, metadata.dtv_slot_size);
// Get the thread pointer.
addr_t tp = thread->GetThreadPointer();
@@ -865,8 +866,33 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp,
}
// Lookup the DTV structure for this thread.
- addr_t dtv_ptr = tp + metadata.dtv_offset;
- addr_t dtv = ReadPointer(dtv_ptr);
+ addr_t dtv_ptr = LLDB_INVALID_ADDRESS;
+ if (metadata.dtv_offset < metadata.pthread_size) {
+ // The DTV pointer field lies within `pthread`. This indicates that `libc`
+ // placed `tcbhead_t header`, which contains the `dtv` field, inside
+ // `pthread`, so, for this architecture, `TLS_TCB_AT_TP` is set to `1` and
+ // `TLS_DTV_AT_TP` is `0`. This corresponds to the "Variant II" memory
+ // layout described in Ulrich Drepper's ELF TLS document
+ // (https://akkadia.org/drepper/tls.pdf). The thread pointer points to the
+ // start of `pthread`, and the address of the `dtv` field can be calculated
+ // by adding its offset.
+ dtv_ptr = tp + metadata.dtv_offset;
+ } else if (metadata.dtv_offset == metadata.pthread_size) {
+ // The DTV pointer field is located right after `pthread`. This means that,
+ // for this architecture, `TLS_DTV_AT_TP` is set to `1` in `libc`, which may
+ // correspond to the "Version I" memory layout, in which the thread pointer
+ // points directly to the `dtv` field. However, for different architectures,
+ // the position of the `dtv` field relative to the thread pointer may vary,
+ // so the following calculations must be adjusted for each platform.
+ //
+ // On AArch64 and ARM, `tp` is known to point directly to `dtv`.
+ const llvm::Triple &triple = module_sp->GetArchitecture().GetTriple();
+ if (triple.isAArch64() || triple.isARM()) {
+ dtv_ptr = tp;
+ }
+ }
+ addr_t dtv = (dtv_ptr != LLDB_INVALID_ADDRESS) ? ReadPointer(dtv_ptr)
+ : LLDB_INVALID_ADDRESS;
if (dtv == LLDB_INVALID_ADDRESS) {
LLDB_LOGF(log, "GetThreadLocalData error: fail to read dtv");
return LLDB_INVALID_ADDRESS;
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index c1bc6a3f036bf..70b957b0285fe 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -25,9 +25,10 @@
#if defined(__arm64__) || defined(__aarch64__)
#include "NativeRegisterContextLinux_arm64dbreg.h"
+#endif
+
#include "lldb/Host/linux/Ptrace.h"
#include <asm/ptrace.h>
-#endif
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr))
@@ -68,8 +69,9 @@ NativeRegisterContextLinux::DetermineArchitecture(lldb::tid_t tid) {
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextRegisterInfo(native_thread,
- new RegisterInfoPOSIX_arm(target_arch)),
+ : NativeRegisterContextRegisterInfo(
+ native_thread,
+ new RegisterInfoPOSIX_arm(target_arch, /*has_tls_reg=*/true)),
NativeRegisterContextLinux(native_thread) {
assert(target_arch.GetMachine() == llvm::Triple::arm);
@@ -77,6 +79,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
+ m_tpidr = 0;
// 16 is just a maximum value, query hardware for actual watchpoint count
m_max_hwp_supported = 16;
@@ -120,6 +123,11 @@ NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info,
error = ReadFPR();
if (error.Fail())
return error;
+ } else if (IsTLS(reg)) {
+ error = ReadTLS();
+ if (error.Success())
+ reg_value.SetUInt32(m_tpidr);
+ return error;
} else {
uint32_t full_reg = reg;
bool is_subreg = reg_info->invalidate_regs &&
@@ -199,6 +207,10 @@ NativeRegisterContextLinux_arm::WriteRegister(const RegisterInfo *reg_info,
return WriteFPR();
}
+ if (IsTLS(reg_index))
+ return Status::FromErrorString(
+ "writing to a thread pointer register is not implemented");
+
return Status::FromErrorString(
"failed - register wasn't recognized to be a GPR or an FPR, "
"write strategy unknown");
@@ -283,6 +295,13 @@ bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const {
return false;
}
+bool NativeRegisterContextLinux_arm::IsTLS(unsigned reg) const {
+ if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
+ RegisterInfoPOSIX_arm::TLSRegSet)
+ return true;
+ return false;
+}
+
llvm::Error NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
if (!m_refresh_hwdebug_info)
return llvm::Error::success();
@@ -480,4 +499,20 @@ Status NativeRegisterContextLinux_arm::WriteFPR() {
#endif // __arm__
}
+Status NativeRegisterContextLinux_arm::ReadTLS() {
+#ifdef __arm__
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GET_THREAD_AREA,
+ m_thread.GetID(), nullptr,
+ GetTLSBuffer(), GetTLSSize());
+#else // __aarch64__
+ Status error;
+
+ struct iovec ioVec;
+ ioVec.iov_base = GetTLSBuffer();
+ ioVec.iov_len = GetTLSSize();
+
+ return ReadRegisterSet(&ioVec, GetTLSSize(), NT_ARM_TLS);
+#endif // __arm__
+}
+
#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index cf36859b16ad4..2c292ad19b966 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -58,15 +58,22 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux,
Status WriteFPR() override;
+ Status ReadTLS();
+
void *GetGPRBuffer() override { return &m_gpr_arm; }
void *GetFPRBuffer() override { return &m_fpr; }
size_t GetFPRSize() override { return sizeof(m_fpr); }
+ void *GetTLSBuffer() { return &m_tpidr; }
+
+ size_t GetTLSSize() { return sizeof(m_tpidr); }
+
private:
uint32_t m_gpr_arm[k_num_gpr_registers_arm];
RegisterInfoPOSIX_arm::FPU m_fpr;
+ uint32_t m_tpidr;
bool m_refresh_hwdebug_info;
@@ -74,6 +81,8 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux,
bool IsFPR(unsigned reg) const;
+ bool IsTLS(unsigned reg) const;
+
llvm::Error ReadHardwareDebugInfo() override;
llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index 684176bccdf0c..2d8f5a30fcd56 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -39,6 +39,13 @@ bool RegisterContextPOSIX_arm::IsFPR(unsigned reg) {
return false;
}
+bool RegisterContextPOSIX_arm::IsTLS(unsigned reg) {
+ if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
+ RegisterInfoPOSIX_arm::TLSRegSet)
+ return true;
+ return false;
+}
+
RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(
lldb_private::Thread &thread,
std::unique_ptr<RegisterInfoPOSIX_arm> register_info)
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
index 099c37d46f496..ecd927e64cf70 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
@@ -51,6 +51,8 @@ class RegisterContextPOSIX_arm : public lldb_private::RegisterContext {
bool IsFPR(unsigned reg);
+ bool IsTLS(unsigned reg);
+
size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm::FPU); }
virtual bool ReadGPR() = 0;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
index d47647422ae21..3a3846ace1aaf 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
@@ -75,7 +75,9 @@ GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
enum {
k_num_gpr_registers = gpr_cpsr - gpr_r0 + 1,
k_num_fpr_registers = fpu_q15 - fpu_s0 + 1,
- k_num_register_sets = 2
+ k_num_tls_registers = 1,
+ k_num_register_sets_without_tls = 2,
+ k_num_register_sets_with_tls = 3
};
// arm general purpose registers.
@@ -142,18 +144,30 @@ static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) ==
k_num_fpr_registers,
"g_fpu_regnums_arm has wrong number of register infos");
+// arm thread local storage registers.
+static const uint32_t g_tls_regnums_arm[] = {
+ tls_tpidruro,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_tls_regnums_arm / sizeof g_tls_regnums_arm[0]) - 1) ==
+ k_num_tls_registers,
+ "g_tls_regnums_arm has wrong number of register infos");
+
// Register sets for arm.
-static const RegisterSet g_reg_sets_arm[k_num_register_sets] = {
+static const RegisterSet g_reg_sets_arm[k_num_register_sets_with_tls] = {
{"General Purpose Registers", "gpr", k_num_gpr_registers,
g_gpr_regnums_arm},
{"Floating Point Registers", "fpu", k_num_fpr_registers,
- g_fpu_regnums_arm}};
+ g_fpu_regnums_arm},
+ {"Thread Local Storage Registers", "tls", k_num_tls_registers,
+ g_tls_regnums_arm}};
RegisterInfoPOSIX_arm::RegisterInfoPOSIX_arm(
- const lldb_private::ArchSpec &target_arch)
+ const lldb_private::ArchSpec &target_arch, bool has_tls_reg)
: lldb_private::RegisterInfoAndSetInterface(target_arch),
m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)) {}
+ m_register_info_count(GetRegisterInfoCount(target_arch)),
+ m_has_tls_reg(has_tls_reg) {}
size_t RegisterInfoPOSIX_arm::GetGPRSize() const {
return sizeof(struct RegisterInfoPOSIX_arm::GPR);
@@ -169,7 +183,8 @@ RegisterInfoPOSIX_arm::GetRegisterInfo() const {
}
size_t RegisterInfoPOSIX_arm::GetRegisterSetCount() const {
- return k_num_register_sets;
+ return m_has_tls_reg ? k_num_register_sets_with_tls
+ : k_num_register_sets_without_tls;
}
size_t RegisterInfoPOSIX_arm::GetRegisterSetFromRegisterIndex(
@@ -178,6 +193,8 @@ size_t RegisterInfoPOSIX_arm::GetRegisterSetFromRegisterIndex(
return GPRegSet;
if (reg_index <= fpu_q15)
return FPRegSet;
+ if (reg_index == tls_tpidruro && m_has_tls_reg)
+ return TLSRegSet;
return LLDB_INVALID_REGNUM;
}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h
index db155d757ca8c..327e9f746cab0 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h
@@ -15,7 +15,7 @@
class RegisterInfoPOSIX_arm : public lldb_private::RegisterInfoAndSetInterface {
public:
- enum { GPRegSet = 0, FPRegSet};
+ enum { GPRegSet = 0, FPRegSet, TLSRegSet };
struct GPR {
uint32_t r[16]; // R0-R15
@@ -47,7 +47,8 @@ class RegisterInfoPOSIX_arm : public lldb_private::RegisterInfoAndSetInterface {
uint32_t wcr[16];
};
- RegisterInfoPOSIX_arm(const lldb_private::ArchSpec &target_arch);
+ RegisterInfoPOSIX_arm(const lldb_private::ArchSpec &target_arch,
+ bool has_tls_reg = false);
size_t GetGPRSize() const override;
@@ -67,6 +68,7 @@ class RegisterInfoPOSIX_arm : public lldb_private::RegisterInfoAndSetInterface {
private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
+ bool m_has_tls_reg;
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_ARM_H
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
index f535ca40c4030..afaada679cb79 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -146,6 +146,8 @@ enum {
fpu_q14,
fpu_q15,
+ tls_tpidruro,
+
exc_exception,
exc_fsr,
exc_far,
@@ -682,6 +684,20 @@ static RegisterInfo g_register_infos_arm[] = {
FPU_QREG(q14, 56),
FPU_QREG(q15, 60),
+ {
+ "tpidruro",
+ nullptr,
+ 4,
+ 0,
+ eEncodingUint,
+ eFormatHex,
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_TP,
+ LLDB_INVALID_REGNUM, tls_tpidruro},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+
{
"exception",
nullptr,
diff --git a/lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py b/lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py
index ed696bca54ab4..28d5212cbc7dc 100644
--- a/lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py
+++ b/lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py
@@ -38,7 +38,7 @@ def setUp(self):
# TLS works differently on Windows, this would need to be implemented
# separately.
@skipIfWindows
- @skipIf(oslist=["linux"], archs=["arm$", "aarch64"])
+ @skipIf(oslist=["linux"], archs=["aarch64"])
@skipIf(oslist=no_match([lldbplatformutil.getDarwinOSTriples(), "linux"]))
@expectedFailureIf(lldbplatformutil.xcode15LinkerBug())
def test(self):
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This implements reading the thread pointer register (`TPIDRURO`) on ARM Linux and improves `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` to support the TLS memory layout where the thread pointer register points directly to the DTV pointer.
c1f0df4 to
cb8be96
Compare
jeffreytan81
left a comment
There was a problem hiding this comment.
Thanks for adding this.
Is it expected that aarch64 test is still not working? If so, can you documenting the remaining work required to get it working and if you plan to address it next?
|
|
||
| Address address = list[0].symbol->GetAddress(); | ||
| address.SetOffset(address.GetOffset() + field * sizeof(uint32_t)); | ||
| int field_num = (field == eStructSize) ? 0 : field; |
There was a problem hiding this comment.
Can you add a comment explaining this change?
igorkudrin
left a comment
There was a problem hiding this comment.
I've just realised that I forgot to specify a distinct offset for the new register. Fixing this now with an additional "fixup" commit.
Sorry to bring this up so late but this reminds me we need tests for the register access. Please split this PR so that adding the new register is its own PR, and this is just the dyld parts. My AArch64 TLS register commits for reference: You've implemented the register as read only, which is fine. So you don't need to test what happens with an expression, just check that a write from lldb fails. You can likely use the existing Arm core file and read whatever random value happens to be in there. For a live test, I suggest a program with a thread local, and reading the TLS register using inline asm into a local variable that LLDB can read. Then compare that to what you see in LLDB via. You can put the live process test in a new folder in https://github.com/llvm/llvm-project/tree/main/lldb/test/API/linux. The core file tests are in lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py. Each needs a release note, I suggest:
|
|
And to be clear - you don't need to annotate the tests with any "only if glibc" stuff. We don't actively support running the test suite on Linux with anything else. My concern with other C libraries is what individual users see rather than people who build and test lldb. If those folks need musl support than as you say, they can work on that. |
I've created #182438; will update this PR when the other one is merged.
Thanks for the references!
As far as I can see,
Thanks!
Such users will be able to read the TP register, but because |
Yep, kernel sources confirm that.
Great, no problem then. |
DavidSpickett
left a comment
There was a problem hiding this comment.
LGTM
@jeffreytan81 any more comments? (note that adding the new register was split into another PR, which has already landed)
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently, `DynamicLoaderPOSIXDYLD::GetThreadLocalData()` only supports the TLS memory layout where the thread pointer register points to the start of the `pthread` structure, and the address of the DTV pointer can be calculated by adding the offset of the `dtv` field to `tp`. On ARM (and AArch64), the thread pointer points directly to `dtv`. The patch improves the detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.
Currently,
DynamicLoaderPOSIXDYLD::GetThreadLocalData()only supports the TLS memory layout where the thread pointer register points to the start of thepthreadstructure, and the address of the DTV pointer can be calculated by adding the offset of thedtvfield totp. On ARM (and AArch64), the thread pointer points directly todtv. The patch improves detection of the actual memory layout in the method and adjusts the calculations for the new case, thus adding support for thread-local variables on ARM Linux.