LLDB mainline
ThreadElfCore.cpp
Go to the documentation of this file.
1//===-- ThreadElfCore.cpp -------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
11#include "lldb/Target/Target.h"
12#include "lldb/Target/Unwind.h"
15#include "lldb/Utility/Log.h"
16
31#include "ProcessElfCore.h"
41#include "ThreadElfCore.h"
42
43#include <memory>
44
45using namespace lldb;
46using namespace lldb_private;
47
48// Construct a Thread object with given data
50 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
51 m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset),
52 m_notes(td.notes) {}
53
55
57 GetRegisterContext()->InvalidateIfNeeded(false);
58}
59
61 if (!m_reg_context_sp) {
63 }
64 return m_reg_context_sp;
65}
66
69 RegisterContextSP reg_ctx_sp;
70 uint32_t concrete_frame_idx = 0;
71 Log *log = GetLog(LLDBLog::Thread);
72
73 if (frame)
74 concrete_frame_idx = frame->GetConcreteFrameIndex();
75
76 bool is_linux = false;
77 if (concrete_frame_idx == 0) {
80
81 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
82 ArchSpec arch = process->GetArchitecture();
83 RegisterInfoInterface *reg_interface = nullptr;
84
85 switch (arch.GetTriple().getOS()) {
86 case llvm::Triple::FreeBSD: {
87 switch (arch.GetMachine()) {
88 case llvm::Triple::aarch64:
89 case llvm::Triple::arm:
90 break;
91 case llvm::Triple::ppc:
92 reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
93 break;
94 case llvm::Triple::ppc64:
95 reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
96 break;
97 case llvm::Triple::mips64:
98 reg_interface = new RegisterContextFreeBSD_mips64(arch);
99 break;
100 case llvm::Triple::x86:
101 reg_interface = new RegisterContextFreeBSD_i386(arch);
102 break;
103 case llvm::Triple::x86_64:
104 reg_interface = new RegisterContextFreeBSD_x86_64(arch);
105 break;
106 default:
107 break;
108 }
109 break;
110 }
111
112 case llvm::Triple::NetBSD: {
113 switch (arch.GetMachine()) {
114 case llvm::Triple::aarch64:
115 break;
116 case llvm::Triple::x86:
117 reg_interface = new RegisterContextNetBSD_i386(arch);
118 break;
119 case llvm::Triple::x86_64:
120 reg_interface = new RegisterContextNetBSD_x86_64(arch);
121 break;
122 default:
123 break;
124 }
125 break;
126 }
127
128 case llvm::Triple::Linux: {
129 is_linux = true;
130 switch (arch.GetMachine()) {
131 case llvm::Triple::aarch64:
132 break;
133 case llvm::Triple::ppc64le:
134 reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
135 break;
136 case llvm::Triple::systemz:
137 reg_interface = new RegisterContextLinux_s390x(arch);
138 break;
139 case llvm::Triple::x86:
140 reg_interface = new RegisterContextLinux_i386(arch);
141 break;
142 case llvm::Triple::x86_64:
143 reg_interface = new RegisterContextLinux_x86_64(arch);
144 break;
145 default:
146 break;
147 }
148 break;
149 }
150
151 case llvm::Triple::OpenBSD: {
152 switch (arch.GetMachine()) {
153 case llvm::Triple::aarch64:
154 break;
155 case llvm::Triple::x86:
156 reg_interface = new RegisterContextOpenBSD_i386(arch);
157 break;
158 case llvm::Triple::x86_64:
159 reg_interface = new RegisterContextOpenBSD_x86_64(arch);
160 break;
161 default:
162 break;
163 }
164 break;
165 }
166
167 default:
168 break;
169 }
170
171 if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
172 arch.GetMachine() != llvm::Triple::arm &&
173 arch.GetMachine() != llvm::Triple::riscv64) {
174 LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
175 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
176 assert(false && "Architecture or OS not supported");
177 }
178
179 switch (arch.GetMachine()) {
180 case llvm::Triple::aarch64:
182 *this, arch, m_gpregset_data, m_notes);
183 break;
184 case llvm::Triple::arm:
185 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
186 *this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
187 m_notes);
188 break;
189 case llvm::Triple::riscv64:
191 *this, arch, m_gpregset_data, m_notes);
192 break;
193 case llvm::Triple::mipsel:
194 case llvm::Triple::mips:
195 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
196 *this, reg_interface, m_gpregset_data, m_notes);
197 break;
198 case llvm::Triple::mips64:
199 case llvm::Triple::mips64el:
200 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
201 *this, reg_interface, m_gpregset_data, m_notes);
202 break;
203 case llvm::Triple::ppc:
204 case llvm::Triple::ppc64:
205 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
206 *this, reg_interface, m_gpregset_data, m_notes);
207 break;
208 case llvm::Triple::ppc64le:
209 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
210 *this, reg_interface, m_gpregset_data, m_notes);
211 break;
212 case llvm::Triple::systemz:
213 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
214 *this, reg_interface, m_gpregset_data, m_notes);
215 break;
216 case llvm::Triple::x86:
217 case llvm::Triple::x86_64:
218 if (is_linux) {
219 m_thread_reg_ctx_sp = std::make_shared<RegisterContextLinuxCore_x86_64>(
220 *this, reg_interface, m_gpregset_data, m_notes);
221 } else {
222 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
223 *this, reg_interface, m_gpregset_data, m_notes);
224 }
225 break;
226 default:
227 break;
228 }
229
230 reg_ctx_sp = m_thread_reg_ctx_sp;
231 } else {
232 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
233 }
234 return reg_ctx_sp;
235}
236
238 ProcessSP process_sp(GetProcess());
239 if (!process_sp)
240 return false;
241
243 *this, m_signo, /*description=*/nullptr, m_code));
244 return true;
245}
246
247// Parse PRSTATUS from NOTE entry
249 memset(this, 0, sizeof(ELFLinuxPrStatus));
250}
251
253 constexpr size_t mips_linux_pr_status_size_o32 = 96;
254 constexpr size_t mips_linux_pr_status_size_n32 = 72;
255 constexpr size_t num_ptr_size_members = 10;
256 if (arch.IsMIPS()) {
257 std::string abi = arch.GetTargetABI();
258 assert(!abi.empty() && "ABI is not set");
259 if (!abi.compare("n64"))
260 return sizeof(ELFLinuxPrStatus);
261 else if (!abi.compare("o32"))
262 return mips_linux_pr_status_size_o32;
263 // N32 ABI
264 return mips_linux_pr_status_size_n32;
265 }
266 switch (arch.GetCore()) {
269 return 72;
270 default:
271 if (arch.GetAddressByteSize() == 8)
272 return sizeof(ELFLinuxPrStatus);
273 else
274 return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
275 }
276}
277
279 const ArchSpec &arch) {
281 if (GetSize(arch) > data.GetByteSize()) {
282 error.SetErrorStringWithFormat(
283 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
284 GetSize(arch), data.GetByteSize());
285 return error;
286 }
287
288 // Read field by field to correctly account for endianess of both the core
289 // dump and the platform running lldb.
290 offset_t offset = 0;
291 si_signo = data.GetU32(&offset);
292 si_code = data.GetU32(&offset);
293 si_errno = data.GetU32(&offset);
294
295 pr_cursig = data.GetU16(&offset);
296 offset += 2; // pad
297
298 pr_sigpend = data.GetAddress(&offset);
299 pr_sighold = data.GetAddress(&offset);
300
301 pr_pid = data.GetU32(&offset);
302 pr_ppid = data.GetU32(&offset);
303 pr_pgrp = data.GetU32(&offset);
304 pr_sid = data.GetU32(&offset);
305
306 pr_utime.tv_sec = data.GetAddress(&offset);
307 pr_utime.tv_usec = data.GetAddress(&offset);
308
309 pr_stime.tv_sec = data.GetAddress(&offset);
310 pr_stime.tv_usec = data.GetAddress(&offset);
311
312 pr_cutime.tv_sec = data.GetAddress(&offset);
313 pr_cutime.tv_usec = data.GetAddress(&offset);
314
315 pr_cstime.tv_sec = data.GetAddress(&offset);
316 pr_cstime.tv_usec = data.GetAddress(&offset);
317
318 return error;
319}
320
321// Parse PRPSINFO from NOTE entry
323 memset(this, 0, sizeof(ELFLinuxPrPsInfo));
324}
325
327 constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
328 if (arch.IsMIPS()) {
329 uint8_t address_byte_size = arch.GetAddressByteSize();
330 if (address_byte_size == 8)
331 return sizeof(ELFLinuxPrPsInfo);
332 return mips_linux_pr_psinfo_size_o32_n32;
333 }
334
335 switch (arch.GetCore()) {
338 return sizeof(ELFLinuxPrPsInfo);
341 return 124;
342 default:
343 return 0;
344 }
345}
346
348 const ArchSpec &arch) {
350 ByteOrder byteorder = data.GetByteOrder();
351 if (GetSize(arch) > data.GetByteSize()) {
352 error.SetErrorStringWithFormat(
353 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
354 GetSize(arch), data.GetByteSize());
355 return error;
356 }
357 size_t size = 0;
358 offset_t offset = 0;
359
360 pr_state = data.GetU8(&offset);
361 pr_sname = data.GetU8(&offset);
362 pr_zomb = data.GetU8(&offset);
363 pr_nice = data.GetU8(&offset);
364 if (data.GetAddressByteSize() == 8) {
365 // Word align the next field on 64 bit.
366 offset += 4;
367 }
368
369 pr_flag = data.GetAddress(&offset);
370
371 if (arch.IsMIPS()) {
372 // The pr_uid and pr_gid is always 32 bit irrespective of platforms
373 pr_uid = data.GetU32(&offset);
374 pr_gid = data.GetU32(&offset);
375 } else {
376 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
377 pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
378 pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
379 }
380
381 pr_pid = data.GetU32(&offset);
382 pr_ppid = data.GetU32(&offset);
383 pr_pgrp = data.GetU32(&offset);
384 pr_sid = data.GetU32(&offset);
385
386 size = 16;
387 data.ExtractBytes(offset, size, byteorder, pr_fname);
388 offset += size;
389
390 size = 80;
391 data.ExtractBytes(offset, size, byteorder, pr_psargs);
392 offset += size;
393
394 return error;
395}
396
397// Parse SIGINFO from NOTE entry
399
401 if (arch.IsMIPS())
402 return sizeof(ELFLinuxSigInfo);
403 switch (arch.GetCore()) {
405 return sizeof(ELFLinuxSigInfo);
409 return 12;
410 default:
411 return 0;
412 }
413}
414
417 if (GetSize(arch) > data.GetByteSize()) {
418 error.SetErrorStringWithFormat(
419 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
420 GetSize(arch), data.GetByteSize());
421 return error;
422 }
423
424 // Parsing from a 32 bit ELF core file, and populating/reusing the structure
425 // properly, because the struct is for the 64 bit version
426 offset_t offset = 0;
427 si_signo = data.GetU32(&offset);
428 si_errno = data.GetU32(&offset);
429 si_code = data.GetU32(&offset);
430
431 return error;
432}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:366
lldb_private::ArchSpec GetArchitecture()
static std::unique_ptr< RegisterContextCorePOSIX_arm64 > Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
static std::unique_ptr< RegisterContextCorePOSIX_riscv64 > Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
void RefreshStateAfterStop() override
lldb::RegisterContextSP GetRegisterContext() override
~ThreadElfCore() override
ThreadElfCore(lldb_private::Process &process, const ThreadData &td)
lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override
std::vector< lldb_private::CoreNote > m_notes
lldb::RegisterContextSP m_thread_reg_ctx_sp
lldb_private::DataExtractor m_gpregset_data
bool CalculateStopInfo() override
Ask the thread subclass to set its stop info.
An architecture specification class.
Definition: ArchSpec.h:31
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:691
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
bool IsMIPS() const
if MIPS architecture return true.
Definition: ArchSpec.cpp:559
std::string GetTargetABI() const
Return a string representing target application ABI.
Definition: ArchSpec.cpp:561
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:683
Core GetCore() const
Definition: ArchSpec.h:429
An data extractor class.
Definition: DataExtractor.h:48
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint64_t GetAddress(lldb::offset_t *offset_ptr) const
Extract an address from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint32_t GetAddressByteSize() const
Get the current address size.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
size_t ExtractBytes(lldb::offset_t offset, lldb::offset_t length, lldb::ByteOrder dst_byte_order, void *dst) const
Extract an arbitrary number of bytes in the specified byte order.
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
RegisterInfo interface to patch RegisterInfo structure for archs.
This base class provides an interface to stack frames.
Definition: StackFrame.h:43
uint32_t GetConcreteFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList, not counting inlined frame...
Definition: StackFrame.h:429
An error handling class.
Definition: Status.h:44
static lldb::StopInfoSP CreateStopReasonWithSignal(Thread &thread, int signo, const char *description=nullptr, std::optional< int > code=std::nullopt)
Definition: StopInfo.cpp:1386
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp)
Definition: Thread.cpp:457
virtual void DestroyThread()
Definition: Thread.cpp:245
virtual Unwind & GetUnwinder()
Definition: Thread.cpp:1888
lldb::ProcessSP GetProcess() const
Definition: Thread.h:155
lldb::RegisterContextSP m_reg_context_sp
The register context for this thread's current register state.
Definition: Thread.h:1317
lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame)
Definition: Unwind.h:56
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:331
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:386
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:391
lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch)
static size_t GetSize(const lldb_private::ArchSpec &arch)
static size_t GetSize(const lldb_private::ArchSpec &arch)
uint64_t pr_sighold
Definition: ThreadElfCore.h:42
compat_timeval pr_cutime
Definition: ThreadElfCore.h:51
lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch)
uint64_t pr_sigpend
Definition: ThreadElfCore.h:41
compat_timeval pr_stime
Definition: ThreadElfCore.h:50
compat_timeval pr_utime
Definition: ThreadElfCore.h:49
compat_timeval pr_cstime
Definition: ThreadElfCore.h:52
lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch)
static size_t GetSize(const lldb_private::ArchSpec &arch)
uint64_t tv_sec
Definition: ThreadElfCore.h:19
uint64_t tv_usec
Definition: ThreadElfCore.h:20