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 "ThreadElfCore.h"
18 #include "ProcessElfCore.h"
19 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
20 #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
21 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
22 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
23 #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
24 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
25 #include "RegisterContextPOSIXCore_arm64.h"
26 #include "RegisterContextPOSIXCore_mips64.h"
27 #include "RegisterContextPOSIXCore_powerpc.h"
28 #include "RegisterContextPOSIXCore_x86_64.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //----------------------------------------------------------------------
34 // Construct a Thread object with given data
35 //----------------------------------------------------------------------
36 ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
37                               const ThreadData &td) :
38     Thread(process, tid),
39     m_thread_name(td.name),
40     m_thread_reg_ctx_sp (),
41     m_signo(td.signo),
42     m_gpregset_data(td.gpregset),
43     m_fpregset_data(td.fpregset),
44     m_vregset_data(td.vregset)
45 {
46 }
47 
48 ThreadElfCore::~ThreadElfCore ()
49 {
50     DestroyThread();
51 }
52 
53 void
54 ThreadElfCore::RefreshStateAfterStop()
55 {
56     GetRegisterContext()->InvalidateIfNeeded (false);
57 }
58 
59 void
60 ThreadElfCore::ClearStackFrames ()
61 {
62     Unwind *unwinder = GetUnwinder ();
63     if (unwinder)
64         unwinder->Clear();
65     Thread::ClearStackFrames();
66 }
67 
68 RegisterContextSP
69 ThreadElfCore::GetRegisterContext ()
70 {
71     if (m_reg_context_sp.get() == NULL) {
72         m_reg_context_sp = CreateRegisterContextForFrame (NULL);
73     }
74     return m_reg_context_sp;
75 }
76 
77 RegisterContextSP
78 ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
79 {
80     RegisterContextSP reg_ctx_sp;
81     uint32_t concrete_frame_idx = 0;
82     Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
83 
84     if (frame)
85         concrete_frame_idx = frame->GetConcreteFrameIndex ();
86 
87     if (concrete_frame_idx == 0)
88     {
89         if (m_thread_reg_ctx_sp)
90             return m_thread_reg_ctx_sp;
91 
92         ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
93         ArchSpec arch = process->GetArchitecture();
94         RegisterInfoInterface *reg_interface = NULL;
95 
96         switch (arch.GetTriple().getOS())
97         {
98             case llvm::Triple::FreeBSD:
99             {
100                 switch (arch.GetMachine())
101                 {
102                     case llvm::Triple::aarch64:
103                         reg_interface = new RegisterContextFreeBSD_arm64(arch);
104                         break;
105                     case llvm::Triple::ppc:
106                         reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
107                         break;
108                     case llvm::Triple::ppc64:
109                         reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
110                         break;
111                     case llvm::Triple::mips64:
112                         reg_interface = new RegisterContextFreeBSD_mips64(arch);
113                         break;
114                     case llvm::Triple::x86:
115                         reg_interface = new RegisterContextFreeBSD_i386(arch);
116                         break;
117                     case llvm::Triple::x86_64:
118                         reg_interface = new RegisterContextFreeBSD_x86_64(arch);
119                         break;
120                     default:
121                         break;
122                 }
123                 break;
124             }
125 
126             case llvm::Triple::Linux:
127             {
128                 switch (arch.GetMachine())
129                 {
130                     case llvm::Triple::x86_64:
131                         reg_interface = new RegisterContextLinux_x86_64(arch);
132                         break;
133                     default:
134                         break;
135                 }
136                 break;
137             }
138 
139             default:
140                 break;
141         }
142 
143         if (!reg_interface) {
144             if (log)
145                 log->Printf ("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
146                              __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
147                 assert (false && "Architecture or OS not supported");
148         }
149 
150         switch (arch.GetMachine())
151         {
152             case llvm::Triple::aarch64:
153                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
154                 break;
155             case llvm::Triple::mips64:
156                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
157                 break;
158             case llvm::Triple::ppc:
159             case llvm::Triple::ppc64:
160                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data));
161                 break;
162             case llvm::Triple::x86:
163             case llvm::Triple::x86_64:
164                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
165                 break;
166             default:
167                 break;
168         }
169 
170         reg_ctx_sp = m_thread_reg_ctx_sp;
171     }
172     else if (m_unwinder_ap.get())
173     {
174         reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
175     }
176     return reg_ctx_sp;
177 }
178 
179 bool
180 ThreadElfCore::CalculateStopInfo ()
181 {
182     ProcessSP process_sp (GetProcess());
183     if (process_sp)
184     {
185         SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo));
186         return true;
187     }
188     return false;
189 }
190 
191 //----------------------------------------------------------------
192 // Parse PRSTATUS from NOTE entry
193 //----------------------------------------------------------------
194 ELFLinuxPrStatus::ELFLinuxPrStatus()
195 {
196     memset(this, 0, sizeof(ELFLinuxPrStatus));
197 }
198 
199 bool
200 ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
201 {
202     ByteOrder byteorder = data.GetByteOrder();
203     size_t len;
204     switch(arch.GetCore())
205     {
206         case ArchSpec::eCore_x86_64_x86_64:
207             len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this);
208             return len == ELFLINUXPRSTATUS64_SIZE;
209         default:
210             return false;
211     }
212 }
213 
214 //----------------------------------------------------------------
215 // Parse PRPSINFO from NOTE entry
216 //----------------------------------------------------------------
217 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo()
218 {
219     memset(this, 0, sizeof(ELFLinuxPrPsInfo));
220 }
221 
222 bool
223 ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
224 {
225     ByteOrder byteorder = data.GetByteOrder();
226     size_t len;
227     switch(arch.GetCore())
228     {
229         case ArchSpec::eCore_x86_64_x86_64:
230             len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
231             return len == ELFLINUXPRPSINFO64_SIZE;
232         default:
233             return false;
234     }
235 }
236 
237