1//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
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/Log.h"
15
16#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
17#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
18#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
19#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
20#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
21#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
22#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
23#ifdef LLDB_ENABLE_ALL
24#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
25#endif // LLDB_ENABLE_ALL
26#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
27#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
28#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
29#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
30#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
31#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
32#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
33#include "ProcessElfCore.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#ifdef LLDB_ENABLE_ALL
40#include "RegisterContextPOSIXCore_s390x.h"
41#endif // LLDB_ENABLE_ALL
42#include "RegisterContextPOSIXCore_x86_64.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
51ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
52    : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
53      m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {}
54
55ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
56
57void ThreadElfCore::RefreshStateAfterStop() {
58  GetRegisterContext()->InvalidateIfNeeded(false);
59}
60
61RegisterContextSP ThreadElfCore::GetRegisterContext() {
62  if (!m_reg_context_sp) {
63    m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
64  }
65  return m_reg_context_sp;
66}
67
68RegisterContextSP
69ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
70  RegisterContextSP reg_ctx_sp;
71  uint32_t concrete_frame_idx = 0;
72  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
73
74  if (frame)
75    concrete_frame_idx = frame->GetConcreteFrameIndex();
76
77  if (concrete_frame_idx == 0) {
78    if (m_thread_reg_ctx_sp)
79      return m_thread_reg_ctx_sp;
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        reg_interface = new RegisterInfoPOSIX_arm64(arch);
90        break;
91      case llvm::Triple::arm:
92        reg_interface = new RegisterInfoPOSIX_arm(arch);
93        break;
94      case llvm::Triple::ppc:
95        reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
96        break;
97      case llvm::Triple::ppc64:
98        reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
99        break;
100      case llvm::Triple::mips64:
101        reg_interface = new RegisterContextFreeBSD_mips64(arch);
102        break;
103      case llvm::Triple::x86:
104        reg_interface = new RegisterContextFreeBSD_i386(arch);
105        break;
106      case llvm::Triple::x86_64:
107        reg_interface = new RegisterContextFreeBSD_x86_64(arch);
108        break;
109      default:
110        break;
111      }
112      break;
113    }
114
115    case llvm::Triple::NetBSD: {
116      switch (arch.GetMachine()) {
117      case llvm::Triple::aarch64:
118        reg_interface = new RegisterInfoPOSIX_arm64(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      switch (arch.GetMachine()) {
131      case llvm::Triple::arm:
132        reg_interface = new RegisterInfoPOSIX_arm(arch);
133        break;
134      case llvm::Triple::aarch64:
135        reg_interface = new RegisterInfoPOSIX_arm64(arch);
136        break;
137      case llvm::Triple::mipsel:
138      case llvm::Triple::mips:
139        reg_interface = new RegisterContextLinux_mips(arch);
140        break;
141      case llvm::Triple::mips64el:
142      case llvm::Triple::mips64:
143        reg_interface = new RegisterContextLinux_mips64(arch);
144        break;
145      case llvm::Triple::ppc64le:
146        reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
147        break;
148#ifdef LLDB_ENABLE_ALL
149      case llvm::Triple::systemz:
150        reg_interface = new RegisterContextLinux_s390x(arch);
151        break;
152#endif // LLDB_ENABLE_ALL
153      case llvm::Triple::x86:
154        reg_interface = new RegisterContextLinux_i386(arch);
155        break;
156      case llvm::Triple::x86_64:
157        reg_interface = new RegisterContextLinux_x86_64(arch);
158        break;
159      default:
160        break;
161      }
162      break;
163    }
164
165    case llvm::Triple::OpenBSD: {
166      switch (arch.GetMachine()) {
167      case llvm::Triple::aarch64:
168        reg_interface = new RegisterInfoPOSIX_arm64(arch);
169        break;
170      case llvm::Triple::arm:
171        reg_interface = new RegisterInfoPOSIX_arm(arch);
172        break;
173      case llvm::Triple::x86:
174        reg_interface = new RegisterContextOpenBSD_i386(arch);
175        break;
176      case llvm::Triple::x86_64:
177        reg_interface = new RegisterContextOpenBSD_x86_64(arch);
178        break;
179      default:
180        break;
181      }
182      break;
183    }
184
185    default:
186      break;
187    }
188
189    if (!reg_interface) {
190      LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
191                __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
192      assert(false && "Architecture or OS not supported");
193    }
194
195    switch (arch.GetMachine()) {
196    case llvm::Triple::aarch64:
197      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
198          *this, reg_interface, m_gpregset_data, m_notes);
199      break;
200    case llvm::Triple::arm:
201      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
202          *this, reg_interface, m_gpregset_data, m_notes);
203      break;
204    case llvm::Triple::mipsel:
205    case llvm::Triple::mips:
206      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
207          *this, reg_interface, m_gpregset_data, m_notes);
208      break;
209    case llvm::Triple::mips64:
210    case llvm::Triple::mips64el:
211      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
212          *this, reg_interface, m_gpregset_data, m_notes);
213      break;
214    case llvm::Triple::ppc:
215    case llvm::Triple::ppc64:
216      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
217          *this, reg_interface, m_gpregset_data, m_notes);
218      break;
219    case llvm::Triple::ppc64le:
220      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
221          *this, reg_interface, m_gpregset_data, m_notes);
222      break;
223#ifdef LLDB_ENABLE_ALL
224    case llvm::Triple::systemz:
225      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
226          *this, reg_interface, m_gpregset_data, m_notes);
227      break;
228#endif // LLDB_ENABLE_ALL
229    case llvm::Triple::x86:
230    case llvm::Triple::x86_64:
231      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
232          *this, reg_interface, m_gpregset_data, m_notes);
233      break;
234    default:
235      break;
236    }
237
238    reg_ctx_sp = m_thread_reg_ctx_sp;
239  } else {
240    Unwind *unwinder = GetUnwinder();
241    if (unwinder != nullptr)
242      reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
243  }
244  return reg_ctx_sp;
245}
246
247bool ThreadElfCore::CalculateStopInfo() {
248  ProcessSP process_sp(GetProcess());
249  if (process_sp) {
250    SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
251    return true;
252  }
253  return false;
254}
255
256// Parse PRSTATUS from NOTE entry
257ELFLinuxPrStatus::ELFLinuxPrStatus() {
258  memset(this, 0, sizeof(ELFLinuxPrStatus));
259}
260
261size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
262  constexpr size_t mips_linux_pr_status_size_o32 = 96;
263  constexpr size_t mips_linux_pr_status_size_n32 = 72;
264  constexpr size_t num_ptr_size_members = 10;
265  if (arch.IsMIPS()) {
266    std::string abi = arch.GetTargetABI();
267    assert(!abi.empty() && "ABI is not set");
268    if (!abi.compare("n64"))
269      return sizeof(ELFLinuxPrStatus);
270    else if (!abi.compare("o32"))
271      return mips_linux_pr_status_size_o32;
272    // N32 ABI
273    return mips_linux_pr_status_size_n32;
274  }
275  switch (arch.GetCore()) {
276  case lldb_private::ArchSpec::eCore_x86_32_i386:
277  case lldb_private::ArchSpec::eCore_x86_32_i486:
278    return 72;
279  default:
280    if (arch.GetAddressByteSize() == 8)
281      return sizeof(ELFLinuxPrStatus);
282    else
283      return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
284  }
285}
286
287Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
288                               const ArchSpec &arch) {
289  Status error;
290  if (GetSize(arch) > data.GetByteSize()) {
291    error.SetErrorStringWithFormat(
292        "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
293        GetSize(arch), data.GetByteSize());
294    return error;
295  }
296
297  // Read field by field to correctly account for endianess of both the core
298  // dump and the platform running lldb.
299  offset_t offset = 0;
300  si_signo = data.GetU32(&offset);
301  si_code = data.GetU32(&offset);
302  si_errno = data.GetU32(&offset);
303
304  pr_cursig = data.GetU16(&offset);
305  offset += 2; // pad
306
307  pr_sigpend = data.GetPointer(&offset);
308  pr_sighold = data.GetPointer(&offset);
309
310  pr_pid = data.GetU32(&offset);
311  pr_ppid = data.GetU32(&offset);
312  pr_pgrp = data.GetU32(&offset);
313  pr_sid = data.GetU32(&offset);
314
315  pr_utime.tv_sec = data.GetPointer(&offset);
316  pr_utime.tv_usec = data.GetPointer(&offset);
317
318  pr_stime.tv_sec = data.GetPointer(&offset);
319  pr_stime.tv_usec = data.GetPointer(&offset);
320
321  pr_cutime.tv_sec = data.GetPointer(&offset);
322  pr_cutime.tv_usec = data.GetPointer(&offset);
323
324  pr_cstime.tv_sec = data.GetPointer(&offset);
325  pr_cstime.tv_usec = data.GetPointer(&offset);
326
327  return error;
328}
329
330// Parse PRPSINFO from NOTE entry
331ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
332  memset(this, 0, sizeof(ELFLinuxPrPsInfo));
333}
334
335size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
336  constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
337  if (arch.IsMIPS()) {
338    uint8_t address_byte_size = arch.GetAddressByteSize();
339    if (address_byte_size == 8)
340      return sizeof(ELFLinuxPrPsInfo);
341    return mips_linux_pr_psinfo_size_o32_n32;
342  }
343
344  switch (arch.GetCore()) {
345  case lldb_private::ArchSpec::eCore_s390x_generic:
346  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
347    return sizeof(ELFLinuxPrPsInfo);
348  case lldb_private::ArchSpec::eCore_x86_32_i386:
349  case lldb_private::ArchSpec::eCore_x86_32_i486:
350    return 124;
351  default:
352    return 0;
353  }
354}
355
356Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
357                               const ArchSpec &arch) {
358  Status error;
359  ByteOrder byteorder = data.GetByteOrder();
360  if (GetSize(arch) > data.GetByteSize()) {
361    error.SetErrorStringWithFormat(
362        "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
363        GetSize(arch), data.GetByteSize());
364    return error;
365  }
366  size_t size = 0;
367  offset_t offset = 0;
368
369  pr_state = data.GetU8(&offset);
370  pr_sname = data.GetU8(&offset);
371  pr_zomb = data.GetU8(&offset);
372  pr_nice = data.GetU8(&offset);
373  if (data.GetAddressByteSize() == 8) {
374    // Word align the next field on 64 bit.
375    offset += 4;
376  }
377
378  pr_flag = data.GetPointer(&offset);
379
380  if (arch.IsMIPS()) {
381    // The pr_uid and pr_gid is always 32 bit irrespective of platforms
382    pr_uid = data.GetU32(&offset);
383    pr_gid = data.GetU32(&offset);
384  } else {
385    // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
386    pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
387    pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
388  }
389
390  pr_pid = data.GetU32(&offset);
391  pr_ppid = data.GetU32(&offset);
392  pr_pgrp = data.GetU32(&offset);
393  pr_sid = data.GetU32(&offset);
394
395  size = 16;
396  data.ExtractBytes(offset, size, byteorder, pr_fname);
397  offset += size;
398
399  size = 80;
400  data.ExtractBytes(offset, size, byteorder, pr_psargs);
401  offset += size;
402
403  return error;
404}
405
406// Parse SIGINFO from NOTE entry
407ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
408
409size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
410  if (arch.IsMIPS())
411    return sizeof(ELFLinuxSigInfo);
412  switch (arch.GetCore()) {
413  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
414    return sizeof(ELFLinuxSigInfo);
415  case lldb_private::ArchSpec::eCore_s390x_generic:
416  case lldb_private::ArchSpec::eCore_x86_32_i386:
417  case lldb_private::ArchSpec::eCore_x86_32_i486:
418    return 12;
419  default:
420    return 0;
421  }
422}
423
424Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
425  Status error;
426  if (GetSize(arch) > data.GetByteSize()) {
427    error.SetErrorStringWithFormat(
428        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
429        GetSize(arch), data.GetByteSize());
430    return error;
431  }
432
433  // Parsing from a 32 bit ELF core file, and populating/reusing the structure
434  // properly, because the struct is for the 64 bit version
435  offset_t offset = 0;
436  si_signo = data.GetU32(&offset);
437  si_code = data.GetU32(&offset);
438  si_errno = data.GetU32(&offset);
439
440  return error;
441}
442