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