1 //===-- ThreadElfCore.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/RegisterContext.h"
10 #include "lldb/Target/StopInfo.h"
11 #include "lldb/Target/Target.h"
12 #include "lldb/Target/Unwind.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/Utility/LLDBLog.h"
15 #include "lldb/Utility/Log.h"
17 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
18 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
19 #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
20 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
21 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
22 #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
23 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
24 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
25 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
26 #include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
27 #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
28 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
29 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
30 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
31 #include "ProcessElfCore.h"
32 #include "RegisterContextLinuxCore_x86_64.h"
33 #include "RegisterContextPOSIXCore_arm.h"
34 #include "RegisterContextPOSIXCore_arm64.h"
35 #include "RegisterContextPOSIXCore_mips64.h"
36 #include "RegisterContextPOSIXCore_powerpc.h"
37 #include "RegisterContextPOSIXCore_ppc64le.h"
38 #include "RegisterContextPOSIXCore_s390x.h"
39 #include "RegisterContextPOSIXCore_x86_64.h"
40 #include "ThreadElfCore.h"
45 using namespace lldb_private
;
47 // Construct a Thread object with given data
48 ThreadElfCore::ThreadElfCore(Process
&process
, const ThreadData
&td
)
49 : Thread(process
, td
.tid
), m_thread_name(td
.name
), m_thread_reg_ctx_sp(),
50 m_signo(td
.signo
), m_code(td
.code
), m_gpregset_data(td
.gpregset
),
53 ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
55 void ThreadElfCore::RefreshStateAfterStop() {
56 GetRegisterContext()->InvalidateIfNeeded(false);
59 RegisterContextSP
ThreadElfCore::GetRegisterContext() {
60 if (!m_reg_context_sp
) {
61 m_reg_context_sp
= CreateRegisterContextForFrame(nullptr);
63 return m_reg_context_sp
;
67 ThreadElfCore::CreateRegisterContextForFrame(StackFrame
*frame
) {
68 RegisterContextSP reg_ctx_sp
;
69 uint32_t concrete_frame_idx
= 0;
70 Log
*log
= GetLog(LLDBLog::Thread
);
73 concrete_frame_idx
= frame
->GetConcreteFrameIndex();
75 bool is_linux
= false;
76 if (concrete_frame_idx
== 0) {
77 if (m_thread_reg_ctx_sp
)
78 return m_thread_reg_ctx_sp
;
80 ProcessElfCore
*process
= static_cast<ProcessElfCore
*>(GetProcess().get());
81 ArchSpec arch
= process
->GetArchitecture();
82 RegisterInfoInterface
*reg_interface
= nullptr;
84 switch (arch
.GetTriple().getOS()) {
85 case llvm::Triple::FreeBSD
: {
86 switch (arch
.GetMachine()) {
87 case llvm::Triple::aarch64
:
88 case llvm::Triple::arm
:
90 case llvm::Triple::ppc
:
91 reg_interface
= new RegisterContextFreeBSD_powerpc32(arch
);
93 case llvm::Triple::ppc64
:
94 reg_interface
= new RegisterContextFreeBSD_powerpc64(arch
);
96 case llvm::Triple::mips64
:
97 reg_interface
= new RegisterContextFreeBSD_mips64(arch
);
99 case llvm::Triple::x86
:
100 reg_interface
= new RegisterContextFreeBSD_i386(arch
);
102 case llvm::Triple::x86_64
:
103 reg_interface
= new RegisterContextFreeBSD_x86_64(arch
);
111 case llvm::Triple::NetBSD
: {
112 switch (arch
.GetMachine()) {
113 case llvm::Triple::aarch64
:
115 case llvm::Triple::x86
:
116 reg_interface
= new RegisterContextNetBSD_i386(arch
);
118 case llvm::Triple::x86_64
:
119 reg_interface
= new RegisterContextNetBSD_x86_64(arch
);
127 case llvm::Triple::Linux
: {
129 switch (arch
.GetMachine()) {
130 case llvm::Triple::aarch64
:
132 case llvm::Triple::ppc64le
:
133 reg_interface
= new RegisterInfoPOSIX_ppc64le(arch
);
135 case llvm::Triple::systemz
:
136 reg_interface
= new RegisterContextLinux_s390x(arch
);
138 case llvm::Triple::x86
:
139 reg_interface
= new RegisterContextLinux_i386(arch
);
141 case llvm::Triple::x86_64
:
142 reg_interface
= new RegisterContextLinux_x86_64(arch
);
150 case llvm::Triple::OpenBSD
: {
151 switch (arch
.GetMachine()) {
152 case llvm::Triple::aarch64
:
154 case llvm::Triple::x86
:
155 reg_interface
= new RegisterContextOpenBSD_i386(arch
);
157 case llvm::Triple::x86_64
:
158 reg_interface
= new RegisterContextOpenBSD_x86_64(arch
);
170 if (!reg_interface
&& arch
.GetMachine() != llvm::Triple::aarch64
&&
171 arch
.GetMachine() != llvm::Triple::arm
) {
172 LLDB_LOGF(log
, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
173 __FUNCTION__
, arch
.GetMachine(), arch
.GetTriple().getOS());
174 assert(false && "Architecture or OS not supported");
177 switch (arch
.GetMachine()) {
178 case llvm::Triple::aarch64
:
179 m_thread_reg_ctx_sp
= RegisterContextCorePOSIX_arm64::Create(
180 *this, arch
, m_gpregset_data
, m_notes
);
182 case llvm::Triple::arm
:
183 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_arm
>(
184 *this, std::make_unique
<RegisterInfoPOSIX_arm
>(arch
), m_gpregset_data
,
187 case llvm::Triple::mipsel
:
188 case llvm::Triple::mips
:
189 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_mips64
>(
190 *this, reg_interface
, m_gpregset_data
, m_notes
);
192 case llvm::Triple::mips64
:
193 case llvm::Triple::mips64el
:
194 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_mips64
>(
195 *this, reg_interface
, m_gpregset_data
, m_notes
);
197 case llvm::Triple::ppc
:
198 case llvm::Triple::ppc64
:
199 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_powerpc
>(
200 *this, reg_interface
, m_gpregset_data
, m_notes
);
202 case llvm::Triple::ppc64le
:
203 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_ppc64le
>(
204 *this, reg_interface
, m_gpregset_data
, m_notes
);
206 case llvm::Triple::systemz
:
207 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_s390x
>(
208 *this, reg_interface
, m_gpregset_data
, m_notes
);
210 case llvm::Triple::x86
:
211 case llvm::Triple::x86_64
:
213 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextLinuxCore_x86_64
>(
214 *this, reg_interface
, m_gpregset_data
, m_notes
);
216 m_thread_reg_ctx_sp
= std::make_shared
<RegisterContextCorePOSIX_x86_64
>(
217 *this, reg_interface
, m_gpregset_data
, m_notes
);
224 reg_ctx_sp
= m_thread_reg_ctx_sp
;
226 reg_ctx_sp
= GetUnwinder().CreateRegisterContextForFrame(frame
);
231 bool ThreadElfCore::CalculateStopInfo() {
232 ProcessSP
process_sp(GetProcess());
236 SetStopInfo(StopInfo::CreateStopReasonWithSignal(
237 *this, m_signo
, /*description=*/nullptr, m_code
));
241 // Parse PRSTATUS from NOTE entry
242 ELFLinuxPrStatus::ELFLinuxPrStatus() {
243 memset(this, 0, sizeof(ELFLinuxPrStatus
));
246 size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec
&arch
) {
247 constexpr size_t mips_linux_pr_status_size_o32
= 96;
248 constexpr size_t mips_linux_pr_status_size_n32
= 72;
249 constexpr size_t num_ptr_size_members
= 10;
251 std::string abi
= arch
.GetTargetABI();
252 assert(!abi
.empty() && "ABI is not set");
253 if (!abi
.compare("n64"))
254 return sizeof(ELFLinuxPrStatus
);
255 else if (!abi
.compare("o32"))
256 return mips_linux_pr_status_size_o32
;
258 return mips_linux_pr_status_size_n32
;
260 switch (arch
.GetCore()) {
261 case lldb_private::ArchSpec::eCore_x86_32_i386
:
262 case lldb_private::ArchSpec::eCore_x86_32_i486
:
265 if (arch
.GetAddressByteSize() == 8)
266 return sizeof(ELFLinuxPrStatus
);
268 return sizeof(ELFLinuxPrStatus
) - num_ptr_size_members
* 4;
272 Status
ELFLinuxPrStatus::Parse(const DataExtractor
&data
,
273 const ArchSpec
&arch
) {
275 if (GetSize(arch
) > data
.GetByteSize()) {
276 error
.SetErrorStringWithFormat(
277 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64
,
278 GetSize(arch
), data
.GetByteSize());
282 // Read field by field to correctly account for endianess of both the core
283 // dump and the platform running lldb.
285 si_signo
= data
.GetU32(&offset
);
286 si_code
= data
.GetU32(&offset
);
287 si_errno
= data
.GetU32(&offset
);
289 pr_cursig
= data
.GetU16(&offset
);
292 pr_sigpend
= data
.GetAddress(&offset
);
293 pr_sighold
= data
.GetAddress(&offset
);
295 pr_pid
= data
.GetU32(&offset
);
296 pr_ppid
= data
.GetU32(&offset
);
297 pr_pgrp
= data
.GetU32(&offset
);
298 pr_sid
= data
.GetU32(&offset
);
300 pr_utime
.tv_sec
= data
.GetAddress(&offset
);
301 pr_utime
.tv_usec
= data
.GetAddress(&offset
);
303 pr_stime
.tv_sec
= data
.GetAddress(&offset
);
304 pr_stime
.tv_usec
= data
.GetAddress(&offset
);
306 pr_cutime
.tv_sec
= data
.GetAddress(&offset
);
307 pr_cutime
.tv_usec
= data
.GetAddress(&offset
);
309 pr_cstime
.tv_sec
= data
.GetAddress(&offset
);
310 pr_cstime
.tv_usec
= data
.GetAddress(&offset
);
315 // Parse PRPSINFO from NOTE entry
316 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
317 memset(this, 0, sizeof(ELFLinuxPrPsInfo
));
320 size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec
&arch
) {
321 constexpr size_t mips_linux_pr_psinfo_size_o32_n32
= 128;
323 uint8_t address_byte_size
= arch
.GetAddressByteSize();
324 if (address_byte_size
== 8)
325 return sizeof(ELFLinuxPrPsInfo
);
326 return mips_linux_pr_psinfo_size_o32_n32
;
329 switch (arch
.GetCore()) {
330 case lldb_private::ArchSpec::eCore_s390x_generic
:
331 case lldb_private::ArchSpec::eCore_x86_64_x86_64
:
332 return sizeof(ELFLinuxPrPsInfo
);
333 case lldb_private::ArchSpec::eCore_x86_32_i386
:
334 case lldb_private::ArchSpec::eCore_x86_32_i486
:
341 Status
ELFLinuxPrPsInfo::Parse(const DataExtractor
&data
,
342 const ArchSpec
&arch
) {
344 ByteOrder byteorder
= data
.GetByteOrder();
345 if (GetSize(arch
) > data
.GetByteSize()) {
346 error
.SetErrorStringWithFormat(
347 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64
,
348 GetSize(arch
), data
.GetByteSize());
354 pr_state
= data
.GetU8(&offset
);
355 pr_sname
= data
.GetU8(&offset
);
356 pr_zomb
= data
.GetU8(&offset
);
357 pr_nice
= data
.GetU8(&offset
);
358 if (data
.GetAddressByteSize() == 8) {
359 // Word align the next field on 64 bit.
363 pr_flag
= data
.GetAddress(&offset
);
366 // The pr_uid and pr_gid is always 32 bit irrespective of platforms
367 pr_uid
= data
.GetU32(&offset
);
368 pr_gid
= data
.GetU32(&offset
);
370 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
371 pr_uid
= data
.GetMaxU64(&offset
, data
.GetAddressByteSize() >> 1);
372 pr_gid
= data
.GetMaxU64(&offset
, data
.GetAddressByteSize() >> 1);
375 pr_pid
= data
.GetU32(&offset
);
376 pr_ppid
= data
.GetU32(&offset
);
377 pr_pgrp
= data
.GetU32(&offset
);
378 pr_sid
= data
.GetU32(&offset
);
381 data
.ExtractBytes(offset
, size
, byteorder
, pr_fname
);
385 data
.ExtractBytes(offset
, size
, byteorder
, pr_psargs
);
391 // Parse SIGINFO from NOTE entry
392 ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo
)); }
394 size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec
&arch
) {
396 return sizeof(ELFLinuxSigInfo
);
397 switch (arch
.GetCore()) {
398 case lldb_private::ArchSpec::eCore_x86_64_x86_64
:
399 return sizeof(ELFLinuxSigInfo
);
400 case lldb_private::ArchSpec::eCore_s390x_generic
:
401 case lldb_private::ArchSpec::eCore_x86_32_i386
:
402 case lldb_private::ArchSpec::eCore_x86_32_i486
:
409 Status
ELFLinuxSigInfo::Parse(const DataExtractor
&data
, const ArchSpec
&arch
) {
411 if (GetSize(arch
) > data
.GetByteSize()) {
412 error
.SetErrorStringWithFormat(
413 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64
,
414 GetSize(arch
), data
.GetByteSize());
418 // Parsing from a 32 bit ELF core file, and populating/reusing the structure
419 // properly, because the struct is for the 64 bit version
421 si_signo
= data
.GetU32(&offset
);
422 si_errno
= data
.GetU32(&offset
);
423 si_code
= data
.GetU32(&offset
);