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