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