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 "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
18 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
19 #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
20 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
21 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
22 #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
23 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
24 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
25 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
26 #include "ProcessElfCore.h"
27 #include "RegisterContextPOSIXCore_arm.h"
28 #include "RegisterContextPOSIXCore_arm64.h"
29 #include "RegisterContextPOSIXCore_mips64.h"
30 #include "RegisterContextPOSIXCore_powerpc.h"
31 #include "RegisterContextPOSIXCore_s390x.h"
32 #include "RegisterContextPOSIXCore_x86_64.h"
33 #include "ThreadElfCore.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 //----------------------------------------------------------------------
39 // Construct a Thread object with given data
40 //----------------------------------------------------------------------
41 ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
42     : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
43       m_signo(td.signo), m_gpregset_data(td.gpregset),
44       m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {}
45 
46 ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
47 
48 void ThreadElfCore::RefreshStateAfterStop() {
49   GetRegisterContext()->InvalidateIfNeeded(false);
50 }
51 
52 void ThreadElfCore::ClearStackFrames() {
53   Unwind *unwinder = GetUnwinder();
54   if (unwinder)
55     unwinder->Clear();
56   Thread::ClearStackFrames();
57 }
58 
59 RegisterContextSP ThreadElfCore::GetRegisterContext() {
60   if (m_reg_context_sp.get() == NULL) {
61     m_reg_context_sp = CreateRegisterContextForFrame(NULL);
62   }
63   return m_reg_context_sp;
64 }
65 
66 RegisterContextSP
67 ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
68   RegisterContextSP reg_ctx_sp;
69   uint32_t concrete_frame_idx = 0;
70   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
71 
72   if (frame)
73     concrete_frame_idx = frame->GetConcreteFrameIndex();
74 
75   if (concrete_frame_idx == 0) {
76     if (m_thread_reg_ctx_sp)
77       return m_thread_reg_ctx_sp;
78 
79     ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
80     ArchSpec arch = process->GetArchitecture();
81     RegisterInfoInterface *reg_interface = NULL;
82 
83     switch (arch.GetTriple().getOS()) {
84     case llvm::Triple::FreeBSD: {
85       switch (arch.GetMachine()) {
86       case llvm::Triple::aarch64:
87         reg_interface = new RegisterInfoPOSIX_arm64(arch);
88         break;
89       case llvm::Triple::arm:
90         reg_interface = new RegisterInfoPOSIX_arm(arch);
91         break;
92       case llvm::Triple::ppc:
93         reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
94         break;
95       case llvm::Triple::ppc64:
96         reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
97         break;
98       case llvm::Triple::mips64:
99         reg_interface = new RegisterContextFreeBSD_mips64(arch);
100         break;
101       case llvm::Triple::x86:
102         reg_interface = new RegisterContextFreeBSD_i386(arch);
103         break;
104       case llvm::Triple::x86_64:
105         reg_interface = new RegisterContextFreeBSD_x86_64(arch);
106         break;
107       default:
108         break;
109       }
110       break;
111     }
112 
113     case llvm::Triple::Linux: {
114       switch (arch.GetMachine()) {
115       case llvm::Triple::arm:
116         reg_interface = new RegisterInfoPOSIX_arm(arch);
117         break;
118       case llvm::Triple::aarch64:
119         reg_interface = new RegisterInfoPOSIX_arm64(arch);
120         break;
121       case llvm::Triple::systemz:
122         reg_interface = new RegisterContextLinux_s390x(arch);
123         break;
124       case llvm::Triple::x86:
125         reg_interface = new RegisterContextLinux_i386(arch);
126         break;
127       case llvm::Triple::x86_64:
128         reg_interface = new RegisterContextLinux_x86_64(arch);
129         break;
130       default:
131         break;
132       }
133       break;
134     }
135 
136     default:
137       break;
138     }
139 
140     if (!reg_interface) {
141       if (log)
142         log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
143                     __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
144       assert(false && "Architecture or OS not supported");
145     }
146 
147     switch (arch.GetMachine()) {
148     case llvm::Triple::aarch64:
149       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64(
150           *this, reg_interface, m_gpregset_data, m_fpregset_data));
151       break;
152     case llvm::Triple::arm:
153       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm(
154           *this, reg_interface, m_gpregset_data, m_fpregset_data));
155       break;
156     case llvm::Triple::mips64:
157       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64(
158           *this, reg_interface, m_gpregset_data, m_fpregset_data));
159       break;
160     case llvm::Triple::ppc:
161     case llvm::Triple::ppc64:
162       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc(
163           *this, reg_interface, m_gpregset_data, m_fpregset_data,
164           m_vregset_data));
165       break;
166     case llvm::Triple::systemz:
167       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x(
168           *this, reg_interface, m_gpregset_data, m_fpregset_data));
169       break;
170     case llvm::Triple::x86:
171     case llvm::Triple::x86_64:
172       m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
173           *this, reg_interface, m_gpregset_data, m_fpregset_data));
174       break;
175     default:
176       break;
177     }
178 
179     reg_ctx_sp = m_thread_reg_ctx_sp;
180   } else if (m_unwinder_ap.get()) {
181     reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
182   }
183   return reg_ctx_sp;
184 }
185 
186 bool ThreadElfCore::CalculateStopInfo() {
187   ProcessSP process_sp(GetProcess());
188   if (process_sp) {
189     SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
190     return true;
191   }
192   return false;
193 }
194 
195 //----------------------------------------------------------------
196 // Parse PRSTATUS from NOTE entry
197 //----------------------------------------------------------------
198 ELFLinuxPrStatus::ELFLinuxPrStatus() {
199   memset(this, 0, sizeof(ELFLinuxPrStatus));
200 }
201 
202 Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
203   Error error;
204   if (GetSize(arch) > data.GetByteSize()) {
205     error.SetErrorStringWithFormat(
206         "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
207         GetSize(arch), data.GetByteSize());
208     return error;
209   }
210 
211   // Read field by field to correctly account for endianess
212   // of both the core dump and the platform running lldb.
213   offset_t offset = 0;
214   si_signo = data.GetU32(&offset);
215   si_code = data.GetU32(&offset);
216   si_errno = data.GetU32(&offset);
217 
218   pr_cursig = data.GetU16(&offset);
219   offset += 2; // pad
220 
221   pr_sigpend = data.GetPointer(&offset);
222   pr_sighold = data.GetPointer(&offset);
223 
224   pr_pid = data.GetU32(&offset);
225   pr_ppid = data.GetU32(&offset);
226   pr_pgrp = data.GetU32(&offset);
227   pr_sid = data.GetU32(&offset);
228 
229   pr_utime.tv_sec = data.GetPointer(&offset);
230   pr_utime.tv_usec = data.GetPointer(&offset);
231 
232   pr_stime.tv_sec = data.GetPointer(&offset);
233   pr_stime.tv_usec = data.GetPointer(&offset);
234 
235   pr_cutime.tv_sec = data.GetPointer(&offset);
236   pr_cutime.tv_usec = data.GetPointer(&offset);
237 
238   pr_cstime.tv_sec = data.GetPointer(&offset);
239   pr_cstime.tv_usec = data.GetPointer(&offset);
240 
241 
242   return error;
243 }
244 
245 //----------------------------------------------------------------
246 // Parse PRPSINFO from NOTE entry
247 //----------------------------------------------------------------
248 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
249   memset(this, 0, sizeof(ELFLinuxPrPsInfo));
250 }
251 
252 Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
253   Error error;
254   ByteOrder byteorder = data.GetByteOrder();
255   if (GetSize(arch) > data.GetByteSize()) {
256     error.SetErrorStringWithFormat(
257         "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
258         GetSize(arch), data.GetByteSize());
259     return error;
260   }
261   size_t size = 0;
262   offset_t offset = 0;
263 
264   pr_state = data.GetU8(&offset);
265   pr_sname = data.GetU8(&offset);
266   pr_zomb = data.GetU8(&offset);
267   pr_nice = data.GetU8(&offset);
268   if (data.GetAddressByteSize() == 8) {
269     // Word align the next field on 64 bit.
270     offset += 4;
271   }
272 
273   pr_flag = data.GetPointer(&offset);
274 
275   // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
276   pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
277   pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
278 
279   pr_pid = data.GetU32(&offset);
280   pr_ppid = data.GetU32(&offset);
281   pr_pgrp = data.GetU32(&offset);
282   pr_sid = data.GetU32(&offset);
283 
284   size = 16;
285   data.ExtractBytes(offset, size, byteorder, pr_fname);
286   offset += size;
287 
288   size = 80;
289   data.ExtractBytes(offset, size, byteorder, pr_psargs);
290   offset += size;
291 
292   return error;
293 }
294 
295 //----------------------------------------------------------------
296 // Parse SIGINFO from NOTE entry
297 //----------------------------------------------------------------
298 ELFLinuxSigInfo::ELFLinuxSigInfo() {
299   memset(this, 0, sizeof(ELFLinuxSigInfo));
300 }
301 
302 Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
303   Error error;
304   if (GetSize(arch) > data.GetByteSize()) {
305     error.SetErrorStringWithFormat(
306         "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
307         GetSize(arch), data.GetByteSize());
308     return error;
309   }
310 
311   // Parsing from a 32 bit ELF core file, and populating/reusing the structure
312   // properly, because the struct is for the 64 bit version
313   offset_t offset = 0;
314   si_signo = data.GetU32(&offset);
315   si_code = data.GetU32(&offset);
316   si_errno = data.GetU32(&offset);
317 
318   return error;
319 }
320