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