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
13
14#include "lldb/Core/Module.h"
16#include "lldb/Core/Section.h"
17#include "lldb/Target/ABI.h"
19#include "lldb/Target/Process.h"
26#include "lldb/Utility/Log.h"
29
30#include "llvm/ADT/StringRef.h"
31#include "llvm/BinaryFormat/Minidump.h"
32#include "llvm/Support/ConvertUTF.h"
33#include "llvm/Support/Endian.h"
34#include "llvm/Support/Error.h"
35#include "llvm/TargetParser/Triple.h"
36
39#include "lldb/lldb-forward.h"
40#include "lldb/lldb-types.h"
41
42#include <algorithm>
43#include <cinttypes>
44#include <climits>
45#include <cstddef>
46#include <cstdint>
47#include <functional>
48#include <iostream>
49#include <set>
50#include <utility>
51#include <vector>
52
53using namespace lldb;
54using namespace lldb_private;
55using namespace llvm::minidump;
56
58 // First set the offset on the file, and on the bytes saved
60 // We know we will have at least Misc, SystemInfo, Modules, and ThreadList
61 // (corresponding memory list for stacks) And an additional memory list for
62 // non-stacks.
63 lldb_private::Target &target = m_process_sp->GetTarget();
65 // Check if OS is linux and reserve directory space for all linux specific
66 // breakpad extension directories.
67 if (target.GetArchitecture().GetTriple().getOS() ==
68 llvm::Triple::OSType::Linux)
70
71 // Go through all of the threads and check for exceptions.
72 lldb_private::ThreadList thread_list = m_process_sp->GetThreadList();
73 const uint32_t num_threads = thread_list.GetSize();
74 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
75 ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
76 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
77 if (stop_info_sp) {
78 const StopReason &stop_reason = stop_info_sp->GetStopReason();
79 if (stop_reason == StopReason::eStopReasonException ||
80 stop_reason == StopReason::eStopReasonSignal)
82 }
83 }
84
86 m_expected_directories * sizeof(llvm::minidump::Directory);
88 offset_t new_offset = m_core_file->SeekFromStart(m_saved_data_size);
89 if (new_offset != m_saved_data_size)
90 error.SetErrorStringWithFormat("Failed to fill in header and directory "
91 "sections. Written / Expected (%" PRIx64
92 " / %" PRIx64 ")",
93 new_offset, m_saved_data_size);
94
95 return error;
96}
97
99 uint64_t stream_size) {
100 // We explicitly cast type, an 32b enum, to uint32_t to avoid warnings.
103 error.SetErrorStringWithFormat("Unable to add directory for stream type "
104 "%x, offset is greater then 32 bit limit.",
105 (uint32_t)type);
106 return error;
107 }
108
109 if (m_directories.size() + 1 > m_expected_directories) {
110 error.SetErrorStringWithFormat(
111 "Unable to add directory for stream type %x, exceeded expected number "
112 "of directories %zu.",
113 (uint32_t)type, m_expected_directories);
114 return error;
115 }
116
117 LocationDescriptor loc;
118 loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size);
119 // Stream will begin at the current end of data section
120 loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
121
122 Directory dir;
123 dir.Type = static_cast<llvm::support::little_t<StreamType>>(type);
124 dir.Location = loc;
125
126 m_directories.push_back(dir);
127 return error;
128}
129
132 const llvm::Triple &target_triple =
133 m_process_sp->GetTarget().GetArchitecture().GetTriple();
134 error =
135 AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo));
136 if (error.Fail())
137 return error;
138
139 llvm::minidump::ProcessorArchitecture arch;
140 switch (target_triple.getArch()) {
141 case llvm::Triple::ArchType::x86_64:
142 arch = ProcessorArchitecture::AMD64;
143 break;
144 case llvm::Triple::ArchType::x86:
145 arch = ProcessorArchitecture::X86;
146 break;
147 case llvm::Triple::ArchType::arm:
148 arch = ProcessorArchitecture::ARM;
149 break;
150 case llvm::Triple::ArchType::aarch64:
151 arch = ProcessorArchitecture::ARM64;
152 break;
153 case llvm::Triple::ArchType::mips64:
154 case llvm::Triple::ArchType::mips64el:
155 case llvm::Triple::ArchType::mips:
156 case llvm::Triple::ArchType::mipsel:
157 arch = ProcessorArchitecture::MIPS;
158 break;
159 case llvm::Triple::ArchType::ppc64:
160 case llvm::Triple::ArchType::ppc:
161 case llvm::Triple::ArchType::ppc64le:
162 arch = ProcessorArchitecture::PPC;
163 break;
164 default:
165 error.SetErrorStringWithFormat("Architecture %s not supported.",
166 target_triple.getArchName().str().c_str());
167 return error;
168 };
169
170 llvm::support::little_t<OSPlatform> platform_id;
171 switch (target_triple.getOS()) {
172 case llvm::Triple::OSType::Linux:
173 if (target_triple.getEnvironment() ==
174 llvm::Triple::EnvironmentType::Android)
175 platform_id = OSPlatform::Android;
176 else
177 platform_id = OSPlatform::Linux;
178 break;
179 case llvm::Triple::OSType::Win32:
180 platform_id = OSPlatform::Win32NT;
181 break;
182 case llvm::Triple::OSType::MacOSX:
183 platform_id = OSPlatform::MacOSX;
184 break;
185 case llvm::Triple::OSType::IOS:
186 platform_id = OSPlatform::IOS;
187 break;
188 default:
189 error.SetErrorStringWithFormat("OS %s not supported.",
190 target_triple.getOSName().str().c_str());
191 return error;
192 };
193
194 llvm::minidump::SystemInfo sys_info;
195 sys_info.ProcessorArch =
196 static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
197 // Global offset to beginning of a csd_string in a data section
198 sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
199 GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
200 sys_info.PlatformId = platform_id;
201 m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));
202
203 std::string csd_string;
204
205 error = WriteString(csd_string, &m_data);
206 if (error.Fail()) {
207 error.SetErrorString("Unable to convert the csd string to UTF16.");
208 return error;
209 }
210
211 return error;
212}
213
214Status WriteString(const std::string &to_write,
217 // let the StringRef eat also null termination char
218 llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
219 llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;
220
221 bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
222 if (!converted) {
223 error.SetErrorStringWithFormat(
224 "Unable to convert the string to UTF16. Failed to convert %s",
225 to_write.c_str());
226 return error;
227 }
228
229 // size of the UTF16 string should be written without the null termination
230 // character that is stored in 2 bytes
231 llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);
232
233 buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
234 buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());
235
236 return error;
237}
238
239llvm::Expected<uint64_t> getModuleFileSize(Target &target,
240 const ModuleSP &mod) {
241 // JIT module has the same vm and file size.
242 uint64_t SizeOfImage = 0;
243 if (mod->GetObjectFile()->CalculateType() == ObjectFile::Type::eTypeJIT) {
244 for (const auto &section : *mod->GetObjectFile()->GetSectionList()) {
245 SizeOfImage += section->GetByteSize();
246 }
247 return SizeOfImage;
248 }
249 SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();
250
251 if (!sect_sp) {
252 return llvm::createStringError(std::errc::operation_not_supported,
253 "Couldn't obtain the section information.");
254 }
255 lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
256 // Use memory size since zero fill sections, like ".bss", will be smaller on
257 // disk.
258 lldb::addr_t sect_size = sect_sp->GetByteSize();
259 // This will usually be zero, but make sure to calculate the BaseOfImage
260 // offset.
261 const lldb::addr_t base_sect_offset =
262 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
263 sect_addr;
264 SizeOfImage = sect_size - base_sect_offset;
265 lldb::addr_t next_sect_addr = sect_addr + sect_size;
266 Address sect_so_addr;
267 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
268 lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
269 while (next_sect_sp &&
270 next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
271 sect_size = sect_sp->GetByteSize();
272 SizeOfImage += sect_size;
273 next_sect_addr += sect_size;
274 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
275 next_sect_sp = sect_so_addr.GetSection();
276 }
277
278 return SizeOfImage;
279}
280
281// ModuleList stream consists of a number of modules, followed by an array
282// of llvm::minidump::Module's structures. Every structure informs about a
283// single module. Additional data of variable length, such as module's names,
284// are stored just after the ModuleList stream. The llvm::minidump::Module
285// structures point to this helper data by global offset.
287 constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
289
290 lldb_private::Target &target = m_process_sp->GetTarget();
291 const ModuleList &modules = target.GetImages();
292 llvm::support::ulittle32_t modules_count =
293 static_cast<llvm::support::ulittle32_t>(modules.GetSize());
294
295 // This helps us with getting the correct global offset in minidump
296 // file later, when we will be setting up offsets from the
297 // the llvm::minidump::Module's structures into helper data
298 size_t size_before = GetCurrentDataEndOffset();
299
300 // This is the size of the main part of the ModuleList stream.
301 // It consists of a module number and corresponding number of
302 // structs describing individual modules
303 size_t module_stream_size =
304 sizeof(llvm::support::ulittle32_t) + modules_count * minidump_module_size;
305
306 // Adding directory describing this stream.
307 error = AddDirectory(StreamType::ModuleList, module_stream_size);
308 if (error.Fail())
309 return error;
310
311 m_data.AppendData(&modules_count, sizeof(llvm::support::ulittle32_t));
312
313 // Temporary storage for the helper data (of variable length)
314 // as these cannot be dumped to m_data before dumping entire
315 // array of module structures.
316 DataBufferHeap helper_data;
317
318 for (size_t i = 0; i < modules_count; ++i) {
319 ModuleSP mod = modules.GetModuleAtIndex(i);
320 std::string module_name = mod->GetSpecificationDescription();
321 auto maybe_mod_size = getModuleFileSize(target, mod);
322 if (!maybe_mod_size) {
323 llvm::Error mod_size_err = maybe_mod_size.takeError();
324 llvm::handleAllErrors(std::move(mod_size_err),
325 [&](const llvm::ErrorInfoBase &E) {
326 error.SetErrorStringWithFormat(
327 "Unable to get the size of module %s: %s.",
328 module_name.c_str(), E.message().c_str());
329 });
330 return error;
331 }
332
333 uint64_t mod_size = std::move(*maybe_mod_size);
334
335 llvm::support::ulittle32_t signature =
336 static_cast<llvm::support::ulittle32_t>(
337 static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
338 auto uuid = mod->GetUUID().GetBytes();
339
340 VSFixedFileInfo info;
341 info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
342 info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
343 info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
344 info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
345 info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
346 info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
347 info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
348 info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
349 info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
350 info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
351 info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
352 info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
353 info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);
354
355 LocationDescriptor ld;
356 ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
357 ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);
358
359 // Setting up LocationDescriptor for uuid string. The global offset into
360 // minidump file is calculated.
361 LocationDescriptor ld_cv;
362 ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
363 sizeof(llvm::support::ulittle32_t) + uuid.size());
364 ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
365 size_before + module_stream_size + helper_data.GetByteSize());
366
367 helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
368 helper_data.AppendData(uuid.begin(), uuid.size());
369
370 llvm::minidump::Module m;
371 m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
372 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
373 m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size);
374 m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
375 m.TimeDateStamp =
376 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
377 m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
378 size_before + module_stream_size + helper_data.GetByteSize());
379 m.VersionInfo = info;
380 m.CvRecord = ld_cv;
381 m.MiscRecord = ld;
382
383 error = WriteString(module_name, &helper_data);
384
385 if (error.Fail())
386 return error;
387
388 m_data.AppendData(&m, sizeof(llvm::minidump::Module));
389 }
390
391 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
392 return error;
393}
394
396 llvm::StringRef reg_name) {
397 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
398 if (!reg_info)
399 return 0;
401 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
402 if (!success)
403 return 0;
404 return reg_value.GetAsUInt16();
405}
406
408 llvm::StringRef reg_name) {
409 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
410 if (!reg_info)
411 return 0;
413 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
414 if (!success)
415 return 0;
416 return reg_value.GetAsUInt32();
417}
418
420 llvm::StringRef reg_name) {
421 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
422 if (!reg_info)
423 return 0;
425 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
426 if (!success)
427 return 0;
428 return reg_value.GetAsUInt64();
429}
430
431llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
432 llvm::StringRef reg_name) {
433 return static_cast<llvm::support::ulittle16_t>(
434 read_register_u16_raw(reg_ctx, reg_name));
435}
436
437llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
438 llvm::StringRef reg_name) {
439 return static_cast<llvm::support::ulittle32_t>(
440 read_register_u32_raw(reg_ctx, reg_name));
441}
442
443llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
444 llvm::StringRef reg_name) {
445 return static_cast<llvm::support::ulittle64_t>(
446 read_register_u64_raw(reg_ctx, reg_name));
447}
448
449void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name,
450 uint8_t *dst) {
451 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
452 if (reg_info) {
454 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
456 uint32_t bytes_copied = reg_value.GetAsMemoryData(
457 *reg_info, dst, 16, lldb::ByteOrder::eByteOrderLittle, error);
458 if (bytes_copied == 16)
459 return;
460 }
461 }
462 // If anything goes wrong, then zero out the register value.
463 memset(dst, 0, 16);
464}
465
469 thread_context.p1_home = {};
470 thread_context.context_flags = static_cast<uint32_t>(
475 thread_context.rax = read_register_u64(reg_ctx, "rax");
476 thread_context.rbx = read_register_u64(reg_ctx, "rbx");
477 thread_context.rcx = read_register_u64(reg_ctx, "rcx");
478 thread_context.rdx = read_register_u64(reg_ctx, "rdx");
479 thread_context.rdi = read_register_u64(reg_ctx, "rdi");
480 thread_context.rsi = read_register_u64(reg_ctx, "rsi");
481 thread_context.rbp = read_register_u64(reg_ctx, "rbp");
482 thread_context.rsp = read_register_u64(reg_ctx, "rsp");
483 thread_context.r8 = read_register_u64(reg_ctx, "r8");
484 thread_context.r9 = read_register_u64(reg_ctx, "r9");
485 thread_context.r10 = read_register_u64(reg_ctx, "r10");
486 thread_context.r11 = read_register_u64(reg_ctx, "r11");
487 thread_context.r12 = read_register_u64(reg_ctx, "r12");
488 thread_context.r13 = read_register_u64(reg_ctx, "r13");
489 thread_context.r14 = read_register_u64(reg_ctx, "r14");
490 thread_context.r15 = read_register_u64(reg_ctx, "r15");
491 thread_context.rip = read_register_u64(reg_ctx, "rip");
492 thread_context.eflags = read_register_u32(reg_ctx, "rflags");
493 thread_context.cs = read_register_u16(reg_ctx, "cs");
494 thread_context.fs = read_register_u16(reg_ctx, "fs");
495 thread_context.gs = read_register_u16(reg_ctx, "gs");
496 thread_context.ss = read_register_u16(reg_ctx, "ss");
497 thread_context.ds = read_register_u16(reg_ctx, "ds");
498 return thread_context;
499}
500
504 thread_context.context_flags = static_cast<uint32_t>(
505 minidump::RegisterContextMinidump_ARM64::Flags::ARM64_Flag |
506 minidump::RegisterContextMinidump_ARM64::Flags::Integer |
507 minidump::RegisterContextMinidump_ARM64::Flags::FloatingPoint);
508 char reg_name[16];
509 for (uint32_t i = 0; i < 31; ++i) {
510 snprintf(reg_name, sizeof(reg_name), "x%u", i);
511 thread_context.x[i] = read_register_u64(reg_ctx, reg_name);
512 }
513 // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
514 // name set to "x31"
515 thread_context.x[31] = read_register_u64(reg_ctx, "sp");
516 thread_context.pc = read_register_u64(reg_ctx, "pc");
517 thread_context.cpsr = read_register_u32(reg_ctx, "cpsr");
518 thread_context.fpsr = read_register_u32(reg_ctx, "fpsr");
519 thread_context.fpcr = read_register_u32(reg_ctx, "fpcr");
520 for (uint32_t i = 0; i < 32; ++i) {
521 snprintf(reg_name, sizeof(reg_name), "v%u", i);
522 read_register_u128(reg_ctx, reg_name, &thread_context.v[i * 16]);
523 }
524 return thread_context;
525}
526
528 llvm::Triple::ArchType m_arch;
529 union {
532 };
533
534public:
535 ArchThreadContexts(llvm::Triple::ArchType arch) : m_arch(arch) {}
536
538 switch (m_arch) {
539 case llvm::Triple::ArchType::x86_64:
541 return true;
542 case llvm::Triple::ArchType::aarch64:
543 arm64 = GetThreadContext_ARM64(reg_ctx);
544 return true;
545 default:
546 break;
547 }
548 return false;
549 }
550
551 const void *data() const { return &x86_64; }
552
553 size_t size() const {
554 switch (m_arch) {
555 case llvm::Triple::ArchType::x86_64:
556 return sizeof(x86_64);
557 case llvm::Triple::ArchType::aarch64:
558 return sizeof(arm64);
559 default:
560 break;
561 }
562 return 0;
563 }
564};
565
568 // If we have anything in the heap flush it.
570 m_core_file->SeekFromStart(m_thread_list_start);
571 for (auto &pair : m_thread_by_range_end) {
572 // The thread objects will get a new memory descriptor added
573 // When we are emitting the memory list and then we write it here
574 const llvm::minidump::Thread &thread = pair.second;
575 size_t bytes_to_write = sizeof(llvm::minidump::Thread);
576 size_t bytes_written = bytes_to_write;
577 error = m_core_file->Write(&thread, bytes_written);
578 if (error.Fail() || bytes_to_write != bytes_written) {
579 error.SetErrorStringWithFormat(
580 "Wrote incorrect number of bytes to minidump file. (written %zd/%zd)",
581 bytes_written, bytes_to_write);
582 return error;
583 }
584 }
585
586 return error;
587}
588
590 constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
591 lldb_private::ThreadList thread_list = m_process_sp->GetThreadList();
592
593 // size of the entire thread stream consists of:
594 // number of threads and threads array
595 size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
596 thread_list.GetSize() * minidump_thread_size;
597 // save for the ability to set up RVA
598 size_t size_before = GetCurrentDataEndOffset();
600 error = AddDirectory(StreamType::ThreadList, thread_stream_size);
601 if (error.Fail())
602 return error;
603
604 llvm::support::ulittle32_t thread_count =
605 static_cast<llvm::support::ulittle32_t>(thread_list.GetSize());
606 m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));
607
608 // Take the offset after the thread count.
610 DataBufferHeap helper_data;
611
612 const uint32_t num_threads = thread_list.GetSize();
613 Log *log = GetLog(LLDBLog::Object);
614 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
615 ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
616 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
617
618 if (!reg_ctx_sp) {
619 error.SetErrorString("Unable to get the register context.");
620 return error;
621 }
622 RegisterContext *reg_ctx = reg_ctx_sp.get();
623 Target &target = m_process_sp->GetTarget();
624 const ArchSpec &arch = target.GetArchitecture();
625 ArchThreadContexts thread_context(arch.GetMachine());
626 if (!thread_context.prepareRegisterContext(reg_ctx)) {
627 error.SetErrorStringWithFormat(
628 "architecture %s not supported.",
629 arch.GetTriple().getArchName().str().c_str());
630 return error;
631 }
632
633 uint64_t sp = reg_ctx->GetSP();
634 MemoryRegionInfo sp_region;
635 m_process_sp->GetMemoryRegionInfo(sp, sp_region);
636
637 // Emit a blank descriptor
638 MemoryDescriptor stack;
639 LocationDescriptor empty_label;
640 empty_label.DataSize = 0;
641 empty_label.RVA = 0;
642 stack.Memory = empty_label;
643 stack.StartOfMemoryRange = 0;
644 LocationDescriptor thread_context_memory_locator;
645 thread_context_memory_locator.DataSize =
646 static_cast<llvm::support::ulittle32_t>(thread_context.size());
647 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
648 size_before + thread_stream_size + helper_data.GetByteSize());
649 // Cache thie thread context memory so we can reuse for exceptions.
650 m_tid_to_reg_ctx[thread_sp->GetID()] = thread_context_memory_locator;
651
652 LLDB_LOGF(log, "AddThreadList for thread %d: thread_context %zu bytes",
653 thread_idx, thread_context.size());
654 helper_data.AppendData(thread_context.data(), thread_context.size());
655
656 llvm::minidump::Thread t;
657 t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
658 t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
659 (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
660 t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
661 t.Priority = static_cast<llvm::support::ulittle32_t>(0);
662 t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
663 t.Stack = stack, t.Context = thread_context_memory_locator;
664
665 // We save off the stack object so we can circle back and clean it up.
666 m_thread_by_range_end[sp_region.GetRange().GetRangeEnd()] = t;
667 m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
668 }
669
670 LLDB_LOGF(log, "AddThreadList(): total helper_data %" PRIx64 " bytes",
671 helper_data.GetByteSize());
672 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
673 return Status();
674}
675
677 lldb_private::ThreadList thread_list = m_process_sp->GetThreadList();
679 const uint32_t num_threads = thread_list.GetSize();
680 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
681 ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
682 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
683 bool add_exception = false;
684 if (stop_info_sp) {
685 switch (stop_info_sp->GetStopReason()) {
688 add_exception = true;
689 break;
690 default:
691 break;
692 }
693 }
694 if (add_exception) {
695 constexpr size_t minidump_exception_size =
696 sizeof(llvm::minidump::ExceptionStream);
697 error = AddDirectory(StreamType::Exception, minidump_exception_size);
698 if (error.Fail())
699 return error;
700
701 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
702 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
703 Exception exp_record = {};
704 exp_record.ExceptionCode =
705 static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
706 exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0);
707 exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
708 exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
709 exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0);
710 exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
711 // exp_record.ExceptionInformation;
712
713 ExceptionStream exp_stream;
714 exp_stream.ThreadId =
715 static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
716 exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
717 exp_stream.ExceptionRecord = exp_record;
718 auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
719 if (Iter != m_tid_to_reg_ctx.end()) {
720 exp_stream.ThreadContext = Iter->second;
721 } else {
722 exp_stream.ThreadContext.DataSize = 0;
723 exp_stream.ThreadContext.RVA = 0;
724 }
725 m_data.AppendData(&exp_stream, minidump_exception_size);
726 }
727 }
728
729 return error;
730}
731
734 error = AddDirectory(StreamType::MiscInfo,
736 if (error.Fail())
737 return error;
738
740 misc_info.size = static_cast<llvm::support::ulittle32_t>(
742 // Default set flags1 to 0, in case that we will not be able to
743 // get any information
744 misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);
745
747 m_process_sp->GetProcessInfo(process_info);
748 if (process_info.ProcessIDIsValid()) {
749 // Set flags1 to reflect that PID is filled in
750 misc_info.flags1 =
751 static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
753 misc_info.process_id =
754 static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
755 }
756
757 m_data.AppendData(&misc_info,
759 return error;
760}
761
762std::unique_ptr<llvm::MemoryBuffer>
763getFileStreamHelper(const std::string &path) {
764 auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
765 if (!maybe_stream)
766 return nullptr;
767 return std::move(maybe_stream.get());
768}
769
772 // No-op if we are not on linux.
773 if (m_process_sp->GetTarget().GetArchitecture().GetTriple().getOS() !=
774 llvm::Triple::Linux)
775 return error;
776
777 std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
778 {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
779 {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
780 };
781
783 m_process_sp->GetProcessInfo(process_info);
784 if (process_info.ProcessIDIsValid()) {
785 lldb::pid_t pid = process_info.GetProcessID();
786 std::string pid_str = std::to_string(pid);
787 files_with_stream_types.push_back(
788 {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
789 files_with_stream_types.push_back(
790 {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
791 files_with_stream_types.push_back(
792 {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
793 files_with_stream_types.push_back(
794 {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
795 files_with_stream_types.push_back(
796 {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
797 files_with_stream_types.push_back(
798 {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
799 files_with_stream_types.push_back(
800 {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
801 }
802
803 for (const auto &entry : files_with_stream_types) {
804 StreamType stream = entry.first;
805 std::string path = entry.second;
806 auto memory_buffer = getFileStreamHelper(path);
807
808 if (memory_buffer) {
809 size_t size = memory_buffer->getBufferSize();
810 if (size == 0)
811 continue;
812 error = AddDirectory(stream, size);
813 if (error.Fail())
814 return error;
815 m_data.AppendData(memory_buffer->getBufferStart(), size);
816 }
817 }
818
819 return error;
820}
821
824
825 // We first save the thread stacks to ensure they fit in the first UINT32_MAX
826 // bytes of the core file. Thread structures in minidump files can only use
827 // 32 bit memory descriptiors, so we emit them first to ensure the memory is
828 // in accessible with a 32 bit offset.
831 error = m_process_sp->CalculateCoreFileSaveRanges(
832 SaveCoreStyle::eSaveCoreStackOnly, ranges_32);
833 if (error.Fail())
834 return error;
835
836 // Calculate totalsize including the current offset.
837 uint64_t total_size = GetCurrentDataEndOffset();
838 total_size += ranges_32.size() * sizeof(llvm::minidump::MemoryDescriptor);
839 std::unordered_set<addr_t> stack_start_addresses;
840 for (const auto &core_range : ranges_32) {
841 stack_start_addresses.insert(core_range.range.start());
842 total_size += core_range.range.size();
843 }
844
845 if (total_size >= UINT32_MAX) {
846 error.SetErrorStringWithFormat("Unable to write minidump. Stack memory "
847 "exceeds 32b limit. (Num Stacks %zu)",
848 ranges_32.size());
849 return error;
850 }
851
852 Process::CoreFileMemoryRanges all_core_memory_ranges;
853 if (core_style != SaveCoreStyle::eSaveCoreStackOnly) {
854 error = m_process_sp->CalculateCoreFileSaveRanges(core_style,
855 all_core_memory_ranges);
856 if (error.Fail())
857 return error;
858 }
859
860 // After saving the stacks, we start packing as much as we can into 32b.
861 // We apply a generous padding here so that the Directory, MemoryList and
862 // Memory64List sections all begin in 32b addressable space.
863 // Then anything overflow extends into 64b addressable space.
864 // All core memeroy ranges will either container nothing on stacks only
865 // or all the memory ranges including stacks
866 if (!all_core_memory_ranges.empty())
867 total_size +=
868 256 + (all_core_memory_ranges.size() - stack_start_addresses.size()) *
869 sizeof(llvm::minidump::MemoryDescriptor_64);
870
871 for (const auto &core_range : all_core_memory_ranges) {
872 const addr_t range_size = core_range.range.size();
873 if (stack_start_addresses.count(core_range.range.start()) > 0)
874 // Don't double save stacks.
875 continue;
876
877 if (total_size + range_size < UINT32_MAX) {
878 ranges_32.push_back(core_range);
879 total_size += range_size;
880 } else {
881 ranges_64.push_back(core_range);
882 }
883 }
884
885 error = AddMemoryList_32(ranges_32);
886 if (error.Fail())
887 return error;
888
889 // Add the remaining memory as a 64b range.
890 if (!ranges_64.empty()) {
891 error = AddMemoryList_64(ranges_64);
892 if (error.Fail())
893 return error;
894 }
895
896 return FixThreadStacks();
897}
898
900 // write header
901 llvm::minidump::Header header;
902 header.Signature = static_cast<llvm::support::ulittle32_t>(
903 llvm::minidump::Header::MagicSignature);
904 header.Version = static_cast<llvm::support::ulittle32_t>(
905 llvm::minidump::Header::MagicVersion);
906 header.NumberOfStreams =
907 static_cast<llvm::support::ulittle32_t>(m_directories.size());
908 // We write the directories right after the header.
909 header.StreamDirectoryRVA =
910 static_cast<llvm::support::ulittle32_t>(HEADER_SIZE);
911 header.Checksum = static_cast<llvm::support::ulittle32_t>(
912 0u), // not used in most of the writers
913 header.TimeDateStamp =
914 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
915 header.Flags =
916 static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag
917
919 size_t bytes_written;
920
921 m_core_file->SeekFromStart(0);
922 bytes_written = HEADER_SIZE;
923 error = m_core_file->Write(&header, bytes_written);
924 if (error.Fail() || bytes_written != HEADER_SIZE) {
925 if (bytes_written != HEADER_SIZE)
926 error.SetErrorStringWithFormat(
927 "Unable to write the minidump header (written %zd/%zd)",
928 bytes_written, HEADER_SIZE);
929 return error;
930 }
931 return error;
932}
933
936}
937
940 size_t bytes_written;
941 m_core_file->SeekFromStart(HEADER_SIZE);
942 for (const Directory &dir : m_directories) {
943 bytes_written = DIRECTORY_SIZE;
944 error = m_core_file->Write(&dir, bytes_written);
945 if (error.Fail() || bytes_written != DIRECTORY_SIZE) {
946 if (bytes_written != DIRECTORY_SIZE)
947 error.SetErrorStringWithFormat(
948 "unable to write the directory (written %zd/%zd)", bytes_written,
950 return error;
951 }
952 }
953
954 return error;
955}
956
957static uint64_t
959 uint64_t max_size = 0;
960 for (const auto &core_range : ranges)
961 max_size = std::max(max_size, core_range.range.size());
962 return max_size;
963}
964
965Status
967 std::vector<MemoryDescriptor> descriptors;
969 if (ranges.size() == 0)
970 return error;
971
972 Log *log = GetLog(LLDBLog::Object);
973 size_t region_index = 0;
974 auto data_up =
975 std::make_unique<DataBufferHeap>(GetLargestRangeSize(ranges), 0);
976 for (const auto &core_range : ranges) {
977 // Take the offset before we write.
978 const offset_t offset_for_data = GetCurrentDataEndOffset();
979 const addr_t addr = core_range.range.start();
980 const addr_t size = core_range.range.size();
981 const addr_t end = core_range.range.end();
982
983 LLDB_LOGF(log,
984 "AddMemoryList %zu/%zu reading memory for region "
985 "(%" PRIx64 " bytes) [%" PRIx64 ", %" PRIx64 ")",
986 region_index, ranges.size(), size, addr, addr + size);
987 ++region_index;
988
989 const size_t bytes_read =
990 m_process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
991 if (error.Fail() || bytes_read == 0) {
992 LLDB_LOGF(log, "Failed to read memory region. Bytes read: %zu, error: %s",
993 bytes_read, error.AsCString());
994 // Just skip sections with errors or zero bytes in 32b mode
995 continue;
996 } else if (bytes_read != size) {
997 LLDB_LOGF(
998 log, "Memory region at: %" PRIx64 " failed to read %" PRIx64 " bytes",
999 addr, size);
1000 }
1001
1002 MemoryDescriptor descriptor;
1003 descriptor.StartOfMemoryRange =
1004 static_cast<llvm::support::ulittle64_t>(addr);
1005 descriptor.Memory.DataSize =
1006 static_cast<llvm::support::ulittle32_t>(bytes_read);
1007 descriptor.Memory.RVA =
1008 static_cast<llvm::support::ulittle32_t>(offset_for_data);
1009 descriptors.push_back(descriptor);
1010 if (m_thread_by_range_end.count(end) > 0)
1011 m_thread_by_range_end[end].Stack = descriptor;
1012
1013 // Add the data to the buffer, flush as needed.
1014 error = AddData(data_up->GetBytes(), bytes_read);
1015 if (error.Fail())
1016 return error;
1017 }
1018
1019 // Add a directory that references this list
1020 // With a size of the number of ranges as a 32 bit num
1021 // And then the size of all the ranges
1022 error = AddDirectory(StreamType::MemoryList,
1023 sizeof(llvm::support::ulittle32_t) +
1024 descriptors.size() *
1025 sizeof(llvm::minidump::MemoryDescriptor));
1026 if (error.Fail())
1027 return error;
1028
1029 llvm::support::ulittle32_t memory_ranges_num =
1030 static_cast<llvm::support::ulittle32_t>(descriptors.size());
1031 m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle32_t));
1032 // For 32b we can get away with writing off the descriptors after the data.
1033 // This means no cleanup loop needed.
1034 m_data.AppendData(descriptors.data(),
1035 descriptors.size() * sizeof(MemoryDescriptor));
1036
1037 return error;
1038}
1039
1040Status
1042 Status error;
1043 if (ranges.empty())
1044 return error;
1045
1046 error = AddDirectory(StreamType::Memory64List,
1047 (sizeof(llvm::support::ulittle64_t) * 2) +
1048 ranges.size() *
1049 sizeof(llvm::minidump::MemoryDescriptor_64));
1050 if (error.Fail())
1051 return error;
1052
1053 llvm::support::ulittle64_t memory_ranges_num =
1054 static_cast<llvm::support::ulittle64_t>(ranges.size());
1055 m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle64_t));
1056 // Capture the starting offset for all the descriptors so we can clean them up
1057 // if needed.
1058 offset_t starting_offset =
1059 GetCurrentDataEndOffset() + sizeof(llvm::support::ulittle64_t);
1060 // The base_rva needs to start after the directories, which is right after
1061 // this 8 byte variable.
1062 offset_t base_rva =
1063 starting_offset +
1064 (ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64));
1065 llvm::support::ulittle64_t memory_ranges_base_rva =
1066 static_cast<llvm::support::ulittle64_t>(base_rva);
1067 m_data.AppendData(&memory_ranges_base_rva,
1068 sizeof(llvm::support::ulittle64_t));
1069
1070 bool cleanup_required = false;
1071 std::vector<MemoryDescriptor_64> descriptors;
1072 // Enumerate the ranges and create the memory descriptors so we can append
1073 // them first
1074 for (const auto core_range : ranges) {
1075 // Add the space required to store the memory descriptor
1076 MemoryDescriptor_64 memory_desc;
1077 memory_desc.StartOfMemoryRange =
1078 static_cast<llvm::support::ulittle64_t>(core_range.range.start());
1079 memory_desc.DataSize =
1080 static_cast<llvm::support::ulittle64_t>(core_range.range.size());
1081 descriptors.push_back(memory_desc);
1082 // Now write this memory descriptor to the buffer.
1083 m_data.AppendData(&memory_desc, sizeof(MemoryDescriptor_64));
1084 }
1085
1086 Log *log = GetLog(LLDBLog::Object);
1087 size_t region_index = 0;
1088 auto data_up =
1089 std::make_unique<DataBufferHeap>(GetLargestRangeSize(ranges), 0);
1090 for (const auto &core_range : ranges) {
1091 const addr_t addr = core_range.range.start();
1092 const addr_t size = core_range.range.size();
1093
1094 LLDB_LOGF(log,
1095 "AddMemoryList_64 %zu/%zu reading memory for region "
1096 "(%" PRIx64 "bytes) "
1097 "[%" PRIx64 ", %" PRIx64 ")",
1098 region_index, ranges.size(), size, addr, addr + size);
1099 ++region_index;
1100
1101 const size_t bytes_read =
1102 m_process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
1103 if (error.Fail()) {
1104 LLDB_LOGF(log, "Failed to read memory region. Bytes read: %zu, error: %s",
1105 bytes_read, error.AsCString());
1106 error.Clear();
1107 cleanup_required = true;
1108 descriptors[region_index].DataSize = 0;
1109 }
1110 if (bytes_read != size) {
1111 LLDB_LOGF(
1112 log, "Memory region at: %" PRIx64 " failed to read %" PRIx64 " bytes",
1113 addr, size);
1114 cleanup_required = true;
1115 descriptors[region_index].DataSize = bytes_read;
1116 }
1117
1118 // Add the data to the buffer, flush as needed.
1119 error = AddData(data_up->GetBytes(), bytes_read);
1120 if (error.Fail())
1121 return error;
1122 }
1123
1124 // Early return if there is no cleanup needed.
1125 if (!cleanup_required) {
1126 return error;
1127 } else {
1128 // Flush to disk we can make the fixes in place.
1130 // Fixup the descriptors that were not read correctly.
1131 m_core_file->SeekFromStart(starting_offset);
1132 size_t bytes_written = sizeof(MemoryDescriptor_64) * descriptors.size();
1133 error = m_core_file->Write(descriptors.data(), bytes_written);
1134 if (error.Fail() ||
1135 bytes_written != sizeof(MemoryDescriptor_64) * descriptors.size()) {
1136 error.SetErrorStringWithFormat(
1137 "unable to write the memory descriptors (written %zd/%zd)",
1138 bytes_written, sizeof(MemoryDescriptor_64) * descriptors.size());
1139 }
1140
1141 return error;
1142 }
1143}
1144
1145Status MinidumpFileBuilder::AddData(const void *data, uint64_t size) {
1146 // This should also get chunked, because worst case we copy over a big
1147 // object / memory range, say 5gb. In that case, we'd have to allocate 10gb
1148 // 5 gb for the buffer we're copying from, and then 5gb for the buffer we're
1149 // copying to. Which will be short lived and immedaitely go to disk, the goal
1150 // here is to limit the number of bytes we need to host in memory at any given
1151 // time.
1152 m_data.AppendData(data, size);
1154 return FlushBufferToDisk();
1155
1156 return Status();
1157}
1158
1160 Status error;
1161 // Set the stream to it's end.
1162 m_core_file->SeekFromStart(m_saved_data_size);
1163 addr_t starting_size = m_data.GetByteSize();
1164 addr_t remaining_bytes = starting_size;
1165 offset_t offset = 0;
1166
1167 while (remaining_bytes > 0) {
1168 size_t bytes_written = remaining_bytes;
1169 // We don't care how many bytes we wrote unless we got an error
1170 // so just decrement the remaining bytes.
1171 error = m_core_file->Write(m_data.GetBytes() + offset, bytes_written);
1172 if (error.Fail()) {
1173 error.SetErrorStringWithFormat(
1174 "Wrote incorrect number of bytes to minidump file. (written %" PRIx64
1175 "/%" PRIx64 ")",
1176 starting_size - remaining_bytes, starting_size);
1177 return error;
1178 }
1179
1180 offset += bytes_written;
1181 remaining_bytes -= bytes_written;
1182 }
1183
1184 m_saved_data_size += starting_size;
1185 m_data.Clear();
1186 return error;
1187}
1188
1190 Status error;
1191 // If anything is left unsaved, dump it.
1193 if (error.Fail())
1194 return error;
1195
1196 // Overwrite the header which we filled in earlier.
1197 error = DumpHeader();
1198 if (error.Fail())
1199 return error;
1200
1201 // Overwrite the space saved for directories
1203 if (error.Fail())
1204 return error;
1205
1206 return error;
1207}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:366
llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, llvm::StringRef reg_name)
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)
static uint64_t GetLargestRangeSize(const Process::CoreFileMemoryRanges &ranges)
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
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 AddMemoryList_64(lldb_private::Process::CoreFileMemoryRanges &ranges)
lldb_private::Status AddExceptions()
std::unordered_map< lldb::tid_t, llvm::minidump::LocationDescriptor > m_tid_to_reg_ctx
lldb_private::Status AddThreadList()
lldb_private::Status AddHeaderAndCalculateDirectories()
static constexpr size_t DIRECTORY_SIZE
lldb_private::Status AddMemoryList(lldb::SaveCoreStyle core_style)
lldb_private::DataBufferHeap m_data
lldb_private::Status AddSystemInfo()
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::Status FlushBufferToDisk()
lldb::offset_t m_thread_list_start
static constexpr size_t MAX_WRITE_CHUNK_SIZE
lldb_private::Status AddDirectory(llvm::minidump::StreamType type, uint64_t stream_size)
lldb_private::Status FixThreadStacks()
lldb::ProcessSP m_process_sp
lldb_private::Status AddMemoryList_32(lldb_private::Process::CoreFileMemoryRanges &ranges)
static constexpr size_t HEADER_SIZE
lldb::offset_t GetCurrentDataEndOffset() const
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
A section + offset based address class.
Definition: Address.h:62
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition: Address.h:439
An architecture specification class.
Definition: ArchSpec.h:31
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:683
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:103
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
Definition: ModuleList.cpp:429
size_t GetSize() const
Gets the size of the module list.
Definition: ModuleList.cpp:638
bool ProcessIDIsValid() const
Definition: ProcessInfo.h:72
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
std::vector< CoreFileMemoryRange > CoreFileMemoryRanges
Definition: Process.h:736
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:44
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:3104
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:981
const ArchSpec & GetArchitecture() const
Definition: Target.h:1023
uint32_t GetSize(bool can_update=true)
Definition: ThreadList.cpp:82
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
Definition: ThreadList.cpp:90
uint8_t * GetBytes()
Get a pointer to the data.
Definition: DataBuffer.h:108
#define UINT32_MAX
Definition: lldb-defines.h:19
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:331
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::Thread > ThreadSP
Definition: lldb-forward.h:445
uint64_t offset_t
Definition: lldb-types.h:85
uint64_t pid_t
Definition: lldb-types.h:83
@ eByteOrderLittle
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
Definition: lldb-forward.h:426
std::shared_ptr< lldb_private::Section > SectionSP
Definition: lldb-forward.h:413
uint64_t addr_t
Definition: lldb-types.h:80
StopReason
Thread stop reasons.
@ eStopReasonException
@ eStopReasonSignal
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:391
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:370
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
Definition: MinidumpTypes.h:79
llvm::support::ulittle32_t flags1
Definition: MinidumpTypes.h:78
llvm::support::ulittle32_t size
Definition: MinidumpTypes.h:76