1 //===-- ThreadElfCore.cpp -------------------------------------------------===//
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       case llvm::Triple::arm:
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::aarch64:
115         break;
116       case llvm::Triple::x86_64:
117         reg_interface = new RegisterContextNetBSD_x86_64(arch);
118         break;
119       default:
120         break;
121       }
122       break;
123     }
124 
125     case llvm::Triple::Linux: {
126       switch (arch.GetMachine()) {
127       case llvm::Triple::aarch64:
128         break;
129       case llvm::Triple::mipsel:
130       case llvm::Triple::mips:
131         reg_interface = new RegisterContextLinux_mips(arch);
132         break;
133       case llvm::Triple::mips64el:
134       case llvm::Triple::mips64:
135         reg_interface = new RegisterContextLinux_mips64(arch);
136         break;
137       case llvm::Triple::ppc64le:
138         reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
139         break;
140 #ifdef LLDB_ENABLE_ALL
141       case llvm::Triple::systemz:
142         reg_interface = new RegisterContextLinux_s390x(arch);
143         break;
144 #endif // LLDB_ENABLE_ALL
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         break;
161       case llvm::Triple::x86:
162         reg_interface = new RegisterContextOpenBSD_i386(arch);
163         break;
164       case llvm::Triple::x86_64:
165         reg_interface = new RegisterContextOpenBSD_x86_64(arch);
166         break;
167       default:
168         break;
169       }
170       break;
171     }
172 
173     default:
174       break;
175     }
176 
177     if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
178         arch.GetMachine() != llvm::Triple::arm) {
179       LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
180                 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
181       assert(false && "Architecture or OS not supported");
182     }
183 
184     switch (arch.GetMachine()) {
185     case llvm::Triple::aarch64:
186       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
187           *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch),
188           m_gpregset_data, m_notes);
189       break;
190     case llvm::Triple::arm:
191       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
192           *this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
193           m_notes);
194       break;
195     case llvm::Triple::mipsel:
196     case llvm::Triple::mips:
197       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
198           *this, reg_interface, m_gpregset_data, m_notes);
199       break;
200     case llvm::Triple::mips64:
201     case llvm::Triple::mips64el:
202       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
203           *this, reg_interface, m_gpregset_data, m_notes);
204       break;
205     case llvm::Triple::ppc:
206     case llvm::Triple::ppc64:
207       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
208           *this, reg_interface, m_gpregset_data, m_notes);
209       break;
210     case llvm::Triple::ppc64le:
211       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
212           *this, reg_interface, m_gpregset_data, m_notes);
213       break;
214 #ifdef LLDB_ENABLE_ALL
215     case llvm::Triple::systemz:
216       m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
217           *this, reg_interface, m_gpregset_data, m_notes);
218       break;
219 #endif // LLDB_ENABLE_ALL
220     case llvm::Triple::x86:
221     case llvm::Triple::x86_64:
222       m_thread_reg_ctx_sp = std::make_shared<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     reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
232   }
233   return reg_ctx_sp;
234 }
235 
236 bool ThreadElfCore::CalculateStopInfo() {
237   ProcessSP process_sp(GetProcess());
238   if (process_sp) {
239     SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
240     return true;
241   }
242   return false;
243 }
244 
245 // Parse PRSTATUS from NOTE entry
246 ELFLinuxPrStatus::ELFLinuxPrStatus() {
247   memset(this, 0, sizeof(ELFLinuxPrStatus));
248 }
249 
250 size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
251   constexpr size_t mips_linux_pr_status_size_o32 = 96;
252   constexpr size_t mips_linux_pr_status_size_n32 = 72;
253   constexpr size_t num_ptr_size_members = 10;
254   if (arch.IsMIPS()) {
255     std::string abi = arch.GetTargetABI();
256     assert(!abi.empty() && "ABI is not set");
257     if (!abi.compare("n64"))
258       return sizeof(ELFLinuxPrStatus);
259     else if (!abi.compare("o32"))
260       return mips_linux_pr_status_size_o32;
261     // N32 ABI
262     return mips_linux_pr_status_size_n32;
263   }
264   switch (arch.GetCore()) {
265   case lldb_private::ArchSpec::eCore_x86_32_i386:
266   case lldb_private::ArchSpec::eCore_x86_32_i486:
267     return 72;
268   default:
269     if (arch.GetAddressByteSize() == 8)
270       return sizeof(ELFLinuxPrStatus);
271     else
272       return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
273   }
274 }
275 
276 Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
277                                const ArchSpec &arch) {
278   Status error;
279   if (GetSize(arch) > data.GetByteSize()) {
280     error.SetErrorStringWithFormat(
281         "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
282         GetSize(arch), data.GetByteSize());
283     return error;
284   }
285 
286   // Read field by field to correctly account for endianess of both the core
287   // dump and the platform running lldb.
288   offset_t offset = 0;
289   si_signo = data.GetU32(&offset);
290   si_code = data.GetU32(&offset);
291   si_errno = data.GetU32(&offset);
292 
293   pr_cursig = data.GetU16(&offset);
294   offset += 2; // pad
295 
296   pr_sigpend = data.GetAddress(&offset);
297   pr_sighold = data.GetAddress(&offset);
298 
299   pr_pid = data.GetU32(&offset);
300   pr_ppid = data.GetU32(&offset);
301   pr_pgrp = data.GetU32(&offset);
302   pr_sid = data.GetU32(&offset);
303 
304   pr_utime.tv_sec = data.GetAddress(&offset);
305   pr_utime.tv_usec = data.GetAddress(&offset);
306 
307   pr_stime.tv_sec = data.GetAddress(&offset);
308   pr_stime.tv_usec = data.GetAddress(&offset);
309 
310   pr_cutime.tv_sec = data.GetAddress(&offset);
311   pr_cutime.tv_usec = data.GetAddress(&offset);
312 
313   pr_cstime.tv_sec = data.GetAddress(&offset);
314   pr_cstime.tv_usec = data.GetAddress(&offset);
315 
316   return error;
317 }
318 
319 // Parse PRPSINFO from NOTE entry
320 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
321   memset(this, 0, sizeof(ELFLinuxPrPsInfo));
322 }
323 
324 size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
325   constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
326   if (arch.IsMIPS()) {
327     uint8_t address_byte_size = arch.GetAddressByteSize();
328     if (address_byte_size == 8)
329       return sizeof(ELFLinuxPrPsInfo);
330     return mips_linux_pr_psinfo_size_o32_n32;
331   }
332 
333   switch (arch.GetCore()) {
334   case lldb_private::ArchSpec::eCore_s390x_generic:
335   case lldb_private::ArchSpec::eCore_x86_64_x86_64:
336     return sizeof(ELFLinuxPrPsInfo);
337   case lldb_private::ArchSpec::eCore_x86_32_i386:
338   case lldb_private::ArchSpec::eCore_x86_32_i486:
339     return 124;
340   default:
341     return 0;
342   }
343 }
344 
345 Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
346                                const ArchSpec &arch) {
347   Status error;
348   ByteOrder byteorder = data.GetByteOrder();
349   if (GetSize(arch) > data.GetByteSize()) {
350     error.SetErrorStringWithFormat(
351         "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
352         GetSize(arch), data.GetByteSize());
353     return error;
354   }
355   size_t size = 0;
356   offset_t offset = 0;
357 
358   pr_state = data.GetU8(&offset);
359   pr_sname = data.GetU8(&offset);
360   pr_zomb = data.GetU8(&offset);
361   pr_nice = data.GetU8(&offset);
362   if (data.GetAddressByteSize() == 8) {
363     // Word align the next field on 64 bit.
364     offset += 4;
365   }
366 
367   pr_flag = data.GetAddress(&offset);
368 
369   if (arch.IsMIPS()) {
370     // The pr_uid and pr_gid is always 32 bit irrespective of platforms
371     pr_uid = data.GetU32(&offset);
372     pr_gid = data.GetU32(&offset);
373   } else {
374     // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
375     pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
376     pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
377   }
378 
379   pr_pid = data.GetU32(&offset);
380   pr_ppid = data.GetU32(&offset);
381   pr_pgrp = data.GetU32(&offset);
382   pr_sid = data.GetU32(&offset);
383 
384   size = 16;
385   data.ExtractBytes(offset, size, byteorder, pr_fname);
386   offset += size;
387 
388   size = 80;
389   data.ExtractBytes(offset, size, byteorder, pr_psargs);
390   offset += size;
391 
392   return error;
393 }
394 
395 // Parse SIGINFO from NOTE entry
396 ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
397 
398 size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
399   if (arch.IsMIPS())
400     return sizeof(ELFLinuxSigInfo);
401   switch (arch.GetCore()) {
402   case lldb_private::ArchSpec::eCore_x86_64_x86_64:
403     return sizeof(ELFLinuxSigInfo);
404   case lldb_private::ArchSpec::eCore_s390x_generic:
405   case lldb_private::ArchSpec::eCore_x86_32_i386:
406   case lldb_private::ArchSpec::eCore_x86_32_i486:
407     return 12;
408   default:
409     return 0;
410   }
411 }
412 
413 Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
414   Status error;
415   if (GetSize(arch) > data.GetByteSize()) {
416     error.SetErrorStringWithFormat(
417         "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
418         GetSize(arch), data.GetByteSize());
419     return error;
420   }
421 
422   // Parsing from a 32 bit ELF core file, and populating/reusing the structure
423   // properly, because the struct is for the 64 bit version
424   offset_t offset = 0;
425   si_signo = data.GetU32(&offset);
426   si_code = data.GetU32(&offset);
427   si_errno = data.GetU32(&offset);
428 
429   return error;
430 }
431