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