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