1 //===-- ThreadMinidump.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 // Project includes
11 #include "ThreadMinidump.h"
12 #include "ProcessMinidump.h"
13 
14 #include "RegisterContextMinidump_ARM.h"
15 #include "RegisterContextMinidump_ARM64.h"
16 #include "RegisterContextMinidump_x86_32.h"
17 #include "RegisterContextMinidump_x86_64.h"
18 
19 // Other libraries and framework includes
20 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
21 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
22 #include "Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h"
23 #include "Plugins/Process/elf-core/RegisterUtilities.h"
24 
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StopInfo.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Unwind.h"
29 #include "lldb/Utility/DataExtractor.h"
30 #include "lldb/Utility/Log.h"
31 
32 // C Includes
33 // C++ Includes
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 using namespace minidump;
38 
39 ThreadMinidump::ThreadMinidump(Process &process, const MinidumpThread &td,
40                                llvm::ArrayRef<uint8_t> gpregset_data)
41     : Thread(process, td.thread_id), m_thread_reg_ctx_sp(),
42       m_gpregset_data(gpregset_data) {}
43 
44 ThreadMinidump::~ThreadMinidump() {}
45 
46 void ThreadMinidump::RefreshStateAfterStop() {}
47 
48 RegisterContextSP ThreadMinidump::GetRegisterContext() {
49   if (!m_reg_context_sp) {
50     m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
51   }
52   return m_reg_context_sp;
53 }
54 
55 RegisterContextSP
56 ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) {
57   RegisterContextSP reg_ctx_sp;
58   uint32_t concrete_frame_idx = 0;
59 
60   if (frame)
61     concrete_frame_idx = frame->GetConcreteFrameIndex();
62 
63   if (concrete_frame_idx == 0) {
64     if (m_thread_reg_ctx_sp)
65       return m_thread_reg_ctx_sp;
66 
67     ProcessMinidump *process =
68         static_cast<ProcessMinidump *>(GetProcess().get());
69     ArchSpec arch = process->GetArchitecture();
70     RegisterInfoInterface *reg_interface = nullptr;
71 
72     // TODO write other register contexts and add them here
73     switch (arch.GetMachine()) {
74     case llvm::Triple::x86: {
75       reg_interface = new RegisterContextLinux_i386(arch);
76       lldb::DataBufferSP buf =
77           ConvertMinidumpContext_x86_32(m_gpregset_data, reg_interface);
78       DataExtractor gpregset(buf, lldb::eByteOrderLittle, 4);
79       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
80           *this, reg_interface, gpregset, {}));
81       break;
82     }
83     case llvm::Triple::x86_64: {
84       reg_interface = new RegisterContextLinux_x86_64(arch);
85       lldb::DataBufferSP buf =
86           ConvertMinidumpContext_x86_64(m_gpregset_data, reg_interface);
87       DataExtractor gpregset(buf, lldb::eByteOrderLittle, 8);
88       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
89           *this, reg_interface, gpregset, {}));
90       break;
91     }
92     case llvm::Triple::aarch64: {
93       DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
94                          lldb::eByteOrderLittle, 8);
95       m_thread_reg_ctx_sp.reset(new RegisterContextMinidump_ARM64(*this, data));
96       break;
97     }
98     case llvm::Triple::arm: {
99       DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
100                          lldb::eByteOrderLittle, 8);
101       const bool apple = arch.GetTriple().getVendor() == llvm::Triple::Apple;
102       m_thread_reg_ctx_sp.reset(
103           new RegisterContextMinidump_ARM(*this, data, apple));
104       break;
105     }
106     default:
107       break;
108     }
109 
110     reg_ctx_sp = m_thread_reg_ctx_sp;
111   } else if (m_unwinder_ap) {
112     reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
113   }
114 
115   return reg_ctx_sp;
116 }
117 
118 bool ThreadMinidump::CalculateStopInfo() { return false; }
119