ThreadElfCore.cpp revision 314564
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/Core/DataExtractor.h"
11#include "lldb/Core/Log.h"
12#include "lldb/Target/RegisterContext.h"
13#include "lldb/Target/StopInfo.h"
14#include "lldb/Target/Target.h"
15#include "lldb/Target/Unwind.h"
16
17#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
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_arm.h"
23#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
24//#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
25#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
26#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
27#include "ProcessElfCore.h"
28#include "RegisterContextPOSIXCore_arm.h"
29#include "RegisterContextPOSIXCore_arm64.h"
30#include "RegisterContextPOSIXCore_mips64.h"
31#include "RegisterContextPOSIXCore_powerpc.h"
32//#include "RegisterContextPOSIXCore_s390x.h"
33#include "RegisterContextPOSIXCore_x86_64.h"
34#include "ThreadElfCore.h"
35
36using namespace lldb;
37using namespace lldb_private;
38
39//----------------------------------------------------------------------
40// Construct a Thread object with given data
41//----------------------------------------------------------------------
42ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
43    : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
44      m_signo(td.signo), m_gpregset_data(td.gpregset),
45      m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {}
46
47ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
48
49void ThreadElfCore::RefreshStateAfterStop() {
50  GetRegisterContext()->InvalidateIfNeeded(false);
51}
52
53void ThreadElfCore::ClearStackFrames() {
54  Unwind *unwinder = GetUnwinder();
55  if (unwinder)
56    unwinder->Clear();
57  Thread::ClearStackFrames();
58}
59
60RegisterContextSP ThreadElfCore::GetRegisterContext() {
61  if (m_reg_context_sp.get() == NULL) {
62    m_reg_context_sp = CreateRegisterContextForFrame(NULL);
63  }
64  return m_reg_context_sp;
65}
66
67RegisterContextSP
68ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
69  RegisterContextSP reg_ctx_sp;
70  uint32_t concrete_frame_idx = 0;
71  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
72
73  if (frame)
74    concrete_frame_idx = frame->GetConcreteFrameIndex();
75
76  if (concrete_frame_idx == 0) {
77    if (m_thread_reg_ctx_sp)
78      return m_thread_reg_ctx_sp;
79
80    ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
81    ArchSpec arch = process->GetArchitecture();
82    RegisterInfoInterface *reg_interface = NULL;
83
84    switch (arch.GetTriple().getOS()) {
85    case llvm::Triple::FreeBSD: {
86      switch (arch.GetMachine()) {
87      case llvm::Triple::aarch64:
88        reg_interface = new RegisterInfoPOSIX_arm64(arch);
89        break;
90      case llvm::Triple::arm:
91        reg_interface = new RegisterContextFreeBSD_arm(arch);
92        break;
93      case llvm::Triple::ppc:
94        reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
95        break;
96      case llvm::Triple::ppc64:
97        reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
98        break;
99      case llvm::Triple::mips64:
100        reg_interface = new RegisterContextFreeBSD_mips64(arch);
101        break;
102      case llvm::Triple::x86:
103        reg_interface = new RegisterContextFreeBSD_i386(arch);
104        break;
105      case llvm::Triple::x86_64:
106        reg_interface = new RegisterContextFreeBSD_x86_64(arch);
107        break;
108      default:
109        break;
110      }
111      break;
112    }
113
114    case llvm::Triple::Linux: {
115      switch (arch.GetMachine()) {
116      case llvm::Triple::arm:
117        reg_interface = new RegisterContextLinux_arm(arch);
118        break;
119      case llvm::Triple::aarch64:
120        reg_interface = new RegisterInfoPOSIX_arm64(arch);
121        break;
122//    case llvm::Triple::systemz:
123//      reg_interface = new RegisterContextLinux_s390x(arch);
124//      break;
125      case llvm::Triple::x86:
126        reg_interface = new RegisterContextLinux_i386(arch);
127        break;
128      case llvm::Triple::x86_64:
129        reg_interface = new RegisterContextLinux_x86_64(arch);
130        break;
131      default:
132        break;
133      }
134      break;
135    }
136
137    default:
138      break;
139    }
140
141    if (!reg_interface) {
142      if (log)
143        log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
144                    __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
145      assert(false && "Architecture or OS not supported");
146    }
147
148    switch (arch.GetMachine()) {
149    case llvm::Triple::aarch64:
150      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64(
151          *this, reg_interface, m_gpregset_data, m_fpregset_data));
152      break;
153    case llvm::Triple::arm:
154      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm(
155          *this, reg_interface, m_gpregset_data, m_fpregset_data));
156      break;
157    case llvm::Triple::mips64:
158      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64(
159          *this, reg_interface, m_gpregset_data, m_fpregset_data));
160      break;
161    case llvm::Triple::ppc:
162    case llvm::Triple::ppc64:
163      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc(
164          *this, reg_interface, m_gpregset_data, m_fpregset_data,
165          m_vregset_data));
166      break;
167//  case llvm::Triple::systemz:
168//    m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x(
169//        *this, reg_interface, m_gpregset_data, m_fpregset_data));
170//    break;
171    case llvm::Triple::x86:
172    case llvm::Triple::x86_64:
173      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
174          *this, reg_interface, m_gpregset_data, m_fpregset_data));
175      break;
176    default:
177      break;
178    }
179
180    reg_ctx_sp = m_thread_reg_ctx_sp;
181  } else if (m_unwinder_ap.get()) {
182    reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
183  }
184  return reg_ctx_sp;
185}
186
187bool ThreadElfCore::CalculateStopInfo() {
188  ProcessSP process_sp(GetProcess());
189  if (process_sp) {
190    SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
191    return true;
192  }
193  return false;
194}
195
196//----------------------------------------------------------------
197// Parse PRSTATUS from NOTE entry
198//----------------------------------------------------------------
199ELFLinuxPrStatus::ELFLinuxPrStatus() {
200  memset(this, 0, sizeof(ELFLinuxPrStatus));
201}
202
203Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
204  Error error;
205  if (GetSize(arch) > data.GetByteSize()) {
206    error.SetErrorStringWithFormat(
207        "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
208        GetSize(arch), data.GetByteSize());
209    return error;
210  }
211
212  // Read field by field to correctly account for endianess
213  // of both the core dump and the platform running lldb.
214  offset_t offset = 0;
215  si_signo = data.GetU32(&offset);
216  si_code = data.GetU32(&offset);
217  si_errno = data.GetU32(&offset);
218
219  pr_cursig = data.GetU16(&offset);
220  offset += 2; // pad
221
222  pr_sigpend = data.GetPointer(&offset);
223  pr_sighold = data.GetPointer(&offset);
224
225  pr_pid = data.GetU32(&offset);
226  pr_ppid = data.GetU32(&offset);
227  pr_pgrp = data.GetU32(&offset);
228  pr_sid = data.GetU32(&offset);
229
230  pr_utime.tv_sec = data.GetPointer(&offset);
231  pr_utime.tv_usec = data.GetPointer(&offset);
232
233  pr_stime.tv_sec = data.GetPointer(&offset);
234  pr_stime.tv_usec = data.GetPointer(&offset);
235
236  pr_cutime.tv_sec = data.GetPointer(&offset);
237  pr_cutime.tv_usec = data.GetPointer(&offset);
238
239  pr_cstime.tv_sec = data.GetPointer(&offset);
240  pr_cstime.tv_usec = data.GetPointer(&offset);
241
242
243  return error;
244}
245
246//----------------------------------------------------------------
247// Parse PRPSINFO from NOTE entry
248//----------------------------------------------------------------
249ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
250  memset(this, 0, sizeof(ELFLinuxPrPsInfo));
251}
252
253Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
254  Error error;
255  ByteOrder byteorder = data.GetByteOrder();
256  if (GetSize(arch) > data.GetByteSize()) {
257    error.SetErrorStringWithFormat(
258        "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
259        GetSize(arch), data.GetByteSize());
260    return error;
261  }
262  size_t size = 0;
263  offset_t offset = 0;
264
265  pr_state = data.GetU8(&offset);
266  pr_sname = data.GetU8(&offset);
267  pr_zomb = data.GetU8(&offset);
268  pr_nice = data.GetU8(&offset);
269  if (data.GetAddressByteSize() == 8) {
270    // Word align the next field on 64 bit.
271    offset += 4;
272  }
273
274  pr_flag = data.GetPointer(&offset);
275
276  // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
277  pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
278  pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
279
280  pr_pid = data.GetU32(&offset);
281  pr_ppid = data.GetU32(&offset);
282  pr_pgrp = data.GetU32(&offset);
283  pr_sid = data.GetU32(&offset);
284
285  size = 16;
286  data.ExtractBytes(offset, size, byteorder, pr_fname);
287  offset += size;
288
289  size = 80;
290  data.ExtractBytes(offset, size, byteorder, pr_psargs);
291  offset += size;
292
293  return error;
294}
295
296//----------------------------------------------------------------
297// Parse SIGINFO from NOTE entry
298//----------------------------------------------------------------
299ELFLinuxSigInfo::ELFLinuxSigInfo() {
300  memset(this, 0, sizeof(ELFLinuxSigInfo));
301}
302
303Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
304  Error error;
305  if (GetSize(arch) > data.GetByteSize()) {
306    error.SetErrorStringWithFormat(
307        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
308        GetSize(arch), data.GetByteSize());
309    return error;
310  }
311
312  // Parsing from a 32 bit ELF core file, and populating/reusing the structure
313  // properly, because the struct is for the 64 bit version
314  offset_t offset = 0;
315  si_signo = data.GetU32(&offset);
316  si_code = data.GetU32(&offset);
317  si_errno = data.GetU32(&offset);
318
319  return error;
320}
321