LLDB mainline
MinidumpFileBuilder.cpp
Go to the documentation of this file.
1//===-- MinidumpFileBuilder.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
10
11#include <cstring>
12
15
16#include "lldb/Core/Module.h"
18#include "lldb/Core/Section.h"
19#include "lldb/Target/ABI.h"
21#include "lldb/Target/Process.h"
28#include "lldb/Utility/Log.h"
31
32#include "llvm/ADT/StringRef.h"
33#include "llvm/BinaryFormat/Minidump.h"
34#include "llvm/Support/ConvertUTF.h"
35#include "llvm/Support/Endian.h"
36#include "llvm/Support/Error.h"
37#include "llvm/TargetParser/Triple.h"
38
41#include "lldb/lldb-forward.h"
42#include "lldb/lldb-types.h"
43
44#include <algorithm>
45#include <cinttypes>
46#include <cstddef>
47#include <cstdint>
48#include <utility>
49
50using namespace lldb;
51using namespace lldb_private;
52using namespace llvm::minidump;
53
55 // First set the offset on the file, and on the bytes saved
57 // We know we will have at least Misc, SystemInfo, Modules, and ThreadList
58 // (corresponding memory list for stacks), an additional memory list for
59 // non-stacks, and a stream to mark this minidump was generated by LLDB.
60 lldb_private::Target &target = m_process_sp->GetTarget();
62 // Check if OS is linux and reserve directory space for all linux specific
63 // breakpad extension directories.
64 if (target.GetArchitecture().GetTriple().getOS() ==
65 llvm::Triple::OSType::Linux)
67
68 // Go through all of the threads and check for exceptions.
69 std::vector<lldb::ThreadSP> threads =
70 m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
71 for (const ThreadSP &thread_sp : threads) {
72 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
73 if (stop_info_sp) {
74 const StopReason &stop_reason = stop_info_sp->GetStopReason();
75 if (stop_reason != lldb::eStopReasonInvalid)
77 }
78 }
79
80 // Add a generous buffer of directories, these are quite small
81 // and forks may add new directories upstream LLDB hadn't accounted for
82 // when we started pre-calculating directory size, so this should account for
83 // that
85
87 m_expected_directories * sizeof(llvm::minidump::Directory);
89 offset_t new_offset = m_core_file->SeekFromStart(m_saved_data_size);
90 if (new_offset != m_saved_data_size)
92 "Failed to fill in header and directory "
93 "sections. Written / Expected (%" PRIx64 " / %" PRIx64 ")",
94 new_offset, m_saved_data_size);
95
96 if (error.Fail())
97 return error;
98
100}
101
103 uint64_t stream_size) {
104 // We explicitly cast type, an 32b enum, to uint32_t to avoid warnings.
108 "Unable to add directory for stream type "
109 "%x, offset is greater then 32 bit limit.",
110 (uint32_t)type);
111 return error;
112 }
113
114 if (m_directories.size() + 1 > m_expected_directories) {
116 "Unable to add directory for stream type %x, exceeded expected number "
117 "of directories %zu.",
118 (uint32_t)type, m_expected_directories);
119 return error;
120 }
121
122 LocationDescriptor loc;
123 loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size);
124 // Stream will begin at the current end of data section
125 loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
126
127 Directory dir;
128 dir.Type = static_cast<llvm::support::little_t<StreamType>>(type);
129 dir.Location = loc;
130
131 m_directories.push_back(dir);
132 return error;
133}
134
137 StreamType type = StreamType::LLDBGenerated;
138 return AddDirectory(type, 0);
139}
140
143 const llvm::Triple &target_triple =
144 m_process_sp->GetTarget().GetArchitecture().GetTriple();
145 error =
146 AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo));
147 if (error.Fail())
148 return error;
149
150 llvm::minidump::ProcessorArchitecture arch;
151 switch (target_triple.getArch()) {
152 case llvm::Triple::ArchType::x86_64:
153 arch = ProcessorArchitecture::AMD64;
154 break;
155 case llvm::Triple::ArchType::x86:
156 arch = ProcessorArchitecture::X86;
157 break;
158 case llvm::Triple::ArchType::arm:
159 arch = ProcessorArchitecture::ARM;
160 break;
161 case llvm::Triple::ArchType::aarch64:
162 arch = ProcessorArchitecture::ARM64;
163 break;
164 case llvm::Triple::ArchType::mips64:
165 case llvm::Triple::ArchType::mips64el:
166 case llvm::Triple::ArchType::mips:
167 case llvm::Triple::ArchType::mipsel:
168 arch = ProcessorArchitecture::MIPS;
169 break;
170 case llvm::Triple::ArchType::ppc64:
171 case llvm::Triple::ArchType::ppc:
172 case llvm::Triple::ArchType::ppc64le:
173 arch = ProcessorArchitecture::PPC;
174 break;
175 default:
177 "Architecture %s not supported.",
178 target_triple.getArchName().str().c_str());
179 return error;
180 };
181
182 llvm::support::little_t<OSPlatform> platform_id;
183 switch (target_triple.getOS()) {
184 case llvm::Triple::OSType::Linux:
185 if (target_triple.getEnvironment() ==
186 llvm::Triple::EnvironmentType::Android)
187 platform_id = OSPlatform::Android;
188 else
189 platform_id = OSPlatform::Linux;
190 break;
191 case llvm::Triple::OSType::Win32:
192 platform_id = OSPlatform::Win32NT;
193 break;
194 case llvm::Triple::OSType::MacOSX:
195 platform_id = OSPlatform::MacOSX;
196 break;
197 case llvm::Triple::OSType::IOS:
198 platform_id = OSPlatform::IOS;
199 break;
200 case llvm::Triple::OSType::FreeBSD:
201 case llvm::Triple::OSType::NetBSD:
202 case llvm::Triple::OSType::OpenBSD:
203 platform_id = OSPlatform::Unix;
204 break;
205 default:
207 "OS %s not supported.", target_triple.getOSName().str().c_str());
208 return error;
209 };
210
211 llvm::minidump::SystemInfo sys_info{};
212 sys_info.ProcessorArch =
213 static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
214 // Global offset to beginning of a csd_string in a data section
215 sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
216 GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
217 sys_info.PlatformId = platform_id;
218 m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));
219
220 std::string csd_string;
221
222 error = WriteString(csd_string, &m_data);
223 if (error.Fail()) {
224 error =
225 Status::FromErrorString("Unable to convert the csd string to UTF16.");
226 return error;
227 }
228
229 return error;
230}
231
232Status WriteString(const std::string &to_write,
235 // let the StringRef eat also the null terminator
236 llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
237 llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;
238
239 bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
240 if (!converted) {
242 "Unable to convert the string to UTF16. Failed to convert %s",
243 to_write.c_str());
244 return error;
245 }
246
247 // size of the UTF16 string should be written without the null terminator
248 // that is stored in 2 bytes
249 llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);
250
251 buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
252 buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());
253
254 return error;
255}
256
257llvm::Expected<uint64_t> getModuleFileSize(Target &target,
258 const ModuleSP &mod) {
259 // JIT module has the same vm and file size.
260 uint64_t SizeOfImage = 0;
261 if (mod->GetObjectFile()->CalculateType() == ObjectFile::Type::eTypeJIT) {
262 for (const auto &section : *mod->GetObjectFile()->GetSectionList()) {
263 SizeOfImage += section->GetByteSize();
264 }
265 return SizeOfImage;
266 }
267 SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();
268
269 if (!sect_sp) {
270 return llvm::createStringError(std::errc::operation_not_supported,
271 "Couldn't obtain the section information.");
272 }
273 lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
274 // Use memory size since zero fill sections, like ".bss", will be smaller on
275 // disk.
276 lldb::addr_t sect_size = sect_sp->GetByteSize();
277 // This will usually be zero, but make sure to calculate the BaseOfImage
278 // offset.
279 const lldb::addr_t base_sect_offset =
280 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
281 sect_addr;
282 SizeOfImage = sect_size - base_sect_offset;
283 lldb::addr_t next_sect_addr = sect_addr + sect_size;
284 Address sect_so_addr;
285 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
286 lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
287 while (next_sect_sp &&
288 next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
289 sect_size = next_sect_sp->GetByteSize();
290 SizeOfImage += sect_size;
291 next_sect_addr += sect_size;
292 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
293 next_sect_sp = sect_so_addr.GetSection();
294 }
295
296 return SizeOfImage;
297}
298
299// ModuleList stream consists of a number of modules, followed by an array
300// of llvm::minidump::Module's structures. Every structure informs about a
301// single module. Additional data of variable length, such as module's names,
302// are stored just after the ModuleList stream. The llvm::minidump::Module
303// structures point to this helper data by global offset.
305 constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
307
308 lldb_private::Target &target = m_process_sp->GetTarget();
309 const ModuleList &modules = target.GetImages();
310 llvm::support::ulittle32_t modules_count =
311 static_cast<llvm::support::ulittle32_t>(modules.GetSize());
312
313 // This helps us with getting the correct global offset in minidump
314 // file later, when we will be setting up offsets from the
315 // the llvm::minidump::Module's structures into helper data
316 size_t size_before = GetCurrentDataEndOffset();
317
318 // Temporary storage for the helper data (of variable length)
319 // as these cannot be dumped to m_data before dumping entire
320 // array of module structures.
321 DataBufferHeap helper_data;
322
323 // Vector to store modules that pass validation.
324 std::vector<std::pair<ModuleSP, uint64_t>> valid_modules;
325
326 for (size_t i = 0; i < modules_count; ++i) {
327 ModuleSP mod = modules.GetModuleAtIndex(i);
328 std::string module_name = mod->GetSpecificationDescription();
329 auto maybe_mod_size = getModuleFileSize(target, mod);
330 if (!maybe_mod_size) {
331 llvm::Error mod_size_err = maybe_mod_size.takeError();
332 Log *log = GetLog(LLDBLog::Object);
333 llvm::handleAllErrors(
334 std::move(mod_size_err), [&](const llvm::ErrorInfoBase &E) {
335 LLDB_LOGF(log, "Unable to get the size of module %s: %s",
336 module_name.c_str(), E.message().c_str());
337 });
338 continue;
339 }
340 valid_modules.emplace_back(mod, *maybe_mod_size);
341 }
342
343 size_t module_stream_size = sizeof(llvm::support::ulittle32_t) +
344 valid_modules.size() * minidump_module_size;
345
346 error = AddDirectory(StreamType::ModuleList, module_stream_size);
347 if (error.Fail())
348 return error;
349
350 // Setting the header with the number of modules.
351 llvm::support::ulittle32_t count =
352 static_cast<llvm::support::ulittle32_t>(valid_modules.size());
353 m_data.AppendData(&count, sizeof(llvm::support::ulittle32_t));
354
355 for (const auto &valid_module : valid_modules) {
356 ModuleSP mod = valid_module.first;
357 uint64_t module_size = valid_module.second;
358 std::string module_name = mod->GetSpecificationDescription();
359
360 llvm::support::ulittle32_t signature =
361 static_cast<llvm::support::ulittle32_t>(
362 static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
363 auto uuid = mod->GetUUID().GetBytes();
364
365 VSFixedFileInfo info;
366 info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
367 info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
368 info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
369 info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
370 info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
371 info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
372 info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
373 info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
374 info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
375 info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
376 info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
377 info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
378 info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);
379
380 LocationDescriptor ld;
381 ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
382 ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);
383
384 // Setting up LocationDescriptor for uuid string. The global offset into
385 // minidump file is calculated.
386 LocationDescriptor ld_cv;
387 ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
388 sizeof(llvm::support::ulittle32_t) + uuid.size());
389 ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
390 size_before + module_stream_size + helper_data.GetByteSize());
391
392 helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
393 helper_data.AppendData(uuid.begin(), uuid.size());
394
395 llvm::minidump::Module m{};
396 m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
397 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
398 m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(module_size);
399 m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
400 m.TimeDateStamp =
401 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
402 m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
403 size_before + module_stream_size + helper_data.GetByteSize());
404 m.VersionInfo = info;
405 m.CvRecord = ld_cv;
406 m.MiscRecord = ld;
407
408 error = WriteString(module_name, &helper_data);
409
410 if (error.Fail())
411 return error;
412
413 m_data.AppendData(&m, sizeof(llvm::minidump::Module));
414 }
415
416 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
417 return error;
418}
419
421 llvm::StringRef reg_name) {
422 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
423 if (!reg_info)
424 return 0;
426 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
427 if (!success)
428 return 0;
429 return reg_value.GetAsUInt16();
430}
431
433 llvm::StringRef reg_name) {
434 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
435 if (!reg_info)
436 return 0;
438 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
439 if (!success)
440 return 0;
441 return reg_value.GetAsUInt32();
442}
443
445 llvm::StringRef reg_name) {
446 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
447 if (!reg_info)
448 return 0;
450 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
451 if (!success)
452 return 0;
453 return reg_value.GetAsUInt64();
454}
455
456llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
457 llvm::StringRef reg_name) {
458 return static_cast<llvm::support::ulittle16_t>(
459 read_register_u16_raw(reg_ctx, reg_name));
460}
461
462llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
463 llvm::StringRef reg_name) {
464 return static_cast<llvm::support::ulittle32_t>(
465 read_register_u32_raw(reg_ctx, reg_name));
466}
467
468llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
469 llvm::StringRef reg_name) {
470 return static_cast<llvm::support::ulittle64_t>(
471 read_register_u64_raw(reg_ctx, reg_name));
472}
473
474void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name,
475 uint8_t *dst) {
476 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
477 if (reg_info) {
479 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
481 uint32_t bytes_copied = reg_value.GetAsMemoryData(
482 *reg_info, dst, 16, lldb::ByteOrder::eByteOrderLittle, error);
483 if (bytes_copied == 16)
484 return;
485 }
486 }
487 // If anything goes wrong, then zero out the register value.
488 memset(dst, 0, 16);
489}
490
494 thread_context.p1_home = {};
495 thread_context.context_flags = static_cast<uint32_t>(
501 thread_context.rax = read_register_u64(reg_ctx, "rax");
502 thread_context.rbx = read_register_u64(reg_ctx, "rbx");
503 thread_context.rcx = read_register_u64(reg_ctx, "rcx");
504 thread_context.rdx = read_register_u64(reg_ctx, "rdx");
505 thread_context.rdi = read_register_u64(reg_ctx, "rdi");
506 thread_context.rsi = read_register_u64(reg_ctx, "rsi");
507 thread_context.rbp = read_register_u64(reg_ctx, "rbp");
508 thread_context.rsp = read_register_u64(reg_ctx, "rsp");
509 thread_context.r8 = read_register_u64(reg_ctx, "r8");
510 thread_context.r9 = read_register_u64(reg_ctx, "r9");
511 thread_context.r10 = read_register_u64(reg_ctx, "r10");
512 thread_context.r11 = read_register_u64(reg_ctx, "r11");
513 thread_context.r12 = read_register_u64(reg_ctx, "r12");
514 thread_context.r13 = read_register_u64(reg_ctx, "r13");
515 thread_context.r14 = read_register_u64(reg_ctx, "r14");
516 thread_context.r15 = read_register_u64(reg_ctx, "r15");
517 thread_context.rip = read_register_u64(reg_ctx, "rip");
518 // To make our code agnostic to whatever type the register value identifies
519 // itself as, we read as a u64 and truncate to u32/u16 ourselves.
520 thread_context.eflags = read_register_u64(reg_ctx, "rflags");
521 thread_context.cs = read_register_u64(reg_ctx, "cs");
522 thread_context.fs = read_register_u64(reg_ctx, "fs");
523 thread_context.gs = read_register_u64(reg_ctx, "gs");
524 thread_context.ss = read_register_u64(reg_ctx, "ss");
525 thread_context.ds = read_register_u64(reg_ctx, "ds");
526 thread_context.fs_base = read_register_u64(reg_ctx, "fs_base");
527 thread_context.gs_base = read_register_u64(reg_ctx, "gs_base");
528 return thread_context;
529}
530
534 thread_context.context_flags = static_cast<uint32_t>(
538 char reg_name[16];
539 for (uint32_t i = 0; i < 31; ++i) {
540 snprintf(reg_name, sizeof(reg_name), "x%u", i);
541 thread_context.x[i] = read_register_u64(reg_ctx, reg_name);
542 }
543 // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
544 // name set to "x31"
545 thread_context.x[31] = read_register_u64(reg_ctx, "sp");
546 thread_context.pc = read_register_u64(reg_ctx, "pc");
547 thread_context.cpsr = read_register_u32(reg_ctx, "cpsr");
548 thread_context.fpsr = read_register_u32(reg_ctx, "fpsr");
549 thread_context.fpcr = read_register_u32(reg_ctx, "fpcr");
550 for (uint32_t i = 0; i < 32; ++i) {
551 snprintf(reg_name, sizeof(reg_name), "v%u", i);
552 read_register_u128(reg_ctx, reg_name, &thread_context.v[i * 16]);
553 }
554 return thread_context;
555}
556
558 llvm::Triple::ArchType m_arch;
559 union {
563
564public:
565 ArchThreadContexts(llvm::Triple::ArchType arch) : m_arch(arch) {}
566
568 switch (m_arch) {
569 case llvm::Triple::ArchType::x86_64:
570 context.x86_64 = GetThreadContext_x86_64(reg_ctx);
571 return true;
572 case llvm::Triple::ArchType::aarch64:
573 context.arm64 = GetThreadContext_ARM64(reg_ctx);
574 return true;
575 default:
576 break;
577 }
578 return false;
579 }
580
581 const void *data() const { return &context; }
582
583 size_t size() const {
584 switch (m_arch) {
585 case llvm::Triple::ArchType::x86_64:
586 return sizeof(context.x86_64);
587 case llvm::Triple::ArchType::aarch64:
588 return sizeof(context.arm64);
589 default:
590 break;
591 }
592 return 0;
593 }
594};
595
598 // If we have anything in the heap flush it.
600 m_core_file->SeekFromStart(m_thread_list_start);
601 for (auto &pair : m_thread_by_range_end) {
602 // The thread objects will get a new memory descriptor added
603 // When we are emitting the memory list and then we write it here
604 const llvm::minidump::Thread &thread = pair.second;
605 size_t bytes_to_write = sizeof(llvm::minidump::Thread);
606 size_t bytes_written = bytes_to_write;
607 error = m_core_file->Write(&thread, bytes_written);
608 if (error.Fail() || bytes_to_write != bytes_written) {
610 "Wrote incorrect number of bytes to minidump file. (written %zd/%zd)",
611 bytes_written, bytes_to_write);
612 return error;
613 }
614 }
615
616 return error;
617}
618
620 constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
621 std::vector<ThreadSP> thread_list =
622 m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
623
624 // size of the entire thread stream consists of:
625 // number of threads and threads array
626 size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
627 thread_list.size() * minidump_thread_size;
628 // save for the ability to set up RVA
629 size_t size_before = GetCurrentDataEndOffset();
631 error = AddDirectory(StreamType::ThreadList, thread_stream_size);
632 if (error.Fail())
633 return error;
634
635 llvm::support::ulittle32_t thread_count =
636 static_cast<llvm::support::ulittle32_t>(thread_list.size());
637 m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));
638
639 // Take the offset after the thread count.
641 DataBufferHeap helper_data;
642
643 Log *log = GetLog(LLDBLog::Object);
644 for (const ThreadSP &thread_sp : thread_list) {
645 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
646
647 if (!reg_ctx_sp) {
648 error = Status::FromErrorString("Unable to get the register context.");
649 return error;
650 }
651 RegisterContext *reg_ctx = reg_ctx_sp.get();
652 Target &target = m_process_sp->GetTarget();
653 const ArchSpec &arch = target.GetArchitecture();
654 ArchThreadContexts thread_context(arch.GetMachine());
655 if (!thread_context.prepareRegisterContext(reg_ctx)) {
657 "architecture %s not supported.",
658 arch.GetTriple().getArchName().str().c_str());
659 return error;
660 }
661
662 uint64_t sp = reg_ctx->GetSP();
663 MemoryRegionInfo sp_region;
664 m_process_sp->GetMemoryRegionInfo(sp, sp_region);
665
666 // Emit a blank descriptor
667 MemoryDescriptor stack;
668 LocationDescriptor empty_label;
669 empty_label.DataSize = 0;
670 empty_label.RVA = 0;
671 stack.Memory = empty_label;
672 stack.StartOfMemoryRange = 0;
673 LocationDescriptor thread_context_memory_locator;
674 thread_context_memory_locator.DataSize =
675 static_cast<llvm::support::ulittle32_t>(thread_context.size());
676 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
677 size_before + thread_stream_size + helper_data.GetByteSize());
678 // Cache thie thread context memory so we can reuse for exceptions.
679 m_tid_to_reg_ctx[thread_sp->GetID()] = thread_context_memory_locator;
680
681 LLDB_LOGF(log, "AddThreadList for thread %d: thread_context %zu bytes",
682 thread_sp->GetIndexID(), thread_context.size());
683 helper_data.AppendData(thread_context.data(), thread_context.size());
684
685 llvm::minidump::Thread t;
686 t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
687 t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
688 (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
689 t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
690 t.Priority = static_cast<llvm::support::ulittle32_t>(0);
691 t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
692 t.Stack = stack, t.Context = thread_context_memory_locator;
693
694 // We save off the stack object so we can circle back and clean it up.
695 m_thread_by_range_end[sp_region.GetRange().GetRangeEnd()] = t;
696 m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
697 }
698
699 LLDB_LOGF(log, "AddThreadList(): total helper_data %" PRIx64 " bytes",
700 helper_data.GetByteSize());
701 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
702 return Status();
703}
704
706 std::vector<ThreadSP> thread_list =
707 m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
709 for (const ThreadSP &thread_sp : thread_list) {
710 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
711 // If we don't have a stop info, or if it's invalid, skip.
712 if (!stop_info_sp ||
713 stop_info_sp->GetStopReason() == lldb::eStopReasonInvalid)
714 continue;
715
716 constexpr size_t minidump_exception_size =
717 sizeof(llvm::minidump::ExceptionStream);
718 error = AddDirectory(StreamType::Exception, minidump_exception_size);
719 if (error.Fail())
720 return error;
721
722 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
723 Exception exp_record = {};
724 exp_record.ExceptionCode =
725 static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
726 exp_record.ExceptionFlags =
727 static_cast<llvm::support::ulittle32_t>(Exception::LLDB_FLAG);
728 exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
729 exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
730 exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(1);
731 std::string description = stop_info_sp->GetDescription();
732 // We have 120 bytes to work with and it's unlikely description will
733 // overflow, but we gotta check.
734 memcpy(&exp_record.ExceptionInformation, description.c_str(),
735 std::min(description.size(), Exception::MaxParameterBytes));
736 exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
737 ExceptionStream exp_stream;
738 exp_stream.ThreadId =
739 static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
740 exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
741 exp_stream.ExceptionRecord = exp_record;
742 auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
743 if (Iter != m_tid_to_reg_ctx.end()) {
744 exp_stream.ThreadContext = Iter->second;
745 } else {
746 exp_stream.ThreadContext.DataSize = 0;
747 exp_stream.ThreadContext.RVA = 0;
748 }
749 m_data.AppendData(&exp_stream, minidump_exception_size);
750 }
751
752 return error;
753}
754
757 error = AddDirectory(StreamType::MiscInfo,
759 if (error.Fail())
760 return error;
761
763 misc_info.size = static_cast<llvm::support::ulittle32_t>(
765 // Default set flags1 to 0, in case that we will not be able to
766 // get any information
767 misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);
768
770 m_process_sp->GetProcessInfo(process_info);
771 if (process_info.ProcessIDIsValid()) {
772 // Set flags1 to reflect that PID is filled in
773 misc_info.flags1 =
774 static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
776 misc_info.process_id =
777 static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
778 }
779
780 m_data.AppendData(&misc_info,
782 return error;
783}
784
785std::unique_ptr<llvm::MemoryBuffer>
786getFileStreamHelper(const std::string &path) {
787 auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
788 if (!maybe_stream)
789 return nullptr;
790 return std::move(maybe_stream.get());
791}
792
795 // No-op if we are not on linux.
796 if (m_process_sp->GetTarget().GetArchitecture().GetTriple().getOS() !=
797 llvm::Triple::Linux)
798 return error;
799
800 std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
801 {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
802 {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
803 };
804
806 m_process_sp->GetProcessInfo(process_info);
807 if (process_info.ProcessIDIsValid()) {
808 lldb::pid_t pid = process_info.GetProcessID();
809 std::string pid_str = std::to_string(pid);
810 files_with_stream_types.push_back(
811 {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
812 files_with_stream_types.push_back(
813 {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
814 files_with_stream_types.push_back(
815 {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
816 files_with_stream_types.push_back(
817 {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
818 files_with_stream_types.push_back(
819 {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
820 files_with_stream_types.push_back(
821 {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
822 files_with_stream_types.push_back(
823 {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
824 }
825
826 for (const auto &entry : files_with_stream_types) {
827 StreamType stream = entry.first;
828 std::string path = entry.second;
829 auto memory_buffer = getFileStreamHelper(path);
830
831 if (memory_buffer) {
832 size_t size = memory_buffer->getBufferSize();
833 if (size == 0)
834 continue;
835 error = AddDirectory(stream, size);
836 if (error.Fail())
837 return error;
838 m_data.AppendData(memory_buffer->getBufferStart(), size);
839 }
840 }
841
842 return error;
843}
844
847
848 // We first save the thread stacks to ensure they fit in the first UINT32_MAX
849 // bytes of the core file. Thread structures in minidump files can only use
850 // 32 bit memory descriptiors, so we emit them first to ensure the memory is
851 // in accessible with a 32 bit offset.
852 std::vector<CoreFileMemoryRange> ranges_32;
853 llvm::Expected<CoreFileMemoryRanges> all_core_memory_ranges_maybe =
854 m_save_core_options.GetMemoryRegionsToSave();
855 if (!all_core_memory_ranges_maybe)
856 return Status::FromError(all_core_memory_ranges_maybe.takeError());
857
858 const CoreFileMemoryRanges &all_core_memory_ranges =
859 *all_core_memory_ranges_maybe;
860
861 lldb_private::Progress progress("Saving Minidump File", "",
862 all_core_memory_ranges.GetSize());
863 std::vector<CoreFileMemoryRange> all_core_memory_vec;
864 // Extract all the data into just a vector of data. So we can mutate this in
865 // place.
866 for (const auto &core_range : all_core_memory_ranges)
867 all_core_memory_vec.push_back(core_range.data);
868
869 // Start by saving all of the stacks and ensuring they fit under the 32b
870 // limit.
871 uint64_t total_size = GetCurrentDataEndOffset();
872 auto iterator = all_core_memory_vec.begin();
873 while (iterator != all_core_memory_vec.end()) {
874 if (m_thread_by_range_end.count(iterator->range.end()) > 0) {
875 // We don't save stacks twice.
876 ranges_32.push_back(*iterator);
877 total_size +=
878 iterator->range.size() + sizeof(llvm::minidump::MemoryDescriptor);
879 iterator = all_core_memory_vec.erase(iterator);
880 } else {
881 iterator++;
882 }
883 }
884
885 // The header has to be in 32b memory, as it needs to be addressable by a 32b
886 // RVA. Everything else can be 64b.
887 total_size += sizeof(llvm::minidump::MemoryListHeader);
888
889 if (total_size >= UINT32_MAX) {
891 "Unable to write minidump. Stack memory "
892 "exceeds 32b limit. (Num Stacks %zu)",
893 ranges_32.size());
894 return error;
895 }
896
897 // Save only the thread stacks to the 32b memory list. Everything else will
898 // get put in Memory64, this simplifies tracking
899 error = AddMemoryList_32(ranges_32, progress);
900 if (error.Fail())
901 return error;
902
903 // Add the remaining memory as a 64b range.
904 if (!all_core_memory_ranges.IsEmpty()) {
905 error = AddMemoryList_64(all_core_memory_vec, progress);
906 if (error.Fail())
907 return error;
908 }
909
910 return FixThreadStacks();
911}
912
914 // write header
915 llvm::minidump::Header header;
916 header.Signature = static_cast<llvm::support::ulittle32_t>(
917 llvm::minidump::Header::MagicSignature);
918 header.Version = static_cast<llvm::support::ulittle32_t>(
919 llvm::minidump::Header::MagicVersion);
920 header.NumberOfStreams =
921 static_cast<llvm::support::ulittle32_t>(m_directories.size());
922 // We write the directories right after the header.
923 header.StreamDirectoryRVA =
924 static_cast<llvm::support::ulittle32_t>(HEADER_SIZE);
925 header.Checksum = static_cast<llvm::support::ulittle32_t>(
926 0u); // not used in most of the writers
927 header.TimeDateStamp =
928 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
929 header.Flags =
930 static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag
931
933 size_t bytes_written;
934
935 m_core_file->SeekFromStart(0);
936 bytes_written = HEADER_SIZE;
937 error = m_core_file->Write(&header, bytes_written);
938 if (error.Fail() || bytes_written != HEADER_SIZE) {
939 if (bytes_written != HEADER_SIZE)
941 "Unable to write the minidump header (written %zd/%zd)",
942 bytes_written, HEADER_SIZE);
943 return error;
944 }
945 return error;
946}
947
951
954 size_t bytes_written;
955 m_core_file->SeekFromStart(HEADER_SIZE);
956 for (const Directory &dir : m_directories) {
957 bytes_written = DIRECTORY_SIZE;
958 error = m_core_file->Write(&dir, bytes_written);
959 if (error.Fail() || bytes_written != DIRECTORY_SIZE) {
960 if (bytes_written != DIRECTORY_SIZE)
962 "unable to write the directory (written %zd/%zd)", bytes_written,
964 return error;
965 }
966 }
967
968 return error;
969}
970
972 lldb_private::DataBufferHeap &data_buffer,
973 const lldb_private::CoreFileMemoryRange &range, uint64_t &bytes_read) {
974
975 const lldb::addr_t addr = range.range.start();
976 const lldb::addr_t size = range.range.size();
977 Log *log = GetLog(LLDBLog::Object);
978 void *buf = data_buffer.GetBytes();
979 const lldb::addr_t chunk_size = data_buffer.GetByteSize();
980 // Step over an unreadable page at a time, so we never zero-fill memory that
981 // could be read.
982 const lldb::addr_t page_size = 4096;
983
984 // Write exactly `size` bytes: Memory64List locates each range by the
985 // cumulative DataSize of the ranges before it.
986 bytes_read = 0;
987 Status addDataError;
988 while (bytes_read < size) {
989 const lldb::addr_t current_addr = addr + bytes_read;
990 const lldb::addr_t bytes_remaining = size - bytes_read;
991 const lldb::addr_t bytes_to_read = std::min(bytes_remaining, chunk_size);
993 const lldb::addr_t bytes_read_for_chunk =
994 m_process_sp->ReadMemoryFromInferior(current_addr, buf, bytes_to_read,
995 error);
996
997 if (bytes_read_for_chunk > 0) {
998 addDataError = AddData(buf, bytes_read_for_chunk);
999 if (addDataError.Fail())
1000 return addDataError;
1001 bytes_read += bytes_read_for_chunk;
1002 }
1003
1004 // Unreadable page: zero-fill it and continue past the hole.
1005 if (bytes_read_for_chunk < bytes_to_read) {
1006 const lldb::addr_t hole = addr + bytes_read;
1007 lldb::addr_t fill = ((hole + page_size) & ~(page_size - 1)) - hole;
1008 fill = std::min(fill, size - bytes_read);
1009 fill = std::min(fill, chunk_size);
1010 LLDB_LOGF(log,
1011 "Failed to read memory region at: 0x%" PRIx64
1012 ". Zero-filling 0x%" PRIx64 " bytes, error: %s",
1013 hole, fill, error.AsCString());
1014 ::memset(buf, 0, fill);
1015 addDataError = AddData(buf, fill);
1016 if (addDataError.Fail())
1017 return addDataError;
1018 bytes_read += fill;
1019 }
1020 }
1021
1022 return addDataError;
1023}
1024
1025static uint64_t
1026GetLargestRangeSize(const std::vector<CoreFileMemoryRange> &ranges) {
1027 uint64_t max_size = 0;
1028 for (const auto &core_range : ranges)
1029 max_size = std::max(max_size, core_range.range.size());
1030 return max_size;
1031}
1032
1033Status
1034MinidumpFileBuilder::AddMemoryList_32(std::vector<CoreFileMemoryRange> &ranges,
1035 Progress &progress) {
1036 std::vector<MemoryDescriptor> descriptors;
1037 Status error;
1038 if (ranges.size() == 0)
1039 return error;
1040
1041 Log *log = GetLog(LLDBLog::Object);
1042 size_t region_index = 0;
1043 lldb_private::DataBufferHeap data_buffer(
1044 std::min(GetLargestRangeSize(ranges), MAX_WRITE_CHUNK_SIZE), 0);
1045 for (const auto &core_range : ranges) {
1046 // Take the offset before we write.
1047 const offset_t offset_for_data = GetCurrentDataEndOffset();
1048 const addr_t addr = core_range.range.start();
1049 const addr_t size = core_range.range.size();
1050 const addr_t end = core_range.range.end();
1051
1052 LLDB_LOGF(log,
1053 "AddMemoryList %zu/%zu reading memory for region "
1054 "(0x%" PRIx64 " bytes) [0x%" PRIx64 ", 0x%" PRIx64 ")",
1055 region_index, ranges.size(), size, addr, addr + size);
1056 ++region_index;
1057
1058 progress.Increment(1, "Adding Memory Range " + core_range.Dump());
1059 uint64_t bytes_read = 0;
1060 error = ReadWriteMemoryInChunks(data_buffer, core_range, bytes_read);
1061 if (error.Fail())
1062 return error;
1063
1064 // If we completely failed to read this range
1065 // we can drop the memory range
1066 if (bytes_read == 0)
1067 continue;
1068
1069 MemoryDescriptor descriptor;
1070 descriptor.StartOfMemoryRange =
1071 static_cast<llvm::support::ulittle64_t>(addr);
1072 descriptor.Memory.DataSize =
1073 static_cast<llvm::support::ulittle32_t>(bytes_read);
1074 descriptor.Memory.RVA =
1075 static_cast<llvm::support::ulittle32_t>(offset_for_data);
1076 descriptors.push_back(descriptor);
1077 if (m_thread_by_range_end.count(end) > 0)
1078 m_thread_by_range_end[end].Stack = descriptor;
1079 }
1080
1081 // Add a directory that references this list
1082 // With a size of the number of ranges as a 32 bit num
1083 // And then the size of all the ranges
1084 error = AddDirectory(StreamType::MemoryList,
1085 sizeof(llvm::minidump::MemoryListHeader) +
1086 descriptors.size() *
1087 sizeof(llvm::minidump::MemoryDescriptor));
1088 if (error.Fail())
1089 return error;
1090
1091 llvm::minidump::MemoryListHeader list_header;
1092 llvm::support::ulittle32_t memory_ranges_num =
1093 static_cast<llvm::support::ulittle32_t>(descriptors.size());
1094 list_header.NumberOfMemoryRanges = memory_ranges_num;
1095 m_data.AppendData(&list_header, sizeof(llvm::minidump::MemoryListHeader));
1096 // For 32b we can get away with writing off the descriptors after the data.
1097 // This means no cleanup loop needed.
1098 m_data.AppendData(descriptors.data(),
1099 descriptors.size() * sizeof(MemoryDescriptor));
1100
1101 return error;
1102}
1103
1104Status
1105MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges,
1106 Progress &progress) {
1107 Status error;
1108 if (ranges.empty())
1109 return error;
1110
1111 error = AddDirectory(StreamType::Memory64List,
1112 (sizeof(llvm::minidump::Memory64ListHeader)) +
1113 ranges.size() *
1114 sizeof(llvm::minidump::MemoryDescriptor_64));
1115 if (error.Fail())
1116 return error;
1117
1118 llvm::minidump::Memory64ListHeader list_header;
1119 llvm::support::ulittle64_t memory_ranges_num =
1120 static_cast<llvm::support::ulittle64_t>(ranges.size());
1121 list_header.NumberOfMemoryRanges = memory_ranges_num;
1122 // Capture the starting offset for all the descriptors so we can clean them up
1123 // if needed.
1124 offset_t starting_offset =
1125 GetCurrentDataEndOffset() + sizeof(llvm::minidump::Memory64ListHeader);
1126 // The base_rva needs to start after the directories, which is right after
1127 // the descriptors + the size of the header.
1128 offset_t base_rva =
1129 starting_offset +
1130 (ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64));
1131 llvm::support::ulittle64_t memory_ranges_base_rva =
1132 static_cast<llvm::support::ulittle64_t>(base_rva);
1133 list_header.BaseRVA = memory_ranges_base_rva;
1134 m_data.AppendData(&list_header, sizeof(llvm::minidump::Memory64ListHeader));
1135
1136 lldb_private::DataBufferHeap data_buffer(
1137 std::min(GetLargestRangeSize(ranges), MAX_WRITE_CHUNK_SIZE), 0);
1138 bool cleanup_required = false;
1139 std::vector<MemoryDescriptor_64> descriptors;
1140 // Enumerate the ranges and create the memory descriptors so we can append
1141 // them first
1142 for (const auto core_range : ranges) {
1143 // Add the space required to store the memory descriptor
1144 MemoryDescriptor_64 memory_desc;
1145 memory_desc.StartOfMemoryRange =
1146 static_cast<llvm::support::ulittle64_t>(core_range.range.start());
1147 memory_desc.DataSize =
1148 static_cast<llvm::support::ulittle64_t>(core_range.range.size());
1149 descriptors.push_back(memory_desc);
1150 // Now write this memory descriptor to the buffer.
1151 m_data.AppendData(&memory_desc, sizeof(MemoryDescriptor_64));
1152 }
1153
1154 Log *log = GetLog(LLDBLog::Object);
1155 size_t region_index = 0;
1156 for (const auto &core_range : ranges) {
1157 const addr_t addr = core_range.range.start();
1158 const addr_t size = core_range.range.size();
1159
1160 LLDB_LOGF(log,
1161 "AddMemoryList_64 %zu/%zu reading memory for region "
1162 "(%" PRIx64 "bytes) "
1163 "[%" PRIx64 ", %" PRIx64 ")",
1164 region_index, ranges.size(), size, addr, addr + size);
1165
1166 progress.Increment(1, "Adding Memory Range " + core_range.Dump());
1167 uint64_t bytes_read = 0;
1168 error = ReadWriteMemoryInChunks(data_buffer, core_range, bytes_read);
1169 if (error.Fail())
1170 return error;
1171
1172 if (bytes_read == 0) {
1173 cleanup_required = true;
1174 descriptors[region_index].DataSize = 0;
1175 }
1176 if (bytes_read != size) {
1177 cleanup_required = true;
1178 descriptors[region_index].DataSize = bytes_read;
1179 }
1180
1181 ++region_index;
1182 }
1183
1184 // Early return if there is no cleanup needed.
1185 if (!cleanup_required) {
1186 return error;
1187 } else {
1188 // Flush to disk we can make the fixes in place.
1190 // Fixup the descriptors that were not read correctly.
1191 m_core_file->SeekFromStart(starting_offset);
1192 size_t bytes_written = sizeof(MemoryDescriptor_64) * descriptors.size();
1193 error = m_core_file->Write(descriptors.data(), bytes_written);
1194 if (error.Fail() ||
1195 bytes_written != sizeof(MemoryDescriptor_64) * descriptors.size()) {
1197 "unable to write the memory descriptors (written %zd/%zd)",
1198 bytes_written, sizeof(MemoryDescriptor_64) * descriptors.size());
1199 }
1200
1201 return error;
1202 }
1203}
1204
1205Status MinidumpFileBuilder::AddData(const void *data, uint64_t size) {
1206 // Append the data to the buffer, if the buffer spills over, flush it to disk
1207 m_data.AppendData(data, size);
1208 if (m_data.GetByteSize() > MAX_WRITE_CHUNK_SIZE)
1209 return FlushBufferToDisk();
1210
1211 return Status();
1212}
1213
1215 Status error;
1216 // Set the stream to it's end.
1217 m_core_file->SeekFromStart(m_saved_data_size);
1218 addr_t starting_size = m_data.GetByteSize();
1219 addr_t remaining_bytes = starting_size;
1220 offset_t offset = 0;
1221
1222 while (remaining_bytes > 0) {
1223 size_t bytes_written = remaining_bytes;
1224 // We don't care how many bytes we wrote unless we got an error
1225 // so just decrement the remaining bytes.
1226 error = m_core_file->Write(m_data.GetBytes() + offset, bytes_written);
1227 if (error.Fail()) {
1229 "Wrote incorrect number of bytes to minidump file. (written %" PRIx64
1230 "/%" PRIx64 ")",
1231 starting_size - remaining_bytes, starting_size);
1232 return error;
1233 }
1234
1235 offset += bytes_written;
1236 remaining_bytes -= bytes_written;
1237 }
1238
1239 m_saved_data_size += starting_size;
1240 m_data.Clear();
1241 return error;
1242}
1243
1245 Status error;
1246 // If anything is left unsaved, dump it.
1248 if (error.Fail())
1249 return error;
1250
1251 // Overwrite the header which we filled in earlier.
1252 error = DumpHeader();
1253 if (error.Fail())
1254 return error;
1255
1256 // Overwrite the space saved for directories
1258 if (error.Fail())
1259 return error;
1260
1261 return error;
1262}
1263
1265 Log *log = GetLog(LLDBLog::Object);
1266
1267 if (m_core_file) {
1268 Status error = m_core_file->Close();
1269 if (error.Fail())
1270 LLDB_LOGF(log, "Failed to close minidump file: %s", error.AsCString());
1271
1272 m_core_file.reset();
1273 }
1274}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition Log.h:389
llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, llvm::StringRef reg_name)
static uint64_t GetLargestRangeSize(const std::vector< CoreFileMemoryRange > &ranges)
uint64_t read_register_u64_raw(RegisterContext *reg_ctx, llvm::StringRef reg_name)
Status WriteString(const std::string &to_write, lldb_private::DataBufferHeap *buffer)
lldb_private::minidump::MinidumpContext_x86_64 GetThreadContext_x86_64(RegisterContext *reg_ctx)
llvm::Expected< uint64_t > getModuleFileSize(Target &target, const ModuleSP &mod)
uint16_t read_register_u16_raw(RegisterContext *reg_ctx, llvm::StringRef reg_name)
llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx, llvm::StringRef reg_name)
void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name, uint8_t *dst)
std::unique_ptr< llvm::MemoryBuffer > getFileStreamHelper(const std::string &path)
llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, llvm::StringRef reg_name)
minidump::RegisterContextMinidump_ARM64::Context GetThreadContext_ARM64(RegisterContext *reg_ctx)
uint32_t read_register_u32_raw(RegisterContext *reg_ctx, llvm::StringRef reg_name)
Structure holding data neccessary for minidump file creation.
lldb_private::Status WriteString(const std::string &to_write, lldb_private::DataBufferHeap *buffer)
const void * data() const
llvm::Triple::ArchType m_arch
union ArchThreadContexts::@064273365003336047230113131305105076031325035111 context
lldb_private::minidump::MinidumpContext_x86_64 x86_64
lldb_private::minidump::RegisterContextMinidump_ARM64::Context arm64
bool prepareRegisterContext(RegisterContext *reg_ctx)
ArchThreadContexts(llvm::Triple::ArchType arch)
lldb_private::Status AddExceptions()
std::unordered_map< lldb::tid_t, llvm::minidump::LocationDescriptor > m_tid_to_reg_ctx
lldb_private::Status AddLLDBGeneratedStream()
lldb_private::Status AddThreadList()
lldb_private::Status AddHeaderAndCalculateDirectories()
static constexpr uint64_t MAX_WRITE_CHUNK_SIZE
static constexpr size_t DIRECTORY_SIZE
lldb_private::DataBufferHeap m_data
lldb_private::Status AddSystemInfo()
lldb_private::Status ReadWriteMemoryInChunks(lldb_private::DataBufferHeap &data_buffer, const lldb_private::CoreFileMemoryRange &range, uint64_t &bytes_read)
lldb_private::Status AddMemoryList()
std::unordered_map< lldb::addr_t, llvm::minidump::Thread > m_thread_by_range_end
lldb_private::Status AddData(const void *data, uint64_t size)
lldb_private::Status DumpFile()
lldb_private::SaveCoreOptions m_save_core_options
lldb_private::Status FlushBufferToDisk()
lldb::offset_t m_thread_list_start
lldb_private::Status AddDirectory(llvm::minidump::StreamType type, uint64_t stream_size)
lldb_private::Status FixThreadStacks()
lldb::ProcessSP m_process_sp
static constexpr size_t HEADER_SIZE
lldb::offset_t GetCurrentDataEndOffset() const
lldb_private::Status AddMemoryList_32(std::vector< lldb_private::CoreFileMemoryRange > &ranges, lldb_private::Progress &progress)
std::vector< llvm::minidump::Directory > m_directories
lldb_private::Status DumpDirectories() const
lldb_private::Status AddLinuxFileStreams()
lldb_private::Status AddModuleList()
lldb_private::Status AddMiscInfo()
lldb_private::Status DumpHeader() const
lldb_private::Status AddMemoryList_64(std::vector< lldb_private::CoreFileMemoryRange > &ranges, lldb_private::Progress &progress)
A section + offset based address class.
Definition Address.h:62
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition Address.h:426
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:547
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:886
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t GetByteSize() const override
Get the number of bytes in the data buffer.
void AppendData(const void *src, uint64_t src_len)
A collection class for Module objects.
Definition ModuleList.h:128
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
size_t GetSize() const
Gets the size of the module list.
@ eTypeJIT
JIT code that has symbols, sections and possibly debug info.
Definition ObjectFile.h:67
bool ProcessIDIsValid() const
Definition ProcessInfo.h:70
lldb::pid_t GetProcessID() const
Definition ProcessInfo.h:66
A Progress indicator helper class.
Definition Progress.h:60
void Increment(uint64_t amount=1, std::optional< std::string > updated_detail={})
Increment the progress and send a notification to the installed callback.
Definition Progress.cpp:63
uint64_t GetSP(uint64_t fail_value=LLDB_INVALID_ADDRESS)
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
uint16_t GetAsUInt16(uint16_t fail_value=UINT16_MAX, bool *success_ptr=nullptr) const
uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow, bool allow_section_end=false)
Definition Target.cpp:3525
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1283
const ArchSpec & GetArchitecture() const
Definition Target.h:1325
uint8_t * GetBytes()
Get a pointer to the data.
Definition DataBuffer.h:108
#define UINT32_MAX
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::Thread > ThreadSP
uint64_t offset_t
Definition lldb-types.h:86
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
uint64_t pid_t
Definition lldb-types.h:84
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
std::shared_ptr< lldb_private::Section > SectionSP
uint64_t addr_t
Definition lldb-types.h:80
StopReason
Thread stop reasons.
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
std::shared_ptr< lldb_private::Module > ModuleSP
BaseType GetRangeEnd() const
Definition RangeMap.h:78
Every register is described in detail including its name, alternate name (optional),...
llvm::support::ulittle32_t process_id
llvm::support::ulittle32_t flags1