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/LLDBLog.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 #ifdef LLDB_ENABLE_ALL
23 #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
24 #endif // LLDB_ENABLE_ALL
25 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
26 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.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 "RegisterContextLinuxCore_x86_64.h"
35 #include "RegisterContextPOSIXCore_arm.h"
36 #include "RegisterContextPOSIXCore_arm64.h"
37 #include "RegisterContextPOSIXCore_mips64.h"
38 #include "RegisterContextPOSIXCore_powerpc.h"
39 #include "RegisterContextPOSIXCore_ppc64le.h"
40 #include "RegisterContextPOSIXCore_riscv64.h"
41 #ifdef LLDB_ENABLE_ALL
42 #include "RegisterContextPOSIXCore_s390x.h"
43 #endif // LLDB_ENABLE_ALL
44 #include "RegisterContextPOSIXCore_x86_64.h"
45 #include "ThreadElfCore.h"
46
47 #include <memory>
48
49 using namespace lldb;
50 using namespace lldb_private;
51
52 // Construct a Thread object with given data
ThreadElfCore(Process & process,const ThreadData & td)53 ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
54 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
55 m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset),
56 m_notes(td.notes) {}
57
~ThreadElfCore()58 ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
59
RefreshStateAfterStop()60 void ThreadElfCore::RefreshStateAfterStop() {
61 GetRegisterContext()->InvalidateIfNeeded(false);
62 }
63
GetRegisterContext()64 RegisterContextSP ThreadElfCore::GetRegisterContext() {
65 if (!m_reg_context_sp) {
66 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
67 }
68 return m_reg_context_sp;
69 }
70
71 RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)72 ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
73 RegisterContextSP reg_ctx_sp;
74 uint32_t concrete_frame_idx = 0;
75 Log *log = GetLog(LLDBLog::Thread);
76
77 if (frame)
78 concrete_frame_idx = frame->GetConcreteFrameIndex();
79
80 bool is_linux = false;
81 if (concrete_frame_idx == 0) {
82 if (m_thread_reg_ctx_sp)
83 return m_thread_reg_ctx_sp;
84
85 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
86 ArchSpec arch = process->GetArchitecture();
87 RegisterInfoInterface *reg_interface = nullptr;
88
89 switch (arch.GetTriple().getOS()) {
90 case llvm::Triple::FreeBSD: {
91 switch (arch.GetMachine()) {
92 case llvm::Triple::aarch64:
93 case llvm::Triple::arm:
94 break;
95 case llvm::Triple::ppc:
96 reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
97 break;
98 case llvm::Triple::ppc64:
99 reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
100 break;
101 case llvm::Triple::mips64:
102 reg_interface = new RegisterContextFreeBSD_mips64(arch);
103 break;
104 case llvm::Triple::x86:
105 reg_interface = new RegisterContextFreeBSD_i386(arch);
106 break;
107 case llvm::Triple::x86_64:
108 reg_interface = new RegisterContextFreeBSD_x86_64(arch);
109 break;
110 default:
111 break;
112 }
113 break;
114 }
115
116 case llvm::Triple::NetBSD: {
117 switch (arch.GetMachine()) {
118 case llvm::Triple::aarch64:
119 break;
120 case llvm::Triple::x86:
121 reg_interface = new RegisterContextNetBSD_i386(arch);
122 break;
123 case llvm::Triple::x86_64:
124 reg_interface = new RegisterContextNetBSD_x86_64(arch);
125 break;
126 default:
127 break;
128 }
129 break;
130 }
131
132 case llvm::Triple::Linux: {
133 is_linux = true;
134 switch (arch.GetMachine()) {
135 case llvm::Triple::aarch64:
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 arch.GetMachine() != llvm::Triple::riscv64) {
180 LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
181 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
182 assert(false && "Architecture or OS not supported");
183 }
184
185 switch (arch.GetMachine()) {
186 case llvm::Triple::aarch64:
187 m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create(
188 *this, arch, 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::riscv64:
196 m_thread_reg_ctx_sp = RegisterContextCorePOSIX_riscv64::Create(
197 *this, arch, m_gpregset_data, m_notes);
198 break;
199 case llvm::Triple::mipsel:
200 case llvm::Triple::mips:
201 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
202 *this, reg_interface, m_gpregset_data, m_notes);
203 break;
204 case llvm::Triple::mips64:
205 case llvm::Triple::mips64el:
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::ppc:
210 case llvm::Triple::ppc64:
211 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
212 *this, reg_interface, m_gpregset_data, m_notes);
213 break;
214 case llvm::Triple::ppc64le:
215 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
216 *this, reg_interface, m_gpregset_data, m_notes);
217 break;
218 #ifdef LLDB_ENABLE_ALL
219 case llvm::Triple::systemz:
220 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
221 *this, reg_interface, m_gpregset_data, m_notes);
222 break;
223 #endif // LLDB_ENABLE_ALL
224 case llvm::Triple::x86:
225 case llvm::Triple::x86_64:
226 if (is_linux) {
227 m_thread_reg_ctx_sp = std::make_shared<RegisterContextLinuxCore_x86_64>(
228 *this, reg_interface, m_gpregset_data, m_notes);
229 } else {
230 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
231 *this, reg_interface, m_gpregset_data, m_notes);
232 }
233 break;
234 default:
235 break;
236 }
237
238 reg_ctx_sp = m_thread_reg_ctx_sp;
239 } else {
240 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
241 }
242 return reg_ctx_sp;
243 }
244
CalculateStopInfo()245 bool ThreadElfCore::CalculateStopInfo() {
246 ProcessSP process_sp(GetProcess());
247 if (!process_sp)
248 return false;
249
250 SetStopInfo(StopInfo::CreateStopReasonWithSignal(
251 *this, m_signo, /*description=*/nullptr, m_code));
252 return true;
253 }
254
255 // Parse PRSTATUS from NOTE entry
ELFLinuxPrStatus()256 ELFLinuxPrStatus::ELFLinuxPrStatus() {
257 memset(this, 0, sizeof(ELFLinuxPrStatus));
258 }
259
GetSize(const lldb_private::ArchSpec & arch)260 size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
261 constexpr size_t mips_linux_pr_status_size_o32 = 96;
262 constexpr size_t mips_linux_pr_status_size_n32 = 72;
263 constexpr size_t num_ptr_size_members = 10;
264 if (arch.IsMIPS()) {
265 std::string abi = arch.GetTargetABI();
266 assert(!abi.empty() && "ABI is not set");
267 if (!abi.compare("n64"))
268 return sizeof(ELFLinuxPrStatus);
269 else if (!abi.compare("o32"))
270 return mips_linux_pr_status_size_o32;
271 // N32 ABI
272 return mips_linux_pr_status_size_n32;
273 }
274 switch (arch.GetCore()) {
275 case lldb_private::ArchSpec::eCore_x86_32_i386:
276 case lldb_private::ArchSpec::eCore_x86_32_i486:
277 return 72;
278 default:
279 if (arch.GetAddressByteSize() == 8)
280 return sizeof(ELFLinuxPrStatus);
281 else
282 return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
283 }
284 }
285
Parse(const DataExtractor & data,const ArchSpec & arch)286 Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
287 const ArchSpec &arch) {
288 Status error;
289 if (GetSize(arch) > data.GetByteSize()) {
290 error.SetErrorStringWithFormat(
291 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
292 GetSize(arch), data.GetByteSize());
293 return error;
294 }
295
296 // Read field by field to correctly account for endianess of both the core
297 // dump and the platform running lldb.
298 offset_t offset = 0;
299 si_signo = data.GetU32(&offset);
300 si_code = data.GetU32(&offset);
301 si_errno = data.GetU32(&offset);
302
303 pr_cursig = data.GetU16(&offset);
304 offset += 2; // pad
305
306 pr_sigpend = data.GetAddress(&offset);
307 pr_sighold = data.GetAddress(&offset);
308
309 pr_pid = data.GetU32(&offset);
310 pr_ppid = data.GetU32(&offset);
311 pr_pgrp = data.GetU32(&offset);
312 pr_sid = data.GetU32(&offset);
313
314 pr_utime.tv_sec = data.GetAddress(&offset);
315 pr_utime.tv_usec = data.GetAddress(&offset);
316
317 pr_stime.tv_sec = data.GetAddress(&offset);
318 pr_stime.tv_usec = data.GetAddress(&offset);
319
320 pr_cutime.tv_sec = data.GetAddress(&offset);
321 pr_cutime.tv_usec = data.GetAddress(&offset);
322
323 pr_cstime.tv_sec = data.GetAddress(&offset);
324 pr_cstime.tv_usec = data.GetAddress(&offset);
325
326 return error;
327 }
328
329 // Parse PRPSINFO from NOTE entry
ELFLinuxPrPsInfo()330 ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
331 memset(this, 0, sizeof(ELFLinuxPrPsInfo));
332 }
333
GetSize(const lldb_private::ArchSpec & arch)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
Parse(const DataExtractor & data,const ArchSpec & arch)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.GetAddress(&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 // Parse SIGINFO from NOTE entry
ELFLinuxSigInfo()406 ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
407
GetSize(const lldb_private::ArchSpec & arch)408 size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
409 if (arch.IsMIPS())
410 return sizeof(ELFLinuxSigInfo);
411 switch (arch.GetCore()) {
412 case lldb_private::ArchSpec::eCore_x86_64_x86_64:
413 return sizeof(ELFLinuxSigInfo);
414 case lldb_private::ArchSpec::eCore_s390x_generic:
415 case lldb_private::ArchSpec::eCore_x86_32_i386:
416 case lldb_private::ArchSpec::eCore_x86_32_i486:
417 return 12;
418 default:
419 return 0;
420 }
421 }
422
Parse(const DataExtractor & data,const ArchSpec & arch)423 Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
424 Status error;
425 if (GetSize(arch) > data.GetByteSize()) {
426 error.SetErrorStringWithFormat(
427 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
428 GetSize(arch), data.GetByteSize());
429 return error;
430 }
431
432 // Parsing from a 32 bit ELF core file, and populating/reusing the structure
433 // properly, because the struct is for the 64 bit version
434 offset_t offset = 0;
435 si_signo = data.GetU32(&offset);
436 si_errno = data.GetU32(&offset);
437 si_code = data.GetU32(&offset);
438
439 return error;
440 }
441