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