xref: /llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
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 
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"
16 #include "lldb/Utility/ProcessInfo.h"
17 
18 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
19 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
20 #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
21 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
22 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
23 #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
24 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
25 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
26 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
27 #include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
28 #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
29 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
30 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
31 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
32 #include "ProcessElfCore.h"
33 #include "RegisterContextLinuxCore_x86_64.h"
34 #include "RegisterContextPOSIXCore_arm.h"
35 #include "RegisterContextPOSIXCore_arm64.h"
36 #include "RegisterContextPOSIXCore_mips64.h"
37 #include "RegisterContextPOSIXCore_powerpc.h"
38 #include "RegisterContextPOSIXCore_ppc64le.h"
39 #include "RegisterContextPOSIXCore_riscv64.h"
40 #include "RegisterContextPOSIXCore_s390x.h"
41 #include "RegisterContextPOSIXCore_x86_64.h"
42 #include "ThreadElfCore.h"
43 
44 #include <memory>
45 
46 using namespace lldb;
47 using namespace lldb_private;
48 
49 // Construct a Thread object with given data
50 ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
51     : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
52       m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset),
53       m_notes(td.notes) {}
54 
55 ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
56 
57 void ThreadElfCore::RefreshStateAfterStop() {
58   GetRegisterContext()->InvalidateIfNeeded(false);
59 }
60 
61 RegisterContextSP ThreadElfCore::GetRegisterContext() {
62   if (!m_reg_context_sp) {
63     m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
64   }
65   return m_reg_context_sp;
66 }
67 
68 RegisterContextSP
69 ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
70   RegisterContextSP reg_ctx_sp;
71   uint32_t concrete_frame_idx = 0;
72   Log *log = GetLog(LLDBLog::Thread);
73 
74   if (frame)
75     concrete_frame_idx = frame->GetConcreteFrameIndex();
76 
77   bool is_linux = false;
78   if (concrete_frame_idx == 0) {
79     if (m_thread_reg_ctx_sp)
80       return m_thread_reg_ctx_sp;
81 
82     ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
83     ArchSpec arch = process->GetArchitecture();
84     RegisterInfoInterface *reg_interface = nullptr;
85 
86     switch (arch.GetTriple().getOS()) {
87     case llvm::Triple::FreeBSD: {
88       switch (arch.GetMachine()) {
89       case llvm::Triple::aarch64:
90       case llvm::Triple::arm:
91         break;
92       case llvm::Triple::ppc:
93         reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
94         break;
95       case llvm::Triple::ppc64:
96         reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
97         break;
98       case llvm::Triple::mips64:
99         reg_interface = new RegisterContextFreeBSD_mips64(arch);
100         break;
101       case llvm::Triple::x86:
102         reg_interface = new RegisterContextFreeBSD_i386(arch);
103         break;
104       case llvm::Triple::x86_64:
105         reg_interface = new RegisterContextFreeBSD_x86_64(arch);
106         break;
107       default:
108         break;
109       }
110       break;
111     }
112 
113     case llvm::Triple::NetBSD: {
114       switch (arch.GetMachine()) {
115       case llvm::Triple::aarch64:
116         break;
117       case llvm::Triple::x86:
118         reg_interface = new RegisterContextNetBSD_i386(arch);
119         break;
120       case llvm::Triple::x86_64:
121         reg_interface = new RegisterContextNetBSD_x86_64(arch);
122         break;
123       default:
124         break;
125       }
126       break;
127     }
128 
129     case llvm::Triple::Linux: {
130       is_linux = true;
131       switch (arch.GetMachine()) {
132       case llvm::Triple::aarch64:
133         break;
134       case llvm::Triple::ppc64le:
135         reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
136         break;
137       case llvm::Triple::systemz:
138         reg_interface = new RegisterContextLinux_s390x(arch);
139         break;
140       case llvm::Triple::x86:
141         reg_interface = new RegisterContextLinux_i386(arch);
142         break;
143       case llvm::Triple::x86_64:
144         reg_interface = new RegisterContextLinux_x86_64(arch);
145         break;
146       default:
147         break;
148       }
149       break;
150     }
151 
152     case llvm::Triple::OpenBSD: {
153       switch (arch.GetMachine()) {
154       case llvm::Triple::aarch64:
155         break;
156       case llvm::Triple::x86:
157         reg_interface = new RegisterContextOpenBSD_i386(arch);
158         break;
159       case llvm::Triple::x86_64:
160         reg_interface = new RegisterContextOpenBSD_x86_64(arch);
161         break;
162       default:
163         break;
164       }
165       break;
166     }
167 
168     default:
169       break;
170     }
171 
172     if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
173         arch.GetMachine() != llvm::Triple::arm &&
174         arch.GetMachine() != llvm::Triple::riscv64) {
175       LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
176                 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
177       assert(false && "Architecture or OS not supported");
178     }
179 
180     switch (arch.GetMachine()) {
181     case llvm::Triple::aarch64:
182       m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create(
183           *this, arch, m_gpregset_data, m_notes);
184       break;
185     case llvm::Triple::arm:
186       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
187           *this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
188           m_notes);
189       break;
190     case llvm::Triple::riscv64:
191       m_thread_reg_ctx_sp = RegisterContextCorePOSIX_riscv64::Create(
192           *this, arch, m_gpregset_data, m_notes);
193       break;
194     case llvm::Triple::mipsel:
195     case llvm::Triple::mips:
196       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
197           *this, reg_interface, m_gpregset_data, m_notes);
198       break;
199     case llvm::Triple::mips64:
200     case llvm::Triple::mips64el:
201       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
202           *this, reg_interface, m_gpregset_data, m_notes);
203       break;
204     case llvm::Triple::ppc:
205     case llvm::Triple::ppc64:
206       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
207           *this, reg_interface, m_gpregset_data, m_notes);
208       break;
209     case llvm::Triple::ppc64le:
210       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
211           *this, reg_interface, m_gpregset_data, m_notes);
212       break;
213     case llvm::Triple::systemz:
214       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
215           *this, reg_interface, m_gpregset_data, m_notes);
216       break;
217     case llvm::Triple::x86:
218     case llvm::Triple::x86_64:
219       if (is_linux) {
220         m_thread_reg_ctx_sp = std::make_shared<RegisterContextLinuxCore_x86_64>(
221               *this, reg_interface, m_gpregset_data, m_notes);
222       } else {
223         m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
224               *this, reg_interface, m_gpregset_data, m_notes);
225       }
226       break;
227     default:
228       break;
229     }
230 
231     reg_ctx_sp = m_thread_reg_ctx_sp;
232   } else {
233     reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
234   }
235   return reg_ctx_sp;
236 }
237 
238 bool ThreadElfCore::CalculateStopInfo() {
239   ProcessSP process_sp(GetProcess());
240   if (!process_sp)
241     return false;
242 
243   SetStopInfo(StopInfo::CreateStopReasonWithSignal(
244       *this, m_signo, /*description=*/nullptr, m_code));
245   return true;
246 }
247 
248 // Parse PRSTATUS from NOTE entry
249 ELFLinuxPrStatus::ELFLinuxPrStatus() {
250   memset(this, 0, sizeof(ELFLinuxPrStatus));
251 }
252 
253 size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
254   constexpr size_t mips_linux_pr_status_size_o32 = 96;
255   constexpr size_t mips_linux_pr_status_size_n32 = 72;
256   constexpr size_t num_ptr_size_members = 10;
257   if (arch.IsMIPS()) {
258     std::string abi = arch.GetTargetABI();
259     assert(!abi.empty() && "ABI is not set");
260     if (!abi.compare("n64"))
261       return sizeof(ELFLinuxPrStatus);
262     else if (!abi.compare("o32"))
263       return mips_linux_pr_status_size_o32;
264     // N32 ABI
265     return mips_linux_pr_status_size_n32;
266   }
267   switch (arch.GetCore()) {
268   case lldb_private::ArchSpec::eCore_x86_32_i386:
269   case lldb_private::ArchSpec::eCore_x86_32_i486:
270     return 72;
271   default:
272     if (arch.GetAddressByteSize() == 8)
273       return sizeof(ELFLinuxPrStatus);
274     else
275       return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
276   }
277 }
278 
279 Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
280                                const ArchSpec &arch) {
281   Status error;
282   if (GetSize(arch) > data.GetByteSize()) {
283     error = Status::FromErrorStringWithFormat(
284         "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
285         GetSize(arch), data.GetByteSize());
286     return error;
287   }
288 
289   // Read field by field to correctly account for endianess of both the core
290   // dump and the platform running lldb.
291   offset_t offset = 0;
292   si_signo = data.GetU32(&offset);
293   si_code = data.GetU32(&offset);
294   si_errno = data.GetU32(&offset);
295 
296   pr_cursig = data.GetU16(&offset);
297   offset += 2; // pad
298 
299   pr_sigpend = data.GetAddress(&offset);
300   pr_sighold = data.GetAddress(&offset);
301 
302   pr_pid = data.GetU32(&offset);
303   pr_ppid = data.GetU32(&offset);
304   pr_pgrp = data.GetU32(&offset);
305   pr_sid = data.GetU32(&offset);
306 
307   pr_utime.tv_sec = data.GetAddress(&offset);
308   pr_utime.tv_usec = data.GetAddress(&offset);
309 
310   pr_stime.tv_sec = data.GetAddress(&offset);
311   pr_stime.tv_usec = data.GetAddress(&offset);
312 
313   pr_cutime.tv_sec = data.GetAddress(&offset);
314   pr_cutime.tv_usec = data.GetAddress(&offset);
315 
316   pr_cstime.tv_sec = data.GetAddress(&offset);
317   pr_cstime.tv_usec = data.GetAddress(&offset);
318 
319   return error;
320 }
321 
322 static struct compat_timeval
323 copy_timespecs(const ProcessInstanceInfo::timespec &oth) {
324   using sec_t = decltype(compat_timeval::tv_sec);
325   using usec_t = decltype(compat_timeval::tv_usec);
326   return {static_cast<sec_t>(oth.tv_sec), static_cast<usec_t>(oth.tv_usec)};
327 }
328 
329 std::optional<ELFLinuxPrStatus>
330 ELFLinuxPrStatus::Populate(const lldb::ThreadSP &thread_sp) {
331   ELFLinuxPrStatus prstatus{};
332   prstatus.pr_pid = thread_sp->GetID();
333   lldb::ProcessSP process_sp = thread_sp->GetProcess();
334   ProcessInstanceInfo info;
335   if (!process_sp->GetProcessInfo(info))
336     return std::nullopt;
337 
338   prstatus.pr_ppid = info.GetParentProcessID();
339   prstatus.pr_pgrp = info.GetProcessGroupID();
340   prstatus.pr_sid = info.GetProcessSessionID();
341   prstatus.pr_utime = copy_timespecs(info.GetUserTime());
342   prstatus.pr_stime = copy_timespecs(info.GetSystemTime());
343   prstatus.pr_cutime = copy_timespecs(info.GetCumulativeUserTime());
344   prstatus.pr_cstime = copy_timespecs(info.GetCumulativeSystemTime());
345   return prstatus;
346 }
347 
348 // Parse PRPSINFO from NOTE entry
349 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
350   memset(this, 0, sizeof(ELFLinuxPrPsInfo));
351 }
352 
353 size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
354   constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
355   if (arch.IsMIPS()) {
356     uint8_t address_byte_size = arch.GetAddressByteSize();
357     if (address_byte_size == 8)
358       return sizeof(ELFLinuxPrPsInfo);
359     return mips_linux_pr_psinfo_size_o32_n32;
360   }
361 
362   switch (arch.GetCore()) {
363   case lldb_private::ArchSpec::eCore_s390x_generic:
364   case lldb_private::ArchSpec::eCore_x86_64_x86_64:
365     return sizeof(ELFLinuxPrPsInfo);
366   case lldb_private::ArchSpec::eCore_x86_32_i386:
367   case lldb_private::ArchSpec::eCore_x86_32_i486:
368     return 124;
369   default:
370     return 0;
371   }
372 }
373 
374 Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
375                                const ArchSpec &arch) {
376   Status error;
377   ByteOrder byteorder = data.GetByteOrder();
378   if (GetSize(arch) > data.GetByteSize()) {
379     error = Status::FromErrorStringWithFormat(
380         "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
381         GetSize(arch), data.GetByteSize());
382     return error;
383   }
384   size_t size = 0;
385   offset_t offset = 0;
386 
387   pr_state = data.GetU8(&offset);
388   pr_sname = data.GetU8(&offset);
389   pr_zomb = data.GetU8(&offset);
390   pr_nice = data.GetU8(&offset);
391   if (data.GetAddressByteSize() == 8) {
392     // Word align the next field on 64 bit.
393     offset += 4;
394   }
395 
396   pr_flag = data.GetAddress(&offset);
397 
398   if (arch.IsMIPS()) {
399     // The pr_uid and pr_gid is always 32 bit irrespective of platforms
400     pr_uid = data.GetU32(&offset);
401     pr_gid = data.GetU32(&offset);
402   } else {
403     // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
404     pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
405     pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
406   }
407 
408   pr_pid = data.GetU32(&offset);
409   pr_ppid = data.GetU32(&offset);
410   pr_pgrp = data.GetU32(&offset);
411   pr_sid = data.GetU32(&offset);
412 
413   size = 16;
414   data.ExtractBytes(offset, size, byteorder, pr_fname);
415   offset += size;
416 
417   size = 80;
418   data.ExtractBytes(offset, size, byteorder, pr_psargs);
419   offset += size;
420 
421   return error;
422 }
423 
424 std::optional<ELFLinuxPrPsInfo>
425 ELFLinuxPrPsInfo::Populate(const lldb::ProcessSP &process_sp) {
426   ProcessInstanceInfo info;
427   if (!process_sp->GetProcessInfo(info))
428     return std::nullopt;
429 
430   return Populate(info, process_sp->GetState());
431 }
432 
433 std::optional<ELFLinuxPrPsInfo>
434 ELFLinuxPrPsInfo::Populate(const lldb_private::ProcessInstanceInfo &info,
435                            lldb::StateType process_state) {
436   ELFLinuxPrPsInfo prpsinfo{};
437   prpsinfo.pr_pid = info.GetProcessID();
438   prpsinfo.pr_nice = info.GetPriorityValue().value_or(0);
439   prpsinfo.pr_zomb = 0;
440   if (auto zombie_opt = info.IsZombie(); zombie_opt.value_or(false)) {
441     prpsinfo.pr_zomb = 1;
442   }
443   /**
444    * In the linux kernel this comes from:
445    * state = READ_ONCE(p->__state);
446    * i = state ? ffz(~state) + 1 : 0;
447    * psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i];
448    *
449    * So we replicate that here. From proc_pid_stats(5)
450    * R = Running
451    * S = Sleeping on uninterrutible wait
452    * D = Waiting on uninterruptable disk sleep
453    * T = Tracing stop
454    * Z = Zombie
455    * W = Paging
456    */
457   switch (process_state) {
458   case lldb::StateType::eStateSuspended:
459     prpsinfo.pr_sname = 'S';
460     prpsinfo.pr_state = 1;
461     break;
462   case lldb::StateType::eStateStopped:
463     [[fallthrough]];
464   case lldb::StateType::eStateStepping:
465     prpsinfo.pr_sname = 'T';
466     prpsinfo.pr_state = 3;
467     break;
468   case lldb::StateType::eStateUnloaded:
469     [[fallthrough]];
470   case lldb::StateType::eStateRunning:
471     prpsinfo.pr_sname = 'R';
472     prpsinfo.pr_state = 0;
473     break;
474   default:
475     break;
476   }
477 
478   /**
479    * pr_flags is left as 0. The values (in linux) are specific
480    * to the kernel. We recover them from the proc filesystem
481    * but don't put them in ProcessInfo because it would really
482    * become very linux specific and the utility here seems pretty
483    * dubious
484    */
485 
486   if (info.EffectiveUserIDIsValid())
487     prpsinfo.pr_uid = info.GetUserID();
488 
489   if (info.EffectiveGroupIDIsValid())
490     prpsinfo.pr_gid = info.GetGroupID();
491 
492   if (info.ParentProcessIDIsValid())
493     prpsinfo.pr_ppid = info.GetParentProcessID();
494 
495   if (info.ProcessGroupIDIsValid())
496     prpsinfo.pr_pgrp = info.GetProcessGroupID();
497 
498   if (info.ProcessSessionIDIsValid())
499     prpsinfo.pr_sid = info.GetProcessSessionID();
500 
501   constexpr size_t fname_len = std::extent_v<decltype(prpsinfo.pr_fname)>;
502   static_assert(fname_len > 0, "This should always be non zero");
503   const llvm::StringRef fname = info.GetNameAsStringRef();
504   auto fname_begin = fname.begin();
505   std::copy_n(fname_begin, std::min(fname_len, fname.size()),
506               prpsinfo.pr_fname);
507   prpsinfo.pr_fname[fname_len - 1] = '\0';
508   auto args = info.GetArguments();
509   auto argentry_iterator = std::begin(args);
510   char *psargs = prpsinfo.pr_psargs;
511   char *psargs_end = std::end(prpsinfo.pr_psargs);
512   while (psargs < psargs_end && argentry_iterator != args.end()) {
513     llvm::StringRef argentry = argentry_iterator->ref();
514     size_t len =
515         std::min<size_t>(std::distance(psargs, psargs_end), argentry.size());
516     auto arg_iterator = std::begin(argentry);
517     psargs = std::copy_n(arg_iterator, len, psargs);
518     if (psargs != psargs_end)
519       *(psargs++) = ' ';
520     ++argentry_iterator;
521   }
522   *(psargs - 1) = '\0';
523   return prpsinfo;
524 }
525 
526 // Parse SIGINFO from NOTE entry
527 ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
528 
529 size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
530   if (arch.IsMIPS())
531     return sizeof(ELFLinuxSigInfo);
532   switch (arch.GetCore()) {
533   case lldb_private::ArchSpec::eCore_x86_64_x86_64:
534     return sizeof(ELFLinuxSigInfo);
535   case lldb_private::ArchSpec::eCore_s390x_generic:
536   case lldb_private::ArchSpec::eCore_x86_32_i386:
537   case lldb_private::ArchSpec::eCore_x86_32_i486:
538     return 12;
539   default:
540     return 0;
541   }
542 }
543 
544 Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
545   Status error;
546   if (GetSize(arch) > data.GetByteSize()) {
547     error = Status::FromErrorStringWithFormat(
548         "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
549         GetSize(arch), data.GetByteSize());
550     return error;
551   }
552 
553   // Parsing from a 32 bit ELF core file, and populating/reusing the structure
554   // properly, because the struct is for the 64 bit version
555   offset_t offset = 0;
556   si_signo = data.GetU32(&offset);
557   si_errno = data.GetU32(&offset);
558   si_code = data.GetU32(&offset);
559 
560   return error;
561 }
562