[Go to site: main page, start]

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 default:
202 "OS %s not supported.", target_triple.getOSName().str().c_str());
203 return error;
204 };
205
206 llvm::minidump::SystemInfo sys_info{};
207 sys_info.ProcessorArch =
208 static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
209 // Global offset to beginning of a csd_string in a data section
210 sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
211 GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
212 sys_info.PlatformId = platform_id;
213 m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));
214
215 std::string csd_string;
216
217 error = WriteString(csd_string, &m_data);
218 if (error.Fail()) {
219 error =
220 Status::FromErrorString("Unable to convert the csd string to UTF16.");
221 return error;
222 }
223
224 return error;
225}
226
227Status WriteString(const std::string &to_write,
230 // let the StringRef eat also null termination char
231 llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
232 llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;
233
234 bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
235 if (!converted) {
237 "Unable to convert the string to UTF16. Failed to convert %s",
238 to_write.c_str());
239 return error;
240 }
241
242 // size of the UTF16 string should be written without the null termination
243 // character that is stored in 2 bytes
244 llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);
245
246 buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
247 buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());
248
249 return error;
250}
251
252llvm::Expected<uint64_t> getModuleFileSize(Target &target,
253 const ModuleSP &mod) {
254 // JIT module has the same vm and file size.
255 uint64_t SizeOfImage = 0;
256 if (mod->GetObjectFile()->CalculateType() == ObjectFile::Type::eTypeJIT) {
257 for (const auto &section : *mod->GetObjectFile()->GetSectionList()) {
258 SizeOfImage += section->GetByteSize();
259 }
260 return SizeOfImage;
261 }
262 SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();
263
264 if (!sect_sp) {
265 return llvm::createStringError(std::errc::operation_not_supported,
266 "Couldn't obtain the section information.");
267 }
268 lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
269 // Use memory size since zero fill sections, like ".bss", will be smaller on
270 // disk.
271 lldb::addr_t sect_size = sect_sp->GetByteSize();
272 // This will usually be zero, but make sure to calculate the BaseOfImage
273 // offset.
274 const lldb::addr_t base_sect_offset =
275 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
276 sect_addr;
277 SizeOfImage = sect_size - base_sect_offset;
278 lldb::addr_t next_sect_addr = sect_addr + sect_size;
279 Address sect_so_addr;
280 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
281 lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
282 while (next_sect_sp &&
283 next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
284 sect_size = next_sect_sp->GetByteSize();
285 SizeOfImage += sect_size;
286 next_sect_addr += sect_size;
287 target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
288 next_sect_sp = sect_so_addr.GetSection();
289 }
290
291 return SizeOfImage;
292}
293
294// ModuleList stream consists of a number of modules, followed by an array
295// of llvm::minidump::Module's structures. Every structure informs about a
296// single module. Additional data of variable length, such as module's names,
297// are stored just after the ModuleList stream. The llvm::minidump::Module
298// structures point to this helper data by global offset.
300 constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
302
303 lldb_private::Target &target = m_process_sp->GetTarget();
304 const ModuleList &modules = target.GetImages();
305 llvm::support::ulittle32_t modules_count =
306 static_cast<llvm::support::ulittle32_t>(modules.GetSize());
307
308 // This helps us with getting the correct global offset in minidump
309 // file later, when we will be setting up offsets from the
310 // the llvm::minidump::Module's structures into helper data
311 size_t size_before = GetCurrentDataEndOffset();
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 // Vector to store modules that pass validation.
319 std::vector<std::pair<ModuleSP, uint64_t>> valid_modules;
320
321 for (size_t i = 0; i < modules_count; ++i) {
322 ModuleSP mod = modules.GetModuleAtIndex(i);
323 std::string module_name = mod->GetSpecificationDescription();
324 auto maybe_mod_size = getModuleFileSize(target, mod);
325 if (!maybe_mod_size) {
326 llvm::Error mod_size_err = maybe_mod_size.takeError();
327 Log *log = GetLog(LLDBLog::Object);
328 llvm::handleAllErrors(
329 std::move(mod_size_err), [&](const llvm::ErrorInfoBase &E) {
330 LLDB_LOGF(log, "Unable to get the size of module %s: %s",
331 module_name.c_str(), E.message().c_str());
332 });
333 continue;
334 }
335 valid_modules.emplace_back(mod, *maybe_mod_size);
336 }
337
338 size_t module_stream_size = sizeof(llvm::support::ulittle32_t) +
339 valid_modules.size() * minidump_module_size;
340
341 error = AddDirectory(StreamType::ModuleList, module_stream_size);
342 if (error.Fail())
343 return error;
344
345 // Setting the header with the number of modules.
346 llvm::support::ulittle32_t count =
347 static_cast<llvm::support::ulittle32_t>(valid_modules.size());
348 m_data.AppendData(&count, sizeof(llvm::support::ulittle32_t));
349
350 for (const auto &valid_module : valid_modules) {
351 ModuleSP mod = valid_module.first;
352 uint64_t module_size = valid_module.second;
353 std::string module_name = mod->GetSpecificationDescription();
354
355 llvm::support::ulittle32_t signature =
356 static_cast<llvm::support::ulittle32_t>(
357 static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
358 auto uuid = mod->GetUUID().GetBytes();
359
360 VSFixedFileInfo info;
361 info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
362 info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
363 info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
364 info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
365 info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
366 info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
367 info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
368 info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
369 info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
370 info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
371 info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
372 info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
373 info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);
374
375 LocationDescriptor ld;
376 ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
377 ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);
378
379 // Setting up LocationDescriptor for uuid string. The global offset into
380 // minidump file is calculated.
381 LocationDescriptor ld_cv;
382 ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
383 sizeof(llvm::support::ulittle32_t) + uuid.size());
384 ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
385 size_before + module_stream_size + helper_data.GetByteSize());
386
387 helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
388 helper_data.AppendData(uuid.begin(), uuid.size());
389
390 llvm::minidump::Module m{};
391 m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
392 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
393 m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(module_size);
394 m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
395 m.TimeDateStamp =
396 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
397 m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
398 size_before + module_stream_size + helper_data.GetByteSize());
399 m.VersionInfo = info;
400 m.CvRecord = ld_cv;
401 m.MiscRecord = ld;
402
403 error = WriteString(module_name, &helper_data);
404
405 if (error.Fail())
406 return error;
407
408 m_data.AppendData(&m, sizeof(llvm::minidump::Module));
409 }
410
411 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
412 return error;
413}
414
416 llvm::StringRef reg_name) {
417 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
418 if (!reg_info)
419 return 0;
421 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
422 if (!success)
423 return 0;
424 return reg_value.GetAsUInt16();
425}
426
428 llvm::StringRef reg_name) {
429 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
430 if (!reg_info)
431 return 0;
433 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
434 if (!success)
435 return 0;
436 return reg_value.GetAsUInt32();
437}
438
440 llvm::StringRef reg_name) {
441 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
442 if (!reg_info)
443 return 0;
445 bool success = reg_ctx->ReadRegister(reg_info, reg_value);
446 if (!success)
447 return 0;
448 return reg_value.GetAsUInt64();
449}
450
451llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
452 llvm::StringRef reg_name) {
453 return static_cast<llvm::support::ulittle16_t>(
454 read_register_u16_raw(reg_ctx, reg_name));
455}
456
457llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
458 llvm::StringRef reg_name) {
459 return static_cast<llvm::support::ulittle32_t>(
460 read_register_u32_raw(reg_ctx, reg_name));
461}
462
463llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
464 llvm::StringRef reg_name) {
465 return static_cast<llvm::support::ulittle64_t>(
466 read_register_u64_raw(reg_ctx, reg_name));
467}
468
469void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name,
470 uint8_t *dst) {
471 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
472 if (reg_info) {
474 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
476 uint32_t bytes_copied = reg_value.GetAsMemoryData(
477 *reg_info, dst, 16, lldb::ByteOrder::eByteOrderLittle, error);
478 if (bytes_copied == 16)
479 return;
480 }
481 }
482 // If anything goes wrong, then zero out the register value.
483 memset(dst, 0, 16);
484}
485
489 thread_context.p1_home = {};
490 thread_context.context_flags = static_cast<uint32_t>(
496 thread_context.rax = read_register_u64(reg_ctx, "rax");
497 thread_context.rbx = read_register_u64(reg_ctx, "rbx");
498 thread_context.rcx = read_register_u64(reg_ctx, "rcx");
499 thread_context.rdx = read_register_u64(reg_ctx, "rdx");
500 thread_context.rdi = read_register_u64(reg_ctx, "rdi");
501 thread_context.rsi = read_register_u64(reg_ctx, "rsi");
502 thread_context.rbp = read_register_u64(reg_ctx, "rbp");
503 thread_context.rsp = read_register_u64(reg_ctx, "rsp");
504 thread_context.r8 = read_register_u64(reg_ctx, "r8");
505 thread_context.r9 = read_register_u64(reg_ctx, "r9");
506 thread_context.r10 = read_register_u64(reg_ctx, "r10");
507 thread_context.r11 = read_register_u64(reg_ctx, "r11");
508 thread_context.r12 = read_register_u64(reg_ctx, "r12");
509 thread_context.r13 = read_register_u64(reg_ctx, "r13");
510 thread_context.r14 = read_register_u64(reg_ctx, "r14");
511 thread_context.r15 = read_register_u64(reg_ctx, "r15");
512 thread_context.rip = read_register_u64(reg_ctx, "rip");
513 // To make our code agnostic to whatever type the register value identifies
514 // itself as, we read as a u64 and truncate to u32/u16 ourselves.
515 thread_context.eflags = read_register_u64(reg_ctx, "rflags");
516 thread_context.cs = read_register_u64(reg_ctx, "cs");
517 thread_context.fs = read_register_u64(reg_ctx, "fs");
518 thread_context.gs = read_register_u64(reg_ctx, "gs");
519 thread_context.ss = read_register_u64(reg_ctx, "ss");
520 thread_context.ds = read_register_u64(reg_ctx, "ds");
521 thread_context.fs_base = read_register_u64(reg_ctx, "fs_base");
522 thread_context.gs_base = read_register_u64(reg_ctx, "gs_base");
523 return thread_context;
524}
525
529 thread_context.context_flags = static_cast<uint32_t>(
533 char reg_name[16];
534 for (uint32_t i = 0; i < 31; ++i) {
535 snprintf(reg_name, sizeof(reg_name), "x%u", i);
536 thread_context.x[i] = read_register_u64(reg_ctx, reg_name);
537 }
538 // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
539 // name set to "x31"
540 thread_context.x[31] = read_register_u64(reg_ctx, "sp");
541 thread_context.pc = read_register_u64(reg_ctx, "pc");
542 thread_context.cpsr = read_register_u32(reg_ctx, "cpsr");
543 thread_context.fpsr = read_register_u32(reg_ctx, "fpsr");
544 thread_context.fpcr = read_register_u32(reg_ctx, "fpcr");
545 for (uint32_t i = 0; i < 32; ++i) {
546 snprintf(reg_name, sizeof(reg_name), "v%u", i);
547 read_register_u128(reg_ctx, reg_name, &thread_context.v[i * 16]);
548 }
549 return thread_context;
550}
551
553 llvm::Triple::ArchType m_arch;
554 union {
557 };
558
559public:
560 ArchThreadContexts(llvm::Triple::ArchType arch) : m_arch(arch) {}
561
563 switch (m_arch) {
564 case llvm::Triple::ArchType::x86_64:
566 return true;
567 case llvm::Triple::ArchType::aarch64:
568 arm64 = GetThreadContext_ARM64(reg_ctx);
569 return true;
570 default:
571 break;
572 }
573 return false;
574 }
575
576 const void *data() const { return &x86_64; }
577
578 size_t size() const {
579 switch (m_arch) {
580 case llvm::Triple::ArchType::x86_64:
581 return sizeof(x86_64);
582 case llvm::Triple::ArchType::aarch64:
583 return sizeof(arm64);
584 default:
585 break;
586 }
587 return 0;
588 }
589};
590
593 // If we have anything in the heap flush it.
595 m_core_file->SeekFromStart(m_thread_list_start);
596 for (auto &pair : m_thread_by_range_end) {
597 // The thread objects will get a new memory descriptor added
598 // When we are emitting the memory list and then we write it here
599 const llvm::minidump::Thread &thread = pair.second;
600 size_t bytes_to_write = sizeof(llvm::minidump::Thread);
601 size_t bytes_written = bytes_to_write;
602 error = m_core_file->Write(&thread, bytes_written);
603 if (error.Fail() || bytes_to_write != bytes_written) {
605 "Wrote incorrect number of bytes to minidump file. (written %zd/%zd)",
606 bytes_written, bytes_to_write);
607 return error;
608 }
609 }
610
611 return error;
612}
613
615 constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
616 std::vector<ThreadSP> thread_list =
617 m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
618
619 // size of the entire thread stream consists of:
620 // number of threads and threads array
621 size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
622 thread_list.size() * minidump_thread_size;
623 // save for the ability to set up RVA
624 size_t size_before = GetCurrentDataEndOffset();
626 error = AddDirectory(StreamType::ThreadList, thread_stream_size);
627 if (error.Fail())
628 return error;
629
630 llvm::support::ulittle32_t thread_count =
631 static_cast<llvm::support::ulittle32_t>(thread_list.size());
632 m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));
633
634 // Take the offset after the thread count.
636 DataBufferHeap helper_data;
637
638 Log *log = GetLog(LLDBLog::Object);
639 for (const ThreadSP &thread_sp : thread_list) {
640 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
641
642 if (!reg_ctx_sp) {
643 error = Status::FromErrorString("Unable to get the register context.");
644 return error;
645 }
646 RegisterContext *reg_ctx = reg_ctx_sp.get();
647 Target &target = m_process_sp->GetTarget();
648 const ArchSpec &arch = target.GetArchitecture();
649 ArchThreadContexts thread_context(arch.GetMachine());
650 if (!thread_context.prepareRegisterContext(reg_ctx)) {
652 "architecture %s not supported.",
653 arch.GetTriple().getArchName().str().c_str());
654 return error;
655 }
656
657 uint64_t sp = reg_ctx->GetSP();
658 MemoryRegionInfo sp_region;
659 m_process_sp->GetMemoryRegionInfo(sp, sp_region);
660
661 // Emit a blank descriptor
662 MemoryDescriptor stack;
663 LocationDescriptor empty_label;
664 empty_label.DataSize = 0;
665 empty_label.RVA = 0;
666 stack.Memory = empty_label;
667 stack.StartOfMemoryRange = 0;
668 LocationDescriptor thread_context_memory_locator;
669 thread_context_memory_locator.DataSize =
670 static_cast<llvm::support::ulittle32_t>(thread_context.size());
671 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
672 size_before + thread_stream_size + helper_data.GetByteSize());
673 // Cache thie thread context memory so we can reuse for exceptions.
674 m_tid_to_reg_ctx[thread_sp->GetID()] = thread_context_memory_locator;
675
676 LLDB_LOGF(log, "AddThreadList for thread %d: thread_context %zu bytes",
677 thread_sp->GetIndexID(), thread_context.size());
678 helper_data.AppendData(thread_context.data(), thread_context.size());
679
680 llvm::minidump::Thread t;
681 t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
682 t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
683 (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
684 t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
685 t.Priority = static_cast<llvm::support::ulittle32_t>(0);
686 t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
687 t.Stack = stack, t.Context = thread_context_memory_locator;
688
689 // We save off the stack object so we can circle back and clean it up.
690 m_thread_by_range_end[sp_region.GetRange().GetRangeEnd()] = t;
691 m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
692 }
693
694 LLDB_LOGF(log, "AddThreadList(): total helper_data %" PRIx64 " bytes",
695 helper_data.GetByteSize());
696 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
697 return Status();
698}
699
701 std::vector<ThreadSP> thread_list =
702 m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
704 for (const ThreadSP &thread_sp : thread_list) {
705 StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
706 // If we don't have a stop info, or if it's invalid, skip.
707 if (!stop_info_sp ||
708 stop_info_sp->GetStopReason() == lldb::eStopReasonInvalid)
709 continue;
710
711 constexpr size_t minidump_exception_size =
712 sizeof(llvm::minidump::ExceptionStream);
713 error = AddDirectory(StreamType::Exception, minidump_exception_size);
714 if (error.Fail())
715 return error;
716
717 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
718 Exception exp_record = {};
719 exp_record.ExceptionCode =
720 static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
721 exp_record.ExceptionFlags =
722 static_cast<llvm::support::ulittle32_t>(Exception::LLDB_FLAG);
723 exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
724 exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
725 exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(1);
726 std::string description = stop_info_sp->GetDescription();
727 // We have 120 bytes to work with and it's unlikely description will
728 // overflow, but we gotta check.
729 memcpy(&exp_record.ExceptionInformation, description.c_str(),
730 std::min(description.size(), Exception::MaxParameterBytes));
731 exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
732 ExceptionStream exp_stream;
733 exp_stream.ThreadId =
734 static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
735 exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
736 exp_stream.ExceptionRecord = exp_record;
737 auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
738 if (Iter != m_tid_to_reg_ctx.end()) {
739 exp_stream.ThreadContext = Iter->second;
740 } else {
741 exp_stream.ThreadContext.DataSize = 0;
742 exp_stream.ThreadContext.RVA = 0;
743 }
744 m_data.AppendData(&exp_stream, minidump_exception_size);
745 }
746
747 return error;
748}
749
752 error = AddDirectory(StreamType::MiscInfo,
754 if (error.Fail())
755 return error;
756
758 misc_info.size = static_cast<llvm::support::ulittle32_t>(
760 // Default set flags1 to 0, in case that we will not be able to
761 // get any information
762 misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);
763
765 m_process_sp->GetProcessInfo(process_info);
766 if (process_info.ProcessIDIsValid()) {
767 // Set flags1 to reflect that PID is filled in
768 misc_info.flags1 =
769 static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
771 misc_info.process_id =
772 static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
773 }
774
775 m_data.AppendData(&misc_info,
777 return error;
778}
779
780std::unique_ptr<llvm::MemoryBuffer>
781getFileStreamHelper(const std::string &path) {
782 auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
783 if (!maybe_stream)
784 return nullptr;
785 return std::move(maybe_stream.get());
786}
787
790 // No-op if we are not on linux.
791 if (m_process_sp->GetTarget().GetArchitecture().GetTriple().getOS() !=
792 llvm::Triple::Linux)
793 return error;
794
795 std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
796 {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
797 {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
798 };
799
801 m_process_sp->GetProcessInfo(process_info);
802 if (process_info.ProcessIDIsValid()) {
803 lldb::pid_t pid = process_info.GetProcessID();
804 std::string pid_str = std::to_string(pid);
805 files_with_stream_types.push_back(
806 {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
807 files_with_stream_types.push_back(
808 {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
809 files_with_stream_types.push_back(
810 {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
811 files_with_stream_types.push_back(
812 {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
813 files_with_stream_types.push_back(
814 {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
815 files_with_stream_types.push_back(
816 {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
817 files_with_stream_types.push_back(
818 {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
819 }
820
821 for (const auto &entry : files_with_stream_types) {
822 StreamType stream = entry.first;
823 std::string path = entry.second;
824 auto memory_buffer = getFileStreamHelper(path);
825
826 if (memory_buffer) {
827 size_t size = memory_buffer->getBufferSize();
828 if (size == 0)
829 continue;
830 error = AddDirectory(stream, size);
831 if (error.Fail())
832 return error;
833 m_data.AppendData(memory_buffer->getBufferStart(), size);
834 }
835 }
836
837 return error;
838}
839
842
843 // We first save the thread stacks to ensure they fit in the first UINT32_MAX
844 // bytes of the core file. Thread structures in minidump files can only use
845 // 32 bit memory descriptiors, so we emit them first to ensure the memory is
846 // in accessible with a 32 bit offset.
847 std::vector<CoreFileMemoryRange> ranges_32;
848 llvm::Expected<CoreFileMemoryRanges> all_core_memory_ranges_maybe =
849 m_save_core_options.GetMemoryRegionsToSave();
850 if (!all_core_memory_ranges_maybe)
851 return Status::FromError(all_core_memory_ranges_maybe.takeError());
852
853 const CoreFileMemoryRanges &all_core_memory_ranges =
854 *all_core_memory_ranges_maybe;
855
856 lldb_private::Progress progress("Saving Minidump File", "",
857 all_core_memory_ranges.GetSize());
858 std::vector<CoreFileMemoryRange> all_core_memory_vec;
859 // Extract all the data into just a vector of data. So we can mutate this in
860 // place.
861 for (const auto &core_range : all_core_memory_ranges)
862 all_core_memory_vec.push_back(core_range.data);
863
864 // Start by saving all of the stacks and ensuring they fit under the 32b
865 // limit.
866 uint64_t total_size = GetCurrentDataEndOffset();
867 auto iterator = all_core_memory_vec.begin();
868 while (iterator != all_core_memory_vec.end()) {
869 if (m_thread_by_range_end.count(iterator->range.end()) > 0) {
870 // We don't save stacks twice.
871 ranges_32.push_back(*iterator);
872 total_size +=
873 iterator->range.size() + sizeof(llvm::minidump::MemoryDescriptor);
874 iterator = all_core_memory_vec.erase(iterator);
875 } else {
876 iterator++;
877 }
878 }
879
880 // The header has to be in 32b memory, as it needs to be addressable by a 32b
881 // RVA. Everything else can be 64b.
882 total_size += sizeof(llvm::minidump::MemoryListHeader);
883
884 if (total_size >= UINT32_MAX) {
886 "Unable to write minidump. Stack memory "
887 "exceeds 32b limit. (Num Stacks %zu)",
888 ranges_32.size());
889 return error;
890 }
891
892 // Save only the thread stacks to the 32b memory list. Everything else will
893 // get put in Memory64, this simplifies tracking
894 error = AddMemoryList_32(ranges_32, progress);
895 if (error.Fail())
896 return error;
897
898 // Add the remaining memory as a 64b range.
899 if (!all_core_memory_ranges.IsEmpty()) {
900 error = AddMemoryList_64(all_core_memory_vec, progress);
901 if (error.Fail())
902 return error;
903 }
904
905 return FixThreadStacks();
906}
907
909 // write header
910 llvm::minidump::Header header;
911 header.Signature = static_cast<llvm::support::ulittle32_t>(
912 llvm::minidump::Header::MagicSignature);
913 header.Version = static_cast<llvm::support::ulittle32_t>(
914 llvm::minidump::Header::MagicVersion);
915 header.NumberOfStreams =
916 static_cast<llvm::support::ulittle32_t>(m_directories.size());
917 // We write the directories right after the header.
918 header.StreamDirectoryRVA =
919 static_cast<llvm::support::ulittle32_t>(HEADER_SIZE);
920 header.Checksum = static_cast<llvm::support::ulittle32_t>(
921 0u); // not used in most of the writers
922 header.TimeDateStamp =
923 static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
924 header.Flags =
925 static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag
926
928 size_t bytes_written;
929
930 m_core_file->SeekFromStart(0);
931 bytes_written = HEADER_SIZE;
932 error = m_core_file->Write(&header, bytes_written);
933 if (error.Fail() || bytes_written != HEADER_SIZE) {
934 if (bytes_written != HEADER_SIZE)
936 "Unable to write the minidump header (written %zd/%zd)",
937 bytes_written, HEADER_SIZE);
938 return error;
939 }
940 return error;
941}
942
946
949 size_t bytes_written;
950 m_core_file->SeekFromStart(HEADER_SIZE);
951 for (const Directory &dir : m_directories) {
952 bytes_written = DIRECTORY_SIZE;
953 error = m_core_file->Write(&dir, bytes_written);
954 if (error.Fail() || bytes_written != DIRECTORY_SIZE) {
955 if (bytes_written != DIRECTORY_SIZE)
957 "unable to write the directory (written %zd/%zd)", bytes_written,
959 return error;
960 }
961 }
962
963 return error;
964}
965
967 lldb_private::DataBufferHeap &data_buffer,
968 const lldb_private::CoreFileMemoryRange &range, uint64_t &bytes_read) {
969
970 const lldb::addr_t addr = range.range.start();
971 const lldb::addr_t size = range.range.size();
972 Log *log = GetLog(LLDBLog::Object);
973 void *buf = data_buffer.GetBytes();
974 const lldb::addr_t chunk_size = data_buffer.GetByteSize();
975 // Step over an unreadable page at a time, so we never zero-fill memory that
976 // could be read.
977 const lldb::addr_t page_size = 4096;
978
979 // Write exactly `size` bytes: Memory64List locates each range by the
980 // cumulative DataSize of the ranges before it.
981 bytes_read = 0;
982 Status addDataError;
983 while (bytes_read < size) {
984 const lldb::addr_t current_addr = addr + bytes_read;
985 const lldb::addr_t bytes_remaining = size - bytes_read;
986 const lldb::addr_t bytes_to_read = std::min(bytes_remaining, chunk_size);
988 const lldb::addr_t bytes_read_for_chunk =
989 m_process_sp->ReadMemoryFromInferior(current_addr, buf, bytes_to_read,
990 error);
991
992 if (bytes_read_for_chunk > 0) {
993 addDataError = AddData(buf, bytes_read_for_chunk);
994 if (addDataError.Fail())
995 return addDataError;
996 bytes_read += bytes_read_for_chunk;
997 }
998
999 // Unreadable page: zero-fill it and continue past the hole.
1000 if (bytes_read_for_chunk < bytes_to_read) {
1001 const lldb::addr_t hole = addr + bytes_read;
1002 lldb::addr_t fill = ((hole + page_size) & ~(page_size - 1)) - hole;
1003 fill = std::min(fill, size - bytes_read);
1004 fill = std::min(fill, chunk_size);
1005 LLDB_LOGF(log,
1006 "Failed to read memory region at: 0x%" PRIx64
1007 ". Zero-filling 0x%" PRIx64 " bytes, error: %s",
1008 hole, fill, error.AsCString());
1009 ::memset(buf, 0, fill);
1010 addDataError = AddData(buf, fill);
1011 if (addDataError.Fail())
1012 return addDataError;
1013 bytes_read += fill;
1014 }
1015 }
1016
1017 return addDataError;
1018}
1019
1020static uint64_t
1021GetLargestRangeSize(const std::vector<CoreFileMemoryRange> &ranges) {
1022 uint64_t max_size = 0;
1023 for (const auto &core_range : ranges)
1024 max_size = std::max(max_size, core_range.range.size());
1025 return max_size;
1026}
1027
1028Status
1029MinidumpFileBuilder::AddMemoryList_32(std::vector<CoreFileMemoryRange> &ranges,
1030 Progress &progress) {
1031 std::vector<MemoryDescriptor> descriptors;
1032 Status error;
1033 if (ranges.size() == 0)
1034 return error;
1035
1036 Log *log = GetLog(LLDBLog::Object);
1037 size_t region_index = 0;
1038 lldb_private::DataBufferHeap data_buffer(
1039 std::min(GetLargestRangeSize(ranges), MAX_WRITE_CHUNK_SIZE), 0);
1040 for (const auto &core_range : ranges) {
1041 // Take the offset before we write.
1042 const offset_t offset_for_data = GetCurrentDataEndOffset();
1043 const addr_t addr = core_range.range.start();
1044 const addr_t size = core_range.range.size();
1045 const addr_t end = core_range.range.end();
1046
1047 LLDB_LOGF(log,
1048 "AddMemoryList %zu/%zu reading memory for region "
1049 "(0x%" PRIx64 " bytes) [0x%" PRIx64 ", 0x%" PRIx64 ")",
1050 region_index, ranges.size(), size, addr, addr + size);
1051 ++region_index;
1052
1053 progress.Increment(1, "Adding Memory Range " + core_range.Dump());
1054 uint64_t bytes_read = 0;
1055 error = ReadWriteMemoryInChunks(data_buffer, core_range, bytes_read);
1056 if (error.Fail())
1057 return error;
1058
1059 // If we completely failed to read this range
1060 // we can drop the memory range
1061 if (bytes_read == 0)
1062 continue;
1063
1064 MemoryDescriptor descriptor;
1065 descriptor.StartOfMemoryRange =
1066 static_cast<llvm::support::ulittle64_t>(addr);
1067 descriptor.Memory.DataSize =
1068 static_cast<llvm::support::ulittle32_t>(bytes_read);
1069 descriptor.Memory.RVA =
1070 static_cast<llvm::support::ulittle32_t>(offset_for_data);
1071 descriptors.push_back(descriptor);
1072 if (m_thread_by_range_end.count(end) > 0)
1073 m_thread_by_range_end[end].Stack = descriptor;
1074 }
1075
1076 // Add a directory that references this list
1077 // With a size of the number of ranges as a 32 bit num
1078 // And then the size of all the ranges
1079 error = AddDirectory(StreamType::MemoryList,
1080 sizeof(llvm::minidump::MemoryListHeader) +
1081 descriptors.size() *
1082 sizeof(llvm::minidump::MemoryDescriptor));
1083 if (error.Fail())
1084 return error;
1085
1086 llvm::minidump::MemoryListHeader list_header;
1087 llvm::support::ulittle32_t memory_ranges_num =
1088 static_cast<llvm::support::ulittle32_t>(descriptors.size());
1089 list_header.NumberOfMemoryRanges = memory_ranges_num;
1090 m_data.AppendData(&list_header, sizeof(llvm::minidump::MemoryListHeader));
1091 // For 32b we can get away with writing off the descriptors after the data.
1092 // This means no cleanup loop needed.
1093 m_data.AppendData(descriptors.data(),
1094 descriptors.size() * sizeof(MemoryDescriptor));
1095
1096 return error;
1097}
1098
1099Status
1100MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges,
1101 Progress &progress) {
1102 Status error;
1103 if (ranges.empty())
1104 return error;
1105
1106 error = AddDirectory(StreamType::Memory64List,
1107 (sizeof(llvm::minidump::Memory64ListHeader)) +
1108 ranges.size() *
1109 sizeof(llvm::minidump::MemoryDescriptor_64));
1110 if (error.Fail())
1111 return error;
1112
1113 llvm::minidump::Memory64ListHeader list_header;
1114 llvm::support::ulittle64_t memory_ranges_num =
1115 static_cast<llvm::support::ulittle64_t>(ranges.size());
1116 list_header.NumberOfMemoryRanges = memory_ranges_num;
1117 // Capture the starting offset for all the descriptors so we can clean them up
1118 // if needed.
1119 offset_t starting_offset =
1120 GetCurrentDataEndOffset() + sizeof(llvm::minidump::Memory64ListHeader);
1121 // The base_rva needs to start after the directories, which is right after
1122 // the descriptors + the size of the header.
1123 offset_t base_rva =
1124 starting_offset +
1125 (ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64));
1126 llvm::support::ulittle64_t memory_ranges_base_rva =
1127 static_cast<llvm::support::ulittle64_t>(base_rva);
1128 list_header.BaseRVA = memory_ranges_base_rva;
1129 m_data.AppendData(&list_header, sizeof(llvm::minidump::Memory64ListHeader));
1130
1131 lldb_private::DataBufferHeap data_buffer(
1132 std::min(GetLargestRangeSize(ranges), MAX_WRITE_CHUNK_SIZE), 0);
1133 bool cleanup_required = false;
1134 std::vector<MemoryDescriptor_64> descriptors;
1135 // Enumerate the ranges and create the memory descriptors so we can append
1136 // them first
1137 for (const auto core_range : ranges) {
1138 // Add the space required to store the memory descriptor
1139 MemoryDescriptor_64 memory_desc;
1140 memory_desc.StartOfMemoryRange =
1141 static_cast<llvm::support::ulittle64_t>(core_range.range.start());
1142 memory_desc.DataSize =
1143 static_cast<llvm::support::ulittle64_t>(core_range.range.size());
1144 descriptors.push_back(memory_desc);
1145 // Now write this memory descriptor to the buffer.
1146 m_data.AppendData(&memory_desc, sizeof(MemoryDescriptor_64));
1147 }
1148
1149 Log *log = GetLog(LLDBLog::Object);
1150 size_t region_index = 0;
1151 for (const auto &core_range : ranges) {
1152 const addr_t addr = core_range.range.start();
1153 const addr_t size = core_range.range.size();
1154
1155 LLDB_LOGF(log,
1156 "AddMemoryList_64 %zu/%zu reading memory for region "
1157 "(%" PRIx64 "bytes) "
1158 "[%" PRIx64 ", %" PRIx64 ")",
1159 region_index, ranges.size(), size, addr, addr + size);
1160
1161 progress.Increment(1, "Adding Memory Range " + core_range.Dump());
1162 uint64_t bytes_read = 0;
1163 error = ReadWriteMemoryInChunks(data_buffer, core_range, bytes_read);
1164 if (error.Fail())
1165 return error;
1166
1167 if (bytes_read == 0) {
1168 cleanup_required = true;
1169 descriptors[region_index].DataSize = 0;
1170 }
1171 if (bytes_read != size) {
1172 cleanup_required = true;
1173 descriptors[region_index].DataSize = bytes_read;
1174 }
1175
1176 ++region_index;
1177 }
1178
1179 // Early return if there is no cleanup needed.
1180 if (!cleanup_required) {
1181 return error;
1182 } else {
1183 // Flush to disk we can make the fixes in place.
1185 // Fixup the descriptors that were not read correctly.
1186 m_core_file->SeekFromStart(starting_offset);
1187 size_t bytes_written = sizeof(MemoryDescriptor_64) * descriptors.size();
1188 error = m_core_file->Write(descriptors.data(), bytes_written);
1189 if (error.Fail() ||
1190 bytes_written != sizeof(MemoryDescriptor_64) * descriptors.size()) {
1192 "unable to write the memory descriptors (written %zd/%zd)",
1193 bytes_written, sizeof(MemoryDescriptor_64) * descriptors.size());
1194 }
1195
1196 return error;
1197 }
1198}
1199
1200Status MinidumpFileBuilder::AddData(const void *data, uint64_t size) {
1201 // Append the data to the buffer, if the buffer spills over, flush it to disk
1202 m_data.AppendData(data, size);
1203 if (m_data.GetByteSize() > MAX_WRITE_CHUNK_SIZE)
1204 return FlushBufferToDisk();
1205
1206 return Status();
1207}
1208
1210 Status error;
1211 // Set the stream to it's end.
1212 m_core_file->SeekFromStart(m_saved_data_size);
1213 addr_t starting_size = m_data.GetByteSize();
1214 addr_t remaining_bytes = starting_size;
1215 offset_t offset = 0;
1216
1217 while (remaining_bytes > 0) {
1218 size_t bytes_written = remaining_bytes;
1219 // We don't care how many bytes we wrote unless we got an error
1220 // so just decrement the remaining bytes.
1221 error = m_core_file->Write(m_data.GetBytes() + offset, bytes_written);
1222 if (error.Fail()) {
1224 "Wrote incorrect number of bytes to minidump file. (written %" PRIx64
1225 "/%" PRIx64 ")",
1226 starting_size - remaining_bytes, starting_size);
1227 return error;
1228 }
1229
1230 offset += bytes_written;
1231 remaining_bytes -= bytes_written;
1232 }
1233
1234 m_saved_data_size += starting_size;
1235 m_data.Clear();
1236 return error;
1237}
1238
1240 Status error;
1241 // If anything is left unsaved, dump it.
1243 if (error.Fail())
1244 return error;
1245
1246 // Overwrite the header which we filled in earlier.
1247 error = DumpHeader();
1248 if (error.Fail())
1249 return error;
1250
1251 // Overwrite the space saved for directories
1253 if (error.Fail())
1254 return error;
1255
1256 return error;
1257}
1258
1260 Log *log = GetLog(LLDBLog::Object);
1261
1262 if (m_core_file) {
1263 Status error = m_core_file->Close();
1264 if (error.Fail())
1265 LLDB_LOGF(log, "Failed to close minidump file: %s", error.AsCString());
1266
1267 m_core_file.reset();
1268 }
1269}
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
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:544
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:881
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:125
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:62
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:3491
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1247
const ArchSpec & GetArchitecture() const
Definition Target.h:1289
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