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