ThreadElfCore.cpp revision 360660
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      if (log)
191        log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
192                    __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
193      assert(false && "Architecture or OS not supported");
194    }
195
196    switch (arch.GetMachine()) {
197    case llvm::Triple::aarch64:
198      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
199          *this, reg_interface, m_gpregset_data, m_notes);
200      break;
201    case llvm::Triple::arm:
202      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
203          *this, reg_interface, m_gpregset_data, m_notes);
204      break;
205    case llvm::Triple::mipsel:
206    case llvm::Triple::mips:
207      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
208          *this, reg_interface, m_gpregset_data, m_notes);
209      break;
210    case llvm::Triple::mips64:
211    case llvm::Triple::mips64el:
212      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
213          *this, reg_interface, m_gpregset_data, m_notes);
214      break;
215    case llvm::Triple::ppc:
216    case llvm::Triple::ppc64:
217      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
218          *this, reg_interface, m_gpregset_data, m_notes);
219      break;
220    case llvm::Triple::ppc64le:
221      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
222          *this, reg_interface, m_gpregset_data, m_notes);
223      break;
224#ifdef LLDB_ENABLE_ALL
225    case llvm::Triple::systemz:
226      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
227          *this, reg_interface, m_gpregset_data, m_notes);
228      break;
229#endif // LLDB_ENABLE_ALL
230    case llvm::Triple::x86:
231    case llvm::Triple::x86_64:
232      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
233          *this, reg_interface, m_gpregset_data, m_notes);
234      break;
235    default:
236      break;
237    }
238
239    reg_ctx_sp = m_thread_reg_ctx_sp;
240  } else {
241    Unwind *unwinder = GetUnwinder();
242    if (unwinder != nullptr)
243      reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
244  }
245  return reg_ctx_sp;
246}
247
248bool ThreadElfCore::CalculateStopInfo() {
249  ProcessSP process_sp(GetProcess());
250  if (process_sp) {
251    SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
252    return true;
253  }
254  return false;
255}
256
257// Parse PRSTATUS from NOTE entry
258ELFLinuxPrStatus::ELFLinuxPrStatus() {
259  memset(this, 0, sizeof(ELFLinuxPrStatus));
260}
261
262size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
263  constexpr size_t mips_linux_pr_status_size_o32 = 96;
264  constexpr size_t mips_linux_pr_status_size_n32 = 72;
265  constexpr size_t num_ptr_size_members = 10;
266  if (arch.IsMIPS()) {
267    std::string abi = arch.GetTargetABI();
268    assert(!abi.empty() && "ABI is not set");
269    if (!abi.compare("n64"))
270      return sizeof(ELFLinuxPrStatus);
271    else if (!abi.compare("o32"))
272      return mips_linux_pr_status_size_o32;
273    // N32 ABI
274    return mips_linux_pr_status_size_n32;
275  }
276  switch (arch.GetCore()) {
277  case lldb_private::ArchSpec::eCore_x86_32_i386:
278  case lldb_private::ArchSpec::eCore_x86_32_i486:
279    return 72;
280  default:
281    if (arch.GetAddressByteSize() == 8)
282      return sizeof(ELFLinuxPrStatus);
283    else
284      return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
285  }
286}
287
288Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
289                               const ArchSpec &arch) {
290  Status error;
291  if (GetSize(arch) > data.GetByteSize()) {
292    error.SetErrorStringWithFormat(
293        "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
294        GetSize(arch), data.GetByteSize());
295    return error;
296  }
297
298  // Read field by field to correctly account for endianess of both the core
299  // dump and the platform running lldb.
300  offset_t offset = 0;
301  si_signo = data.GetU32(&offset);
302  si_code = data.GetU32(&offset);
303  si_errno = data.GetU32(&offset);
304
305  pr_cursig = data.GetU16(&offset);
306  offset += 2; // pad
307
308  pr_sigpend = data.GetPointer(&offset);
309  pr_sighold = data.GetPointer(&offset);
310
311  pr_pid = data.GetU32(&offset);
312  pr_ppid = data.GetU32(&offset);
313  pr_pgrp = data.GetU32(&offset);
314  pr_sid = data.GetU32(&offset);
315
316  pr_utime.tv_sec = data.GetPointer(&offset);
317  pr_utime.tv_usec = data.GetPointer(&offset);
318
319  pr_stime.tv_sec = data.GetPointer(&offset);
320  pr_stime.tv_usec = data.GetPointer(&offset);
321
322  pr_cutime.tv_sec = data.GetPointer(&offset);
323  pr_cutime.tv_usec = data.GetPointer(&offset);
324
325  pr_cstime.tv_sec = data.GetPointer(&offset);
326  pr_cstime.tv_usec = data.GetPointer(&offset);
327
328  return error;
329}
330
331// Parse PRPSINFO from NOTE entry
332ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
333  memset(this, 0, sizeof(ELFLinuxPrPsInfo));
334}
335
336size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
337  constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
338  if (arch.IsMIPS()) {
339    uint8_t address_byte_size = arch.GetAddressByteSize();
340    if (address_byte_size == 8)
341      return sizeof(ELFLinuxPrPsInfo);
342    return mips_linux_pr_psinfo_size_o32_n32;
343  }
344
345  switch (arch.GetCore()) {
346  case lldb_private::ArchSpec::eCore_s390x_generic:
347  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
348    return sizeof(ELFLinuxPrPsInfo);
349  case lldb_private::ArchSpec::eCore_x86_32_i386:
350  case lldb_private::ArchSpec::eCore_x86_32_i486:
351    return 124;
352  default:
353    return 0;
354  }
355}
356
357Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
358                               const ArchSpec &arch) {
359  Status error;
360  ByteOrder byteorder = data.GetByteOrder();
361  if (GetSize(arch) > data.GetByteSize()) {
362    error.SetErrorStringWithFormat(
363        "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
364        GetSize(arch), data.GetByteSize());
365    return error;
366  }
367  size_t size = 0;
368  offset_t offset = 0;
369
370  pr_state = data.GetU8(&offset);
371  pr_sname = data.GetU8(&offset);
372  pr_zomb = data.GetU8(&offset);
373  pr_nice = data.GetU8(&offset);
374  if (data.GetAddressByteSize() == 8) {
375    // Word align the next field on 64 bit.
376    offset += 4;
377  }
378
379  pr_flag = data.GetPointer(&offset);
380
381  if (arch.IsMIPS()) {
382    // The pr_uid and pr_gid is always 32 bit irrespective of platforms
383    pr_uid = data.GetU32(&offset);
384    pr_gid = data.GetU32(&offset);
385  } else {
386    // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
387    pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
388    pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
389  }
390
391  pr_pid = data.GetU32(&offset);
392  pr_ppid = data.GetU32(&offset);
393  pr_pgrp = data.GetU32(&offset);
394  pr_sid = data.GetU32(&offset);
395
396  size = 16;
397  data.ExtractBytes(offset, size, byteorder, pr_fname);
398  offset += size;
399
400  size = 80;
401  data.ExtractBytes(offset, size, byteorder, pr_psargs);
402  offset += size;
403
404  return error;
405}
406
407// Parse SIGINFO from NOTE entry
408ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
409
410size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
411  if (arch.IsMIPS())
412    return sizeof(ELFLinuxSigInfo);
413  switch (arch.GetCore()) {
414  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
415    return sizeof(ELFLinuxSigInfo);
416  case lldb_private::ArchSpec::eCore_s390x_generic:
417  case lldb_private::ArchSpec::eCore_x86_32_i386:
418  case lldb_private::ArchSpec::eCore_x86_32_i486:
419    return 12;
420  default:
421    return 0;
422  }
423}
424
425Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
426  Status error;
427  if (GetSize(arch) > data.GetByteSize()) {
428    error.SetErrorStringWithFormat(
429        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
430        GetSize(arch), data.GetByteSize());
431    return error;
432  }
433
434  // Parsing from a 32 bit ELF core file, and populating/reusing the structure
435  // properly, because the struct is for the 64 bit version
436  offset_t offset = 0;
437  si_signo = data.GetU32(&offset);
438  si_code = data.GetU32(&offset);
439  si_errno = data.GetU32(&offset);
440
441  return error;
442}
443