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