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