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