Skip to content

Commit

Permalink
[lldb][AArch64] Add reading of TLS tpidr register from core files
Browse files Browse the repository at this point in the history
7e22921 did live processes, this does
core files. Pretty simple, there is an NT_ARM_TLS note that contains
at least tpidr, and on systems with the Scalable Matrix Extension (SME), tpidr2
as well.

tpidr2 will be handled in future patches for SME support.

This NT_ARM_TLS note has always been present but it seems convenient to
handle it as "optional" inside of LLDB. We'll probably want the flexibility
when supporting tpidr2.

Normally the C library would set tpidr but all our test sources build
without it. So I've updated the neon test program to write to tpidr
and regenerated the corefile.

I've removed the LLDB_PTRACE_NT_ARM_TLS that was unused, we get
what we need from llvm's defs instead.

Reviewed By: omjavaid

Differential Revision: https://reviews.llvm.org/D156118
  • Loading branch information
DavidSpickett committed Aug 3, 2023
1 parent 067ecad commit 43ad521
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 6 deletions.
2 changes: 0 additions & 2 deletions lldb/include/lldb/Host/linux/Ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,4 @@ typedef int __ptrace_request;
#define PTRACE_POKEMTETAGS 34
#endif

#define LLDB_PTRACE_NT_ARM_TLS 0x401 // ARM TLS register

#endif // liblldb_Host_linux_Ptrace_h_
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const {
return m_register_info_up->IsPAuthReg(reg);
}

bool RegisterContextPOSIX_arm64::IsTLS(unsigned reg) const {
return m_register_info_up->IsTLSReg(reg);
}

RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
lldb_private::Thread &thread,
std::unique_ptr<RegisterInfoPOSIX_arm64> register_info)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext {

bool IsSVE(unsigned reg) const;
bool IsPAuth(unsigned reg) const;
bool IsTLS(unsigned reg) const;

bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); }
bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class RegisterInfoPOSIX_arm64
bool IsSSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSSVE); }
bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); }
bool IsMTEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskMTE); }
bool IsTLSEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskTLS); }

bool IsSVEReg(unsigned reg) const;
bool IsSVEZReg(unsigned reg) const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);

DataExtractor tls_data = getRegset(notes, arch.GetTriple(), AARCH64_TLS_Desc);
// A valid note will always contain at least one register, "tpidr". It may
// expand in future.
if (tls_data.GetByteSize() >= sizeof(uint64_t))
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);

auto register_info_up =
std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
Expand All @@ -59,6 +65,9 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
if (m_register_info_up->IsPAuthEnabled())
m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);

if (m_register_info_up->IsTLSEnabled())
m_tls_data = getRegset(notes, target_triple, AARCH64_TLS_Desc);

ConfigureRegisterContext();
}

Expand Down Expand Up @@ -223,6 +232,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
assert(offset < m_pac_data.GetByteSize());
value.SetFromMemoryData(*reg_info, m_pac_data.GetDataStart() + offset,
reg_info->byte_size, lldb::eByteOrderLittle, error);
} else if (IsTLS(reg)) {
offset = reg_info->byte_offset - m_register_info_up->GetTLSOffset();
assert(offset < m_tls_data.GetByteSize());
value.SetFromMemoryData(*reg_info, m_tls_data.GetDataStart() + offset,
reg_info->byte_size, lldb::eByteOrderLittle, error);
} else
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
lldb_private::DataExtractor m_fpr_data;
lldb_private::DataExtractor m_sve_data;
lldb_private::DataExtractor m_pac_data;
lldb_private::DataExtractor m_tls_data;

SVEState m_sve_state;
uint16_t m_sve_vector_length = 0;
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ constexpr RegsetDesc AARCH64_PAC_Desc[] = {
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
};

constexpr RegsetDesc AARCH64_TLS_Desc[] = {
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_TLS},
};

constexpr RegsetDesc PPC_VMX_Desc[] = {
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,10 @@ def test_aarch64_regs(self):
values = {}
values["x1"] = "0x000000000000002f"
values["w1"] = "0x0000002f"
values["fp"] = "0x0000007fc5dd7f20"
values["lr"] = "0x0000000000400180"
values["sp"] = "0x0000007fc5dd7f00"
values["pc"] = "0x000000000040014c"
values["fp"] = "0x0000ffffdab7c770"
values["lr"] = "0x000000000040019c"
values["sp"] = "0x0000ffffdab7c750"
values["pc"] = "0x0000000000400168"
values[
"v0"
] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
Expand Down Expand Up @@ -366,6 +366,7 @@ def test_aarch64_regs(self):
values["d31"] = "1.3980432860952889E-76"
values["fpsr"] = "0x00000000"
values["fpcr"] = "0x00000000"
values["tpidr"] = "0x1122334455667788"

for regname, value in values.items():
self.expect(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// compile with -march=armv8-a+simd on compatible aarch64 compiler
// linux-aarch64-neon.core was generated by: aarch64-linux-gnu-gcc-8
// commandline: -march=armv8-a+simd -nostdlib -static -g linux-aarch64-neon.c
#include <stdint.h>

static void bar(char *boom) {
char F = 'b';
asm volatile("fmov d0, #0.5\n\t");
Expand All @@ -14,6 +16,9 @@ static void bar(char *boom) {
asm volatile("movi v8.16b, #0x11\n\t");
asm volatile("movi v31.16b, #0x30\n\t");

uint64_t pattern = 0x1122334455667788;
asm volatile("msr tpidr_el0, %0" ::"r"(pattern));

*boom = 47; // Frame bar
}

Expand Down
Binary file not shown.
3 changes: 3 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ Changes to the LLVM tools
Changes to LLDB
---------------------------------

* AArch64 Linux targets now provide access to the Thread Local Storage
register ``tpidr``.

Changes to Sanitizers
---------------------
* HWASan now defaults to detecting use-after-scope bugs.
Expand Down

0 comments on commit 43ad521

Please sign in to comment.