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