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"
13#include "lldb/Target/Unwind.h"
16#include "lldb/Utility/Log.h"
18
32#include "ProcessElfCore.h"
43#include "ThreadElfCore.h"
44
45#include <memory>
46
47using namespace lldb;
48using namespace lldb_private;
49
50// Construct a Thread object with given data
52 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
53 m_gpregset_data(td.gpregset), m_notes(td.notes),
54 m_siginfo_bytes(std::move(td.siginfo_bytes)), m_signo(td.signo) {}
55
57
59 GetRegisterContext()->InvalidateIfNeeded(false);
60}
61
68
71 RegisterContextSP reg_ctx_sp;
72 uint32_t concrete_frame_idx = 0;
74
75 if (frame)
76 concrete_frame_idx = frame->GetConcreteFrameIndex();
77
78 bool is_linux = false;
79 if (concrete_frame_idx == 0) {
82
83 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
84 ArchSpec arch = process->GetArchitecture();
85 RegisterInfoInterface *reg_interface = nullptr;
86
87 switch (arch.GetTriple().getOS()) {
88 case llvm::Triple::FreeBSD: {
89 switch (arch.GetMachine()) {
90 case llvm::Triple::aarch64:
91 case llvm::Triple::arm:
92 break;
93 case llvm::Triple::ppc:
94 reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
95 break;
96 case llvm::Triple::ppc64:
97 case llvm::Triple::ppc64le:
98 reg_interface = new RegisterContextFreeBSD_powerpc64(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::loongarch64 &&
174 arch.GetMachine() != llvm::Triple::riscv64 &&
175 arch.GetMachine() != llvm::Triple::riscv32) {
176 LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
177 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
178 assert(false && "Architecture or OS not supported");
179 }
180
181 switch (arch.GetMachine()) {
182 case llvm::Triple::aarch64:
184 *this, arch, m_gpregset_data, m_notes);
185 break;
186 case llvm::Triple::arm:
187 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
188 *this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
189 m_notes);
190 break;
191 case llvm::Triple::loongarch64:
193 *this, arch, m_gpregset_data, m_notes);
194 break;
195 case llvm::Triple::riscv32:
197 *this, arch, m_gpregset_data, m_notes);
198 break;
199 case llvm::Triple::riscv64:
201 *this, arch, 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>(
220 *this, reg_interface, m_gpregset_data, m_notes);
221 } else {
222 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86>(
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
237llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
238ThreadElfCore::GetSiginfo(size_t max_size) const {
239 if (m_siginfo_bytes.empty())
240 return llvm::createStringError(llvm::inconvertibleErrorCode(),
241 "no siginfo note");
242
243 return llvm::MemoryBuffer::getMemBufferCopy(m_siginfo_bytes,
244 "siginfo note bytes");
245}
246
248 ProcessSP process_sp(GetProcess());
249 if (!process_sp)
250 return false;
251
252 PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
253 if (platform_sp) {
254 lldb::StopInfoSP stopinfo_sp = platform_sp->GetStopInfoFromSiginfo(*this);
255 // The platform SP can optionally handle creating the stop info from the
256 // siginfo value however it's not guaraunteed to be implemented on every
257 // platform, so if we fall through this case, we create from just the signo.
258 if (stopinfo_sp) {
259 SetStopInfo(std::move(stopinfo_sp));
260 return true;
261 }
262 }
263
264 // The above code references the siginfo_t bytes from the NT_SIGINFO note.
265 // This is not the only way to get a signo in an ELF core, and so
266 // ThreadELFCore has a m_signo variable for these cases, which is populated
267 // with a non-zero value when there is no NT_SIGINFO note. However if this is
268 // 0, it's the default value and we have no valid signal and should not report
269 // a stop info.
270 if (m_signo == 0 && m_siginfo_bytes.empty())
271 return false;
272
274 return true;
275}
276
277// Parse PRSTATUS from NOTE entry
279 memset(this, 0, sizeof(ELFLinuxPrStatus));
280}
281
283 constexpr size_t num_ptr_size_members = 10;
284 switch (arch.GetCore()) {
287 return 72;
288 default:
289 if (arch.GetAddressByteSize() == 8)
290 return sizeof(ELFLinuxPrStatus);
291 else
292 return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
293 }
294}
295
297 const ArchSpec &arch) {
299 if (GetSize(arch) > data.GetByteSize()) {
301 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
302 GetSize(arch), data.GetByteSize());
303 return error;
304 }
305
306 // Read field by field to correctly account for endianess of both the core
307 // dump and the platform running lldb.
308 offset_t offset = 0;
309 si_signo = data.GetU32(&offset);
310 si_code = data.GetU32(&offset);
311 si_errno = data.GetU32(&offset);
312
313 pr_cursig = data.GetU16(&offset);
314 offset += 2; // pad
315
316 pr_sigpend = data.GetAddress(&offset);
317 pr_sighold = data.GetAddress(&offset);
318
319 pr_pid = data.GetU32(&offset);
320 pr_ppid = data.GetU32(&offset);
321 pr_pgrp = data.GetU32(&offset);
322 pr_sid = data.GetU32(&offset);
323
324 pr_utime.tv_sec = data.GetAddress(&offset);
325 pr_utime.tv_usec = data.GetAddress(&offset);
326
327 pr_stime.tv_sec = data.GetAddress(&offset);
328 pr_stime.tv_usec = data.GetAddress(&offset);
329
330 pr_cutime.tv_sec = data.GetAddress(&offset);
331 pr_cutime.tv_usec = data.GetAddress(&offset);
332
333 pr_cstime.tv_sec = data.GetAddress(&offset);
334 pr_cstime.tv_usec = data.GetAddress(&offset);
335
336 return error;
337}
338
339static struct compat_timeval
340copy_timespecs(const ProcessInstanceInfo::timespec &oth) {
341 using sec_t = decltype(compat_timeval::tv_sec);
342 using usec_t = decltype(compat_timeval::tv_usec);
343 return {static_cast<sec_t>(oth.tv_sec), static_cast<usec_t>(oth.tv_usec)};
344}
345
346std::optional<ELFLinuxPrStatus>
348 ELFLinuxPrStatus prstatus{};
349 prstatus.pr_pid = thread_sp->GetID();
350 lldb::ProcessSP process_sp = thread_sp->GetProcess();
352 if (!process_sp->GetProcessInfo(info))
353 return std::nullopt;
354
355 prstatus.pr_ppid = info.GetParentProcessID();
356 prstatus.pr_pgrp = info.GetProcessGroupID();
357 prstatus.pr_sid = info.GetProcessSessionID();
358 prstatus.pr_utime = copy_timespecs(info.GetUserTime());
359 prstatus.pr_stime = copy_timespecs(info.GetSystemTime());
362 return prstatus;
363}
364
365// Parse PRPSINFO from NOTE entry
367 memset(this, 0, sizeof(ELFLinuxPrPsInfo));
368}
369
371 switch (arch.GetCore()) {
374 return sizeof(ELFLinuxPrPsInfo);
377 return 124;
378 default:
379 return 0;
380 }
381}
382
384 const ArchSpec &arch) {
386 ByteOrder byteorder = data.GetByteOrder();
387 if (GetSize(arch) > data.GetByteSize()) {
389 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
390 GetSize(arch), data.GetByteSize());
391 return error;
392 }
393 size_t size = 0;
394 offset_t offset = 0;
395
396 pr_state = data.GetU8(&offset);
397 pr_sname = data.GetU8(&offset);
398 pr_zomb = data.GetU8(&offset);
399 pr_nice = data.GetU8(&offset);
400 if (data.GetAddressByteSize() == 8) {
401 // Word align the next field on 64 bit.
402 offset += 4;
403 }
404
405 pr_flag = data.GetAddress(&offset);
406
407 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
408 pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
409 pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
410
411 pr_pid = data.GetU32(&offset);
412 pr_ppid = data.GetU32(&offset);
413 pr_pgrp = data.GetU32(&offset);
414 pr_sid = data.GetU32(&offset);
415
416 size = 16;
417 data.ExtractBytes(offset, size, byteorder, pr_fname);
418 offset += size;
419
420 size = 80;
421 data.ExtractBytes(offset, size, byteorder, pr_psargs);
422 offset += size;
423
424 return error;
425}
426
427std::optional<ELFLinuxPrPsInfo>
430 if (!process_sp->GetProcessInfo(info))
431 return std::nullopt;
432
433 return Populate(info, process_sp->GetState());
434}
435
436std::optional<ELFLinuxPrPsInfo>
438 lldb::StateType process_state) {
439 ELFLinuxPrPsInfo prpsinfo{};
440 prpsinfo.pr_pid = info.GetProcessID();
441 prpsinfo.pr_nice = info.GetPriorityValue().value_or(0);
442 prpsinfo.pr_zomb = 0;
443 if (auto zombie_opt = info.IsZombie(); zombie_opt.value_or(false)) {
444 prpsinfo.pr_zomb = 1;
445 }
446 /**
447 * In the linux kernel this comes from:
448 * state = READ_ONCE(p->__state);
449 * i = state ? ffz(~state) + 1 : 0;
450 * psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i];
451 *
452 * So we replicate that here. From proc_pid_stats(5)
453 * R = Running
454 * S = Sleeping on uninterrutible wait
455 * D = Waiting on uninterruptable disk sleep
456 * T = Tracing stop
457 * Z = Zombie
458 * W = Paging
459 */
460 switch (process_state) {
462 prpsinfo.pr_sname = 'S';
463 prpsinfo.pr_state = 1;
464 break;
466 [[fallthrough]];
468 prpsinfo.pr_sname = 'T';
469 prpsinfo.pr_state = 3;
470 break;
472 [[fallthrough]];
474 prpsinfo.pr_sname = 'R';
475 prpsinfo.pr_state = 0;
476 break;
477 default:
478 break;
479 }
480
481 /**
482 * pr_flags is left as 0. The values (in linux) are specific
483 * to the kernel. We recover them from the proc filesystem
484 * but don't put them in ProcessInfo because it would really
485 * become very linux specific and the utility here seems pretty
486 * dubious
487 */
488
489 if (info.EffectiveUserIDIsValid())
490 prpsinfo.pr_uid = info.GetUserID();
491
492 if (info.EffectiveGroupIDIsValid())
493 prpsinfo.pr_gid = info.GetGroupID();
494
495 if (info.ParentProcessIDIsValid())
496 prpsinfo.pr_ppid = info.GetParentProcessID();
497
498 if (info.ProcessGroupIDIsValid())
499 prpsinfo.pr_pgrp = info.GetProcessGroupID();
500
501 if (info.ProcessSessionIDIsValid())
502 prpsinfo.pr_sid = info.GetProcessSessionID();
503
504 constexpr size_t fname_len = std::extent_v<decltype(prpsinfo.pr_fname)>;
505 static_assert(fname_len > 0, "This should always be non zero");
506 const llvm::StringRef fname = info.GetNameAsStringRef();
507 auto fname_begin = fname.begin();
508 std::copy_n(fname_begin, std::min(fname_len, fname.size()),
509 prpsinfo.pr_fname);
510 prpsinfo.pr_fname[fname_len - 1] = '\0';
511 auto args = info.GetArguments();
512 auto argentry_iterator = std::begin(args);
513 char *psargs = prpsinfo.pr_psargs;
514 char *psargs_end = std::end(prpsinfo.pr_psargs);
515 while (psargs < psargs_end && argentry_iterator != args.end()) {
516 llvm::StringRef argentry = argentry_iterator->ref();
517 size_t len =
518 std::min<size_t>(std::distance(psargs, psargs_end), argentry.size());
519 auto arg_iterator = std::begin(argentry);
520 psargs = std::copy_n(arg_iterator, len, psargs);
521 if (psargs != psargs_end)
522 *(psargs++) = ' ';
523 ++argentry_iterator;
524 }
525 *(psargs - 1) = '\0';
526 return prpsinfo;
527}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition Log.h:376
static struct compat_timeval copy_timespecs(const ProcessInstanceInfo::timespec &oth)
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_loongarch64 > 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_riscv32 > 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)
std::string m_thread_name
lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override
std::vector< lldb_private::CoreNote > m_notes
lldb::RegisterContextSP m_thread_reg_ctx_sp
llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > GetSiginfo(size_t max_size) const override
lldb_private::DataExtractor m_gpregset_data
bool CalculateStopInfo() override
Ask the thread subclass to set its stop info.
llvm::StringRef m_siginfo_bytes
An architecture specification class.
Definition ArchSpec.h:32
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition ArchSpec.cpp:681
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:457
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:673
Core GetCore() const
Definition ArchSpec.h:448
An data extractor class.
virtual uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
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.
lldb::pid_t GetProcessID() const
Definition ProcessInfo.h:68
uint32_t GetUserID() const
Definition ProcessInfo.h:50
llvm::StringRef GetNameAsStringRef() const
uint32_t GetGroupID() const
Definition ProcessInfo.h:52
lldb::pid_t GetProcessSessionID() const
struct timespec GetSystemTime() const
lldb::pid_t GetParentProcessID() const
struct timespec GetUserTime() const
std::optional< int8_t > GetPriorityValue() const
struct timespec GetCumulativeSystemTime() const
std::optional< bool > IsZombie() const
struct timespec GetCumulativeUserTime() const
lldb::pid_t GetProcessGroupID() const
A plug-in interface definition class for debugging a process.
Definition Process.h:354
RegisterInfo interface to patch RegisterInfo structure for archs.
virtual uint32_t GetConcreteFrameIndex()
Query this frame to find what frame it is in this Thread's StackFrameList, not counting inlined frame...
Definition StackFrame.h:470
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static lldb::StopInfoSP CreateStopReasonWithSignal(Thread &thread, int signo, const char *description=nullptr, std::optional< int > code=std::nullopt)
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp)
Definition Thread.cpp:474
virtual void DestroyThread()
Definition Thread.cpp:258
virtual Unwind & GetUnwinder()
Definition Thread.cpp:2121
Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id=false)
Constructor.
Definition Thread.cpp:225
lldb::ProcessSP GetProcess() const
Definition Thread.h:160
friend class StackFrame
Definition Thread.h:1323
lldb::RegisterContextSP m_reg_context_sp
The register context for this thread's current register state.
Definition Thread.h:1388
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:332
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Platform > PlatformSP
uint64_t offset_t
Definition lldb-types.h:85
StateType
Process and Thread States.
@ eStateUnloaded
Process is object is valid, but not currently loaded.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch)
static size_t GetSize(const lldb_private::ArchSpec &arch)
static std::optional< ELFLinuxPrPsInfo > Populate(const lldb::ProcessSP &process_sp)
static size_t GetSize(const lldb_private::ArchSpec &arch)
compat_timeval pr_cutime
lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch)
compat_timeval pr_stime
compat_timeval pr_utime
static std::optional< ELFLinuxPrStatus > Populate(const lldb::ThreadSP &thread_sp)
compat_timeval pr_cstime