1254721Semaste//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "lldb/Target/RegisterContext.h"
10254721Semaste#include "lldb/Target/StopInfo.h"
11254721Semaste#include "lldb/Target/Target.h"
12254721Semaste#include "lldb/Target/Unwind.h"
13321369Sdim#include "lldb/Utility/DataExtractor.h"
14321369Sdim#include "lldb/Utility/Log.h"
15254721Semaste
16280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
17280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
18280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
19280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
20327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
21327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
22321369Sdim#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
23327952Sdim#ifdef LLDB_ENABLE_ALL
24327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
25327952Sdim#endif // LLDB_ENABLE_ALL
26314564Sdim#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
27321369Sdim#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
28321369Sdim#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
29321369Sdim#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
30321369Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
31314564Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
32327952Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
33314564Sdim#include "ProcessElfCore.h"
34288943Sdim#include "RegisterContextPOSIXCore_arm.h"
35288943Sdim#include "RegisterContextPOSIXCore_arm64.h"
36258054Semaste#include "RegisterContextPOSIXCore_mips64.h"
37280031Sdim#include "RegisterContextPOSIXCore_powerpc.h"
38327952Sdim#include "RegisterContextPOSIXCore_ppc64le.h"
39327952Sdim#ifdef LLDB_ENABLE_ALL
40327952Sdim#include "RegisterContextPOSIXCore_s390x.h"
41327952Sdim#endif // LLDB_ENABLE_ALL
42258054Semaste#include "RegisterContextPOSIXCore_x86_64.h"
43314564Sdim#include "ThreadElfCore.h"
44254721Semaste
45353358Sdim#include <memory>
46353358Sdim
47254721Semasteusing namespace lldb;
48254721Semasteusing namespace lldb_private;
49254721Semaste
50254721Semaste// Construct a Thread object with given data
51314564SdimThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
52314564Sdim    : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
53327952Sdim      m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {}
54254721Semaste
55314564SdimThreadElfCore::~ThreadElfCore() { DestroyThread(); }
56254721Semaste
57314564Sdimvoid ThreadElfCore::RefreshStateAfterStop() {
58314564Sdim  GetRegisterContext()->InvalidateIfNeeded(false);
59254721Semaste}
60254721Semaste
61314564SdimRegisterContextSP ThreadElfCore::GetRegisterContext() {
62341825Sdim  if (!m_reg_context_sp) {
63341825Sdim    m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
64314564Sdim  }
65314564Sdim  return m_reg_context_sp;
66254721Semaste}
67254721Semaste
68254721SemasteRegisterContextSP
69314564SdimThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
70314564Sdim  RegisterContextSP reg_ctx_sp;
71314564Sdim  uint32_t concrete_frame_idx = 0;
72314564Sdim  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
73254721Semaste
74314564Sdim  if (frame)
75314564Sdim    concrete_frame_idx = frame->GetConcreteFrameIndex();
76254721Semaste
77314564Sdim  if (concrete_frame_idx == 0) {
78314564Sdim    if (m_thread_reg_ctx_sp)
79314564Sdim      return m_thread_reg_ctx_sp;
80254721Semaste
81314564Sdim    ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
82314564Sdim    ArchSpec arch = process->GetArchitecture();
83341825Sdim    RegisterInfoInterface *reg_interface = nullptr;
84262528Semaste
85314564Sdim    switch (arch.GetTriple().getOS()) {
86314564Sdim    case llvm::Triple::FreeBSD: {
87314564Sdim      switch (arch.GetMachine()) {
88314564Sdim      case llvm::Triple::aarch64:
89314564Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
90314564Sdim        break;
91314564Sdim      case llvm::Triple::arm:
92321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
93314564Sdim        break;
94314564Sdim      case llvm::Triple::ppc:
95314564Sdim        reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
96314564Sdim        break;
97314564Sdim      case llvm::Triple::ppc64:
98314564Sdim        reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
99314564Sdim        break;
100314564Sdim      case llvm::Triple::mips64:
101314564Sdim        reg_interface = new RegisterContextFreeBSD_mips64(arch);
102314564Sdim        break;
103314564Sdim      case llvm::Triple::x86:
104314564Sdim        reg_interface = new RegisterContextFreeBSD_i386(arch);
105314564Sdim        break;
106314564Sdim      case llvm::Triple::x86_64:
107314564Sdim        reg_interface = new RegisterContextFreeBSD_x86_64(arch);
108314564Sdim        break;
109314564Sdim      default:
110314564Sdim        break;
111314564Sdim      }
112314564Sdim      break;
113314564Sdim    }
114276479Sdim
115321369Sdim    case llvm::Triple::NetBSD: {
116321369Sdim      switch (arch.GetMachine()) {
117353358Sdim      case llvm::Triple::aarch64:
118353358Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
119353358Sdim        break;
120321369Sdim      case llvm::Triple::x86_64:
121321369Sdim        reg_interface = new RegisterContextNetBSD_x86_64(arch);
122321369Sdim        break;
123321369Sdim      default:
124321369Sdim        break;
125321369Sdim      }
126321369Sdim      break;
127321369Sdim    }
128321369Sdim
129314564Sdim    case llvm::Triple::Linux: {
130314564Sdim      switch (arch.GetMachine()) {
131314564Sdim      case llvm::Triple::arm:
132321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
133314564Sdim        break;
134314564Sdim      case llvm::Triple::aarch64:
135314564Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
136314564Sdim        break;
137321369Sdim      case llvm::Triple::mipsel:
138321369Sdim      case llvm::Triple::mips:
139321369Sdim        reg_interface = new RegisterContextLinux_mips(arch);
140321369Sdim        break;
141321369Sdim      case llvm::Triple::mips64el:
142321369Sdim      case llvm::Triple::mips64:
143321369Sdim        reg_interface = new RegisterContextLinux_mips64(arch);
144321369Sdim        break;
145327952Sdim      case llvm::Triple::ppc64le:
146327952Sdim        reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
147327952Sdim        break;
148327952Sdim#ifdef LLDB_ENABLE_ALL
149327952Sdim      case llvm::Triple::systemz:
150327952Sdim        reg_interface = new RegisterContextLinux_s390x(arch);
151327952Sdim        break;
152327952Sdim#endif // LLDB_ENABLE_ALL
153314564Sdim      case llvm::Triple::x86:
154314564Sdim        reg_interface = new RegisterContextLinux_i386(arch);
155314564Sdim        break;
156314564Sdim      case llvm::Triple::x86_64:
157314564Sdim        reg_interface = new RegisterContextLinux_x86_64(arch);
158314564Sdim        break;
159314564Sdim      default:
160314564Sdim        break;
161314564Sdim      }
162314564Sdim      break;
163314564Sdim    }
164262528Semaste
165321369Sdim    case llvm::Triple::OpenBSD: {
166321369Sdim      switch (arch.GetMachine()) {
167321369Sdim      case llvm::Triple::aarch64:
168321369Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
169321369Sdim        break;
170321369Sdim      case llvm::Triple::arm:
171321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
172321369Sdim        break;
173321369Sdim      case llvm::Triple::x86:
174321369Sdim        reg_interface = new RegisterContextOpenBSD_i386(arch);
175321369Sdim        break;
176321369Sdim      case llvm::Triple::x86_64:
177321369Sdim        reg_interface = new RegisterContextOpenBSD_x86_64(arch);
178321369Sdim        break;
179321369Sdim      default:
180321369Sdim        break;
181321369Sdim      }
182321369Sdim      break;
183321369Sdim    }
184321369Sdim
185314564Sdim    default:
186314564Sdim      break;
187314564Sdim    }
188262528Semaste
189314564Sdim    if (!reg_interface) {
190360784Sdim      LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
191360784Sdim                __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
192314564Sdim      assert(false && "Architecture or OS not supported");
193314564Sdim    }
194262528Semaste
195314564Sdim    switch (arch.GetMachine()) {
196314564Sdim    case llvm::Triple::aarch64:
197353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
198353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
199314564Sdim      break;
200314564Sdim    case llvm::Triple::arm:
201353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
202353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
203314564Sdim      break;
204321369Sdim    case llvm::Triple::mipsel:
205321369Sdim    case llvm::Triple::mips:
206353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
207353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
208321369Sdim      break;
209314564Sdim    case llvm::Triple::mips64:
210321369Sdim    case llvm::Triple::mips64el:
211353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
212353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
213314564Sdim      break;
214314564Sdim    case llvm::Triple::ppc:
215314564Sdim    case llvm::Triple::ppc64:
216353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
217353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
218314564Sdim      break;
219327952Sdim    case llvm::Triple::ppc64le:
220353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
221353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
222327952Sdim      break;
223327952Sdim#ifdef LLDB_ENABLE_ALL
224327952Sdim    case llvm::Triple::systemz:
225353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
226353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
227327952Sdim      break;
228327952Sdim#endif // LLDB_ENABLE_ALL
229314564Sdim    case llvm::Triple::x86:
230314564Sdim    case llvm::Triple::x86_64:
231353358Sdim      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
232353358Sdim          *this, reg_interface, m_gpregset_data, m_notes);
233314564Sdim      break;
234314564Sdim    default:
235314564Sdim      break;
236314564Sdim    }
237262528Semaste
238314564Sdim    reg_ctx_sp = m_thread_reg_ctx_sp;
239341825Sdim  } else {
240341825Sdim    Unwind *unwinder = GetUnwinder();
241341825Sdim    if (unwinder != nullptr)
242341825Sdim      reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
243314564Sdim  }
244314564Sdim  return reg_ctx_sp;
245254721Semaste}
246254721Semaste
247314564Sdimbool ThreadElfCore::CalculateStopInfo() {
248314564Sdim  ProcessSP process_sp(GetProcess());
249314564Sdim  if (process_sp) {
250314564Sdim    SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
251314564Sdim    return true;
252314564Sdim  }
253314564Sdim  return false;
254254721Semaste}
255254721Semaste
256254721Semaste// Parse PRSTATUS from NOTE entry
257314564SdimELFLinuxPrStatus::ELFLinuxPrStatus() {
258314564Sdim  memset(this, 0, sizeof(ELFLinuxPrStatus));
259254721Semaste}
260254721Semaste
261327952Sdimsize_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
262321369Sdim  constexpr size_t mips_linux_pr_status_size_o32 = 96;
263321369Sdim  constexpr size_t mips_linux_pr_status_size_n32 = 72;
264353358Sdim  constexpr size_t num_ptr_size_members = 10;
265321369Sdim  if (arch.IsMIPS()) {
266321369Sdim    std::string abi = arch.GetTargetABI();
267321369Sdim    assert(!abi.empty() && "ABI is not set");
268321369Sdim    if (!abi.compare("n64"))
269321369Sdim      return sizeof(ELFLinuxPrStatus);
270321369Sdim    else if (!abi.compare("o32"))
271321369Sdim      return mips_linux_pr_status_size_o32;
272321369Sdim    // N32 ABI
273321369Sdim    return mips_linux_pr_status_size_n32;
274321369Sdim  }
275321369Sdim  switch (arch.GetCore()) {
276321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
277321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
278321369Sdim    return 72;
279321369Sdim  default:
280353358Sdim    if (arch.GetAddressByteSize() == 8)
281353358Sdim      return sizeof(ELFLinuxPrStatus);
282353358Sdim    else
283353358Sdim      return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
284321369Sdim  }
285321369Sdim}
286321369Sdim
287327952SdimStatus ELFLinuxPrStatus::Parse(const DataExtractor &data,
288327952Sdim                               const ArchSpec &arch) {
289321369Sdim  Status error;
290314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
291314564Sdim    error.SetErrorStringWithFormat(
292314564Sdim        "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
293314564Sdim        GetSize(arch), data.GetByteSize());
294314564Sdim    return error;
295314564Sdim  }
296314564Sdim
297341825Sdim  // Read field by field to correctly account for endianess of both the core
298341825Sdim  // dump and the platform running lldb.
299314564Sdim  offset_t offset = 0;
300314564Sdim  si_signo = data.GetU32(&offset);
301314564Sdim  si_code = data.GetU32(&offset);
302314564Sdim  si_errno = data.GetU32(&offset);
303314564Sdim
304314564Sdim  pr_cursig = data.GetU16(&offset);
305314564Sdim  offset += 2; // pad
306314564Sdim
307314564Sdim  pr_sigpend = data.GetPointer(&offset);
308314564Sdim  pr_sighold = data.GetPointer(&offset);
309314564Sdim
310314564Sdim  pr_pid = data.GetU32(&offset);
311314564Sdim  pr_ppid = data.GetU32(&offset);
312314564Sdim  pr_pgrp = data.GetU32(&offset);
313314564Sdim  pr_sid = data.GetU32(&offset);
314314564Sdim
315314564Sdim  pr_utime.tv_sec = data.GetPointer(&offset);
316314564Sdim  pr_utime.tv_usec = data.GetPointer(&offset);
317314564Sdim
318314564Sdim  pr_stime.tv_sec = data.GetPointer(&offset);
319314564Sdim  pr_stime.tv_usec = data.GetPointer(&offset);
320314564Sdim
321314564Sdim  pr_cutime.tv_sec = data.GetPointer(&offset);
322314564Sdim  pr_cutime.tv_usec = data.GetPointer(&offset);
323314564Sdim
324314564Sdim  pr_cstime.tv_sec = data.GetPointer(&offset);
325314564Sdim  pr_cstime.tv_usec = data.GetPointer(&offset);
326314564Sdim
327314564Sdim  return error;
328254721Semaste}
329254721Semaste
330254721Semaste// Parse PRPSINFO from NOTE entry
331314564SdimELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
332314564Sdim  memset(this, 0, sizeof(ELFLinuxPrPsInfo));
333254721Semaste}
334254721Semaste
335327952Sdimsize_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
336321369Sdim  constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
337321369Sdim  if (arch.IsMIPS()) {
338321369Sdim    uint8_t address_byte_size = arch.GetAddressByteSize();
339321369Sdim    if (address_byte_size == 8)
340321369Sdim      return sizeof(ELFLinuxPrPsInfo);
341321369Sdim    return mips_linux_pr_psinfo_size_o32_n32;
342321369Sdim  }
343341825Sdim
344321369Sdim  switch (arch.GetCore()) {
345321369Sdim  case lldb_private::ArchSpec::eCore_s390x_generic:
346321369Sdim  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
347321369Sdim    return sizeof(ELFLinuxPrPsInfo);
348321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
349321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
350321369Sdim    return 124;
351321369Sdim  default:
352321369Sdim    return 0;
353321369Sdim  }
354321369Sdim}
355321369Sdim
356327952SdimStatus ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
357327952Sdim                               const ArchSpec &arch) {
358321369Sdim  Status error;
359314564Sdim  ByteOrder byteorder = data.GetByteOrder();
360314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
361314564Sdim    error.SetErrorStringWithFormat(
362314564Sdim        "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
363314564Sdim        GetSize(arch), data.GetByteSize());
364314564Sdim    return error;
365314564Sdim  }
366314564Sdim  size_t size = 0;
367314564Sdim  offset_t offset = 0;
368314564Sdim
369314564Sdim  pr_state = data.GetU8(&offset);
370314564Sdim  pr_sname = data.GetU8(&offset);
371314564Sdim  pr_zomb = data.GetU8(&offset);
372314564Sdim  pr_nice = data.GetU8(&offset);
373314564Sdim  if (data.GetAddressByteSize() == 8) {
374314564Sdim    // Word align the next field on 64 bit.
375314564Sdim    offset += 4;
376314564Sdim  }
377314564Sdim
378314564Sdim  pr_flag = data.GetPointer(&offset);
379314564Sdim
380321369Sdim  if (arch.IsMIPS()) {
381321369Sdim    // The pr_uid and pr_gid is always 32 bit irrespective of platforms
382321369Sdim    pr_uid = data.GetU32(&offset);
383321369Sdim    pr_gid = data.GetU32(&offset);
384321369Sdim  } else {
385341825Sdim    // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
386341825Sdim    pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
387341825Sdim    pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
388321369Sdim  }
389314564Sdim
390314564Sdim  pr_pid = data.GetU32(&offset);
391314564Sdim  pr_ppid = data.GetU32(&offset);
392314564Sdim  pr_pgrp = data.GetU32(&offset);
393314564Sdim  pr_sid = data.GetU32(&offset);
394314564Sdim
395314564Sdim  size = 16;
396314564Sdim  data.ExtractBytes(offset, size, byteorder, pr_fname);
397314564Sdim  offset += size;
398314564Sdim
399314564Sdim  size = 80;
400314564Sdim  data.ExtractBytes(offset, size, byteorder, pr_psargs);
401314564Sdim  offset += size;
402314564Sdim
403314564Sdim  return error;
404254721Semaste}
405254721Semaste
406314564Sdim// Parse SIGINFO from NOTE entry
407321369SdimELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
408321369Sdim
409321369Sdimsize_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
410321369Sdim  if (arch.IsMIPS())
411321369Sdim    return sizeof(ELFLinuxSigInfo);
412321369Sdim  switch (arch.GetCore()) {
413321369Sdim  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
414321369Sdim    return sizeof(ELFLinuxSigInfo);
415321369Sdim  case lldb_private::ArchSpec::eCore_s390x_generic:
416321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
417321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
418321369Sdim    return 12;
419321369Sdim  default:
420321369Sdim    return 0;
421321369Sdim  }
422314564Sdim}
423314564Sdim
424327952SdimStatus ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
425321369Sdim  Status error;
426314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
427314564Sdim    error.SetErrorStringWithFormat(
428314564Sdim        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
429314564Sdim        GetSize(arch), data.GetByteSize());
430314564Sdim    return error;
431314564Sdim  }
432314564Sdim
433314564Sdim  // Parsing from a 32 bit ELF core file, and populating/reusing the structure
434314564Sdim  // properly, because the struct is for the 64 bit version
435314564Sdim  offset_t offset = 0;
436314564Sdim  si_signo = data.GetU32(&offset);
437314564Sdim  si_code = data.GetU32(&offset);
438314564Sdim  si_errno = data.GetU32(&offset);
439314564Sdim
440314564Sdim  return error;
441314564Sdim}
442