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