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_x86_64.h" 12 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ModuleList.h" 15 #include "lldb/Core/Section.h" 16 #include "lldb/Target/MemoryRegionInfo.h" 17 #include "lldb/Target/Process.h" 18 #include "lldb/Target/RegisterContext.h" 19 #include "lldb/Target/StopInfo.h" 20 #include "lldb/Target/ThreadList.h" 21 #include "lldb/Utility/DataExtractor.h" 22 #include "lldb/Utility/RegisterValue.h" 23 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/BinaryFormat/Minidump.h" 26 #include "llvm/Support/ConvertUTF.h" 27 #include "llvm/Support/Error.h" 28 29 #include "Plugins/Process/minidump/MinidumpTypes.h" 30 31 #include <cinttypes> 32 33 using namespace lldb; 34 using namespace lldb_private; 35 using namespace llvm::minidump; 36 37 void MinidumpFileBuilder::AddDirectory(StreamType type, size_t stream_size) { 38 LocationDescriptor loc; 39 loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size); 40 // Stream will begin at the current end of data section 41 loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset()); 42 43 Directory dir; 44 dir.Type = static_cast<llvm::support::little_t<StreamType>>(type); 45 dir.Location = loc; 46 47 m_directories.push_back(dir); 48 } 49 50 Status MinidumpFileBuilder::AddSystemInfo(const llvm::Triple &target_triple) { 51 Status error; 52 AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo)); 53 54 llvm::minidump::ProcessorArchitecture arch; 55 switch (target_triple.getArch()) { 56 case llvm::Triple::ArchType::x86_64: 57 arch = ProcessorArchitecture::AMD64; 58 break; 59 case llvm::Triple::ArchType::x86: 60 arch = ProcessorArchitecture::X86; 61 break; 62 case llvm::Triple::ArchType::arm: 63 arch = ProcessorArchitecture::ARM; 64 break; 65 case llvm::Triple::ArchType::aarch64: 66 arch = ProcessorArchitecture::ARM64; 67 break; 68 case llvm::Triple::ArchType::mips64: 69 case llvm::Triple::ArchType::mips64el: 70 case llvm::Triple::ArchType::mips: 71 case llvm::Triple::ArchType::mipsel: 72 arch = ProcessorArchitecture::MIPS; 73 break; 74 case llvm::Triple::ArchType::ppc64: 75 case llvm::Triple::ArchType::ppc: 76 case llvm::Triple::ArchType::ppc64le: 77 arch = ProcessorArchitecture::PPC; 78 break; 79 default: 80 error.SetErrorStringWithFormat("Architecture %s not supported.", 81 target_triple.getArchName().str().c_str()); 82 return error; 83 }; 84 85 llvm::support::little_t<OSPlatform> platform_id; 86 switch (target_triple.getOS()) { 87 case llvm::Triple::OSType::Linux: 88 if (target_triple.getEnvironment() == 89 llvm::Triple::EnvironmentType::Android) 90 platform_id = OSPlatform::Android; 91 else 92 platform_id = OSPlatform::Linux; 93 break; 94 case llvm::Triple::OSType::Win32: 95 platform_id = OSPlatform::Win32NT; 96 break; 97 case llvm::Triple::OSType::MacOSX: 98 platform_id = OSPlatform::MacOSX; 99 break; 100 case llvm::Triple::OSType::IOS: 101 platform_id = OSPlatform::IOS; 102 break; 103 default: 104 error.SetErrorStringWithFormat("OS %s not supported.", 105 target_triple.getOSName().str().c_str()); 106 return error; 107 }; 108 109 llvm::minidump::SystemInfo sys_info; 110 sys_info.ProcessorArch = 111 static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch); 112 // Global offset to beginning of a csd_string in a data section 113 sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>( 114 GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo)); 115 sys_info.PlatformId = platform_id; 116 m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo)); 117 118 std::string csd_string = ""; 119 120 error = WriteString(csd_string, &m_data); 121 if (error.Fail()) { 122 error.SetErrorString("Unable to convert the csd string to UTF16."); 123 return error; 124 } 125 126 return error; 127 } 128 129 Status WriteString(const std::string &to_write, 130 lldb_private::DataBufferHeap *buffer) { 131 Status error; 132 // let the StringRef eat also null termination char 133 llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1); 134 llvm::SmallVector<llvm::UTF16, 128> to_write_utf16; 135 136 bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16); 137 if (!converted) { 138 error.SetErrorStringWithFormat( 139 "Unable to convert the string to UTF16. Failed to convert %s", 140 to_write.c_str()); 141 return error; 142 } 143 144 // size of the UTF16 string should be written without the null termination 145 // character that is stored in 2 bytes 146 llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2); 147 148 buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t)); 149 buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes()); 150 151 return error; 152 } 153 154 llvm::Expected<uint64_t> getModuleFileSize(Target &target, 155 const ModuleSP &mod) { 156 SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection(); 157 uint64_t SizeOfImage = 0; 158 159 if (!sect_sp) { 160 return llvm::createStringError(std::errc::operation_not_supported, 161 "Couldn't obtain the section information."); 162 } 163 lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target); 164 // Use memory size since zero fill sections, like ".bss", will be smaller on 165 // disk. 166 lldb::addr_t sect_size = sect_sp->GetByteSize(); 167 // This will usually be zero, but make sure to calculate the BaseOfImage 168 // offset. 169 const lldb::addr_t base_sect_offset = 170 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) - 171 sect_addr; 172 SizeOfImage = sect_size - base_sect_offset; 173 lldb::addr_t next_sect_addr = sect_addr + sect_size; 174 Address sect_so_addr; 175 target.ResolveLoadAddress(next_sect_addr, sect_so_addr); 176 lldb::SectionSP next_sect_sp = sect_so_addr.GetSection(); 177 while (next_sect_sp && 178 next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) { 179 sect_size = sect_sp->GetByteSize(); 180 SizeOfImage += sect_size; 181 next_sect_addr += sect_size; 182 target.ResolveLoadAddress(next_sect_addr, sect_so_addr); 183 next_sect_sp = sect_so_addr.GetSection(); 184 } 185 186 return SizeOfImage; 187 } 188 189 // ModuleList stream consists of a number of modules, followed by an array 190 // of llvm::minidump::Module's structures. Every structure informs about a 191 // single module. Additional data of variable length, such as module's names, 192 // are stored just after the ModuleList stream. The llvm::minidump::Module 193 // structures point to this helper data by global offset. 194 Status MinidumpFileBuilder::AddModuleList(Target &target) { 195 constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module); 196 Status error; 197 198 const ModuleList &modules = target.GetImages(); 199 llvm::support::ulittle32_t modules_count = 200 static_cast<llvm::support::ulittle32_t>(modules.GetSize()); 201 202 // This helps us with getting the correct global offset in minidump 203 // file later, when we will be setting up offsets from the 204 // the llvm::minidump::Module's structures into helper data 205 size_t size_before = GetCurrentDataEndOffset(); 206 207 // This is the size of the main part of the ModuleList stream. 208 // It consists of a module number and corresponding number of 209 // structs describing individual modules 210 size_t module_stream_size = 211 sizeof(llvm::support::ulittle32_t) + modules_count * minidump_module_size; 212 213 // Adding directory describing this stream. 214 AddDirectory(StreamType::ModuleList, module_stream_size); 215 216 m_data.AppendData(&modules_count, sizeof(llvm::support::ulittle32_t)); 217 218 // Temporary storage for the helper data (of variable length) 219 // as these cannot be dumped to m_data before dumping entire 220 // array of module structures. 221 DataBufferHeap helper_data; 222 223 for (size_t i = 0; i < modules_count; ++i) { 224 ModuleSP mod = modules.GetModuleAtIndex(i); 225 std::string module_name = mod->GetSpecificationDescription(); 226 auto maybe_mod_size = getModuleFileSize(target, mod); 227 if (!maybe_mod_size) { 228 error.SetErrorStringWithFormat("Unable to get the size of module %s.", 229 module_name.c_str()); 230 return error; 231 } 232 233 uint64_t mod_size = std::move(*maybe_mod_size); 234 235 llvm::support::ulittle32_t signature = 236 static_cast<llvm::support::ulittle32_t>( 237 static_cast<uint32_t>(minidump::CvSignature::ElfBuildId)); 238 auto uuid = mod->GetUUID().GetBytes(); 239 240 VSFixedFileInfo info; 241 info.Signature = static_cast<llvm::support::ulittle32_t>(0u); 242 info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u); 243 info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u); 244 info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u); 245 info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u); 246 info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u); 247 info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u); 248 info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u); 249 info.FileOS = static_cast<llvm::support::ulittle32_t>(0u); 250 info.FileType = static_cast<llvm::support::ulittle32_t>(0u); 251 info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u); 252 info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u); 253 info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u); 254 255 LocationDescriptor ld; 256 ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u); 257 ld.RVA = static_cast<llvm::support::ulittle32_t>(0u); 258 259 // Setting up LocationDescriptor for uuid string. The global offset into 260 // minidump file is calculated. 261 LocationDescriptor ld_cv; 262 ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>( 263 sizeof(llvm::support::ulittle32_t) + uuid.size()); 264 ld_cv.RVA = static_cast<llvm::support::ulittle32_t>( 265 size_before + module_stream_size + helper_data.GetByteSize()); 266 267 helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t)); 268 helper_data.AppendData(uuid.begin(), uuid.size()); 269 270 llvm::minidump::Module m; 271 m.BaseOfImage = static_cast<llvm::support::ulittle64_t>( 272 mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target)); 273 m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size); 274 m.Checksum = static_cast<llvm::support::ulittle32_t>(0); 275 m.TimeDateStamp = static_cast<llvm::support::ulittle32_t>(std::time(0)); 276 m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>( 277 size_before + module_stream_size + helper_data.GetByteSize()); 278 m.VersionInfo = info; 279 m.CvRecord = ld_cv; 280 m.MiscRecord = ld; 281 282 error = WriteString(module_name, &helper_data); 283 284 if (error.Fail()) 285 return error; 286 287 m_data.AppendData(&m, sizeof(llvm::minidump::Module)); 288 } 289 290 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 291 return error; 292 } 293 294 uint16_t read_register_u16_raw(RegisterContext *reg_ctx, 295 const std::string ®_name) { 296 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 297 if (!reg_info) 298 return 0; 299 lldb_private::RegisterValue reg_value; 300 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 301 if (!success) 302 return 0; 303 return reg_value.GetAsUInt16(); 304 } 305 306 uint32_t read_register_u32_raw(RegisterContext *reg_ctx, 307 const std::string ®_name) { 308 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 309 if (!reg_info) 310 return 0; 311 lldb_private::RegisterValue reg_value; 312 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 313 if (!success) 314 return 0; 315 return reg_value.GetAsUInt32(); 316 } 317 318 uint64_t read_register_u64_raw(RegisterContext *reg_ctx, 319 const std::string ®_name) { 320 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 321 if (!reg_info) 322 return 0; 323 lldb_private::RegisterValue reg_value; 324 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 325 if (!success) 326 return 0; 327 return reg_value.GetAsUInt64(); 328 } 329 330 llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, 331 const std::string ®_name) { 332 return static_cast<llvm::support::ulittle16_t>( 333 read_register_u16_raw(reg_ctx, reg_name)); 334 } 335 336 llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx, 337 const std::string ®_name) { 338 return static_cast<llvm::support::ulittle32_t>( 339 read_register_u32_raw(reg_ctx, reg_name)); 340 } 341 342 llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, 343 const std::string ®_name) { 344 return static_cast<llvm::support::ulittle64_t>( 345 read_register_u64_raw(reg_ctx, reg_name)); 346 } 347 348 lldb_private::minidump::MinidumpContext_x86_64 349 GetThreadContext_64(RegisterContext *reg_ctx) { 350 lldb_private::minidump::MinidumpContext_x86_64 thread_context; 351 thread_context.context_flags = static_cast<uint32_t>( 352 lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag | 353 lldb_private::minidump::MinidumpContext_x86_64_Flags::Control | 354 lldb_private::minidump::MinidumpContext_x86_64_Flags::Segments | 355 lldb_private::minidump::MinidumpContext_x86_64_Flags::Integer); 356 thread_context.rax = read_register_u64(reg_ctx, "rax"); 357 thread_context.rbx = read_register_u64(reg_ctx, "rbx"); 358 thread_context.rcx = read_register_u64(reg_ctx, "rcx"); 359 thread_context.rdx = read_register_u64(reg_ctx, "rdx"); 360 thread_context.rdi = read_register_u64(reg_ctx, "rdi"); 361 thread_context.rsi = read_register_u64(reg_ctx, "rsi"); 362 thread_context.rbp = read_register_u64(reg_ctx, "rbp"); 363 thread_context.rsp = read_register_u64(reg_ctx, "rsp"); 364 thread_context.r8 = read_register_u64(reg_ctx, "r8"); 365 thread_context.r9 = read_register_u64(reg_ctx, "r9"); 366 thread_context.r10 = read_register_u64(reg_ctx, "r10"); 367 thread_context.r11 = read_register_u64(reg_ctx, "r11"); 368 thread_context.r12 = read_register_u64(reg_ctx, "r12"); 369 thread_context.r13 = read_register_u64(reg_ctx, "r13"); 370 thread_context.r14 = read_register_u64(reg_ctx, "r14"); 371 thread_context.r15 = read_register_u64(reg_ctx, "r15"); 372 thread_context.rip = read_register_u64(reg_ctx, "rip"); 373 thread_context.eflags = read_register_u32(reg_ctx, "rflags"); 374 thread_context.cs = read_register_u16(reg_ctx, "cs"); 375 thread_context.fs = read_register_u16(reg_ctx, "fs"); 376 thread_context.gs = read_register_u16(reg_ctx, "gs"); 377 thread_context.ss = read_register_u16(reg_ctx, "ss"); 378 thread_context.ds = read_register_u16(reg_ctx, "ds"); 379 return thread_context; 380 } 381 382 // Function returns start and size of the memory region that contains 383 // memory location pointed to by the current stack pointer. 384 llvm::Expected<std::pair<addr_t, addr_t>> 385 findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp) { 386 MemoryRegionInfo range_info; 387 Status error = process_sp->GetMemoryRegionInfo(rsp, range_info); 388 // Skip failed memory region requests or any regions with no permissions. 389 if (error.Fail() || range_info.GetLLDBPermissions() == 0) 390 return llvm::createStringError( 391 std::errc::not_supported, 392 "unable to load stack segment of the process"); 393 394 const addr_t addr = range_info.GetRange().GetRangeBase(); 395 const addr_t size = range_info.GetRange().GetByteSize(); 396 397 if (size == 0) 398 return llvm::createStringError(std::errc::not_supported, 399 "stack segment of the process is empty"); 400 401 return std::make_pair(addr, size); 402 } 403 404 Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) { 405 constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread); 406 lldb_private::ThreadList thread_list = process_sp->GetThreadList(); 407 408 // size of the entire thread stream consists of: 409 // number of threads and threads array 410 size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) + 411 thread_list.GetSize() * minidump_thread_size; 412 // save for the ability to set up RVA 413 size_t size_before = GetCurrentDataEndOffset(); 414 415 AddDirectory(StreamType::ThreadList, thread_stream_size); 416 417 llvm::support::ulittle32_t thread_count = 418 static_cast<llvm::support::ulittle32_t>(thread_list.GetSize()); 419 m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t)); 420 421 DataBufferHeap helper_data; 422 423 const uint32_t num_threads = thread_list.GetSize(); 424 425 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { 426 ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx)); 427 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 428 Status error; 429 430 if (!reg_ctx_sp) { 431 error.SetErrorString("Unable to get the register context."); 432 return error; 433 } 434 RegisterContext *reg_ctx = reg_ctx_sp.get(); 435 auto thread_context = GetThreadContext_64(reg_ctx); 436 uint64_t rsp = read_register_u64_raw(reg_ctx, "rsp"); 437 auto expected_address_range = findStackHelper(process_sp, rsp); 438 439 if (!expected_address_range) { 440 error.SetErrorString("Unable to get the stack address."); 441 return error; 442 } 443 444 std::pair<uint64_t, uint64_t> range = std::move(*expected_address_range); 445 uint64_t addr = range.first; 446 uint64_t size = range.second; 447 448 auto data_up = std::make_unique<DataBufferHeap>(size, 0); 449 const size_t stack_bytes_read = 450 process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); 451 452 if (error.Fail()) 453 return error; 454 455 LocationDescriptor stack_memory; 456 stack_memory.DataSize = 457 static_cast<llvm::support::ulittle32_t>(stack_bytes_read); 458 stack_memory.RVA = static_cast<llvm::support::ulittle32_t>( 459 size_before + thread_stream_size + helper_data.GetByteSize()); 460 461 MemoryDescriptor stack; 462 stack.StartOfMemoryRange = static_cast<llvm::support::ulittle64_t>(addr); 463 stack.Memory = stack_memory; 464 465 helper_data.AppendData(data_up->GetBytes(), stack_bytes_read); 466 467 LocationDescriptor thread_context_memory_locator; 468 thread_context_memory_locator.DataSize = 469 static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); 470 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( 471 size_before + thread_stream_size + helper_data.GetByteSize()); 472 473 helper_data.AppendData( 474 &thread_context, 475 sizeof(lldb_private::minidump::MinidumpContext_x86_64)); 476 477 llvm::minidump::Thread t; 478 t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); 479 t.SuspendCount = static_cast<llvm::support::ulittle32_t>( 480 (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0); 481 t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0); 482 t.Priority = static_cast<llvm::support::ulittle32_t>(0); 483 t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0); 484 t.Stack = stack, t.Context = thread_context_memory_locator; 485 486 m_data.AppendData(&t, sizeof(llvm::minidump::Thread)); 487 } 488 489 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 490 return Status(); 491 } 492 493 Status MinidumpFileBuilder::AddException(const lldb::ProcessSP &process_sp) { 494 Status error; 495 lldb_private::ThreadList thread_list = process_sp->GetThreadList(); 496 497 const uint32_t num_threads = thread_list.GetSize(); 498 uint32_t stop_reason_thread_idx = 0; 499 for (stop_reason_thread_idx = 0; stop_reason_thread_idx < num_threads; 500 ++stop_reason_thread_idx) { 501 ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); 502 StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); 503 504 if (stop_info_sp && stop_info_sp->IsValid()) 505 break; 506 } 507 508 if (stop_reason_thread_idx == num_threads) { 509 error.SetErrorString("No stop reason thread found."); 510 return error; 511 } 512 513 constexpr size_t minidump_exception_size = 514 sizeof(llvm::minidump::ExceptionStream); 515 AddDirectory(StreamType::Exception, minidump_exception_size); 516 size_t size_before = GetCurrentDataEndOffset(); 517 518 ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); 519 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 520 RegisterContext *reg_ctx = reg_ctx_sp.get(); 521 auto thread_context = GetThreadContext_64(reg_ctx); 522 StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); 523 524 DataBufferHeap helper_data; 525 526 LocationDescriptor thread_context_memory_locator; 527 thread_context_memory_locator.DataSize = 528 static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); 529 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( 530 size_before + minidump_exception_size + helper_data.GetByteSize()); 531 532 helper_data.AppendData( 533 &thread_context, sizeof(lldb_private::minidump::MinidumpContext_x86_64)); 534 535 Exception exp_record; 536 exp_record.ExceptionCode = 537 static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue()); 538 exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0); 539 exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0); 540 exp_record.ExceptionAddress = read_register_u64(reg_ctx, "rip"); 541 exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0); 542 exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); 543 // exp_record.ExceptionInformation; 544 545 ExceptionStream exp_stream; 546 exp_stream.ThreadId = 547 static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); 548 exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); 549 exp_stream.ExceptionRecord = exp_record; 550 exp_stream.ThreadContext = thread_context_memory_locator; 551 552 m_data.AppendData(&exp_stream, minidump_exception_size); 553 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 554 return error; 555 } 556 557 lldb_private::Status 558 MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp) { 559 Status error; 560 561 if (error.Fail()) { 562 error.SetErrorString("Process doesn't support getting memory region info."); 563 return error; 564 } 565 566 // Get interesting addresses 567 std::vector<size_t> interesting_addresses; 568 auto thread_list = process_sp->GetThreadList(); 569 for (size_t i = 0; i < thread_list.GetSize(); ++i) { 570 ThreadSP thread_sp(thread_list.GetThreadAtIndex(i)); 571 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 572 RegisterContext *reg_ctx = reg_ctx_sp.get(); 573 574 interesting_addresses.push_back(read_register_u64(reg_ctx, "rsp")); 575 interesting_addresses.push_back(read_register_u64(reg_ctx, "rip")); 576 } 577 578 DataBufferHeap helper_data; 579 std::vector<MemoryDescriptor> mem_descriptors; 580 581 std::set<addr_t> visited_region_base_addresses; 582 for (size_t interesting_address : interesting_addresses) { 583 MemoryRegionInfo range_info; 584 error = process_sp->GetMemoryRegionInfo(interesting_address, range_info); 585 // Skip failed memory region requests or any regions with no permissions. 586 if (error.Fail() || range_info.GetLLDBPermissions() == 0) 587 continue; 588 const addr_t addr = range_info.GetRange().GetRangeBase(); 589 // Skip any regions we have already saved out. 590 if (visited_region_base_addresses.insert(addr).second == false) 591 continue; 592 const addr_t size = range_info.GetRange().GetByteSize(); 593 if (size == 0) 594 continue; 595 auto data_up = std::make_unique<DataBufferHeap>(size, 0); 596 const size_t bytes_read = 597 process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); 598 if (bytes_read == 0) 599 continue; 600 // We have a good memory region with valid bytes to store. 601 LocationDescriptor memory_dump; 602 memory_dump.DataSize = static_cast<llvm::support::ulittle32_t>(bytes_read); 603 memory_dump.RVA = 604 static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset()); 605 MemoryDescriptor memory_desc; 606 memory_desc.StartOfMemoryRange = 607 static_cast<llvm::support::ulittle64_t>(addr); 608 memory_desc.Memory = memory_dump; 609 mem_descriptors.push_back(memory_desc); 610 m_data.AppendData(data_up->GetBytes(), bytes_read); 611 } 612 613 AddDirectory(StreamType::MemoryList, 614 sizeof(llvm::support::ulittle32_t) + 615 mem_descriptors.size() * 616 sizeof(llvm::minidump::MemoryDescriptor)); 617 llvm::support::ulittle32_t memory_ranges_num(mem_descriptors.size()); 618 619 m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle32_t)); 620 for (auto memory_descriptor : mem_descriptors) { 621 m_data.AppendData(&memory_descriptor, 622 sizeof(llvm::minidump::MemoryDescriptor)); 623 } 624 625 return error; 626 } 627 628 void MinidumpFileBuilder::AddMiscInfo(const lldb::ProcessSP &process_sp) { 629 AddDirectory(StreamType::MiscInfo, 630 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 631 632 lldb_private::minidump::MinidumpMiscInfo misc_info; 633 misc_info.size = static_cast<llvm::support::ulittle32_t>( 634 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 635 // Default set flags1 to 0, in case that we will not be able to 636 // get any information 637 misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0); 638 639 lldb_private::ProcessInstanceInfo process_info; 640 process_sp->GetProcessInfo(process_info); 641 if (process_info.ProcessIDIsValid()) { 642 // Set flags1 to reflect that PID is filled in 643 misc_info.flags1 = 644 static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>( 645 lldb_private::minidump::MinidumpMiscInfoFlags::ProcessID)); 646 misc_info.process_id = 647 static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID()); 648 } 649 650 m_data.AppendData(&misc_info, 651 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 652 } 653 654 std::unique_ptr<llvm::MemoryBuffer> 655 getFileStreamHelper(const std::string &path) { 656 auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path); 657 if (!maybe_stream) 658 return nullptr; 659 return std::move(maybe_stream.get()); 660 } 661 662 void MinidumpFileBuilder::AddLinuxFileStreams( 663 const lldb::ProcessSP &process_sp) { 664 std::vector<std::pair<StreamType, std::string>> files_with_stream_types = { 665 {StreamType::LinuxCPUInfo, "/proc/cpuinfo"}, 666 {StreamType::LinuxLSBRelease, "/etc/lsb-release"}, 667 }; 668 669 lldb_private::ProcessInstanceInfo process_info; 670 process_sp->GetProcessInfo(process_info); 671 if (process_info.ProcessIDIsValid()) { 672 lldb::pid_t pid = process_info.GetProcessID(); 673 std::string pid_str = std::to_string(pid); 674 files_with_stream_types.push_back( 675 {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"}); 676 files_with_stream_types.push_back( 677 {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"}); 678 files_with_stream_types.push_back( 679 {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"}); 680 files_with_stream_types.push_back( 681 {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"}); 682 files_with_stream_types.push_back( 683 {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"}); 684 files_with_stream_types.push_back( 685 {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"}); 686 files_with_stream_types.push_back( 687 {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"}); 688 } 689 690 for (const auto &entry : files_with_stream_types) { 691 StreamType stream = entry.first; 692 std::string path = entry.second; 693 auto memory_buffer = getFileStreamHelper(path); 694 695 if (memory_buffer) { 696 size_t size = memory_buffer->getBufferSize(); 697 if (size == 0) 698 continue; 699 AddDirectory(stream, size); 700 m_data.AppendData(memory_buffer->getBufferStart(), size); 701 } 702 } 703 } 704 705 Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const { 706 constexpr size_t header_size = sizeof(llvm::minidump::Header); 707 constexpr size_t directory_size = sizeof(llvm::minidump::Directory); 708 709 // write header 710 llvm::minidump::Header header; 711 header.Signature = static_cast<llvm::support::ulittle32_t>( 712 llvm::minidump::Header::MagicSignature); 713 header.Version = static_cast<llvm::support::ulittle32_t>( 714 llvm::minidump::Header::MagicVersion); 715 header.NumberOfStreams = 716 static_cast<llvm::support::ulittle32_t>(GetDirectoriesNum()); 717 header.StreamDirectoryRVA = 718 static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset()); 719 header.Checksum = static_cast<llvm::support::ulittle32_t>( 720 0u), // not used in most of the writers 721 header.TimeDateStamp = 722 static_cast<llvm::support::ulittle32_t>(std::time(0)); 723 header.Flags = 724 static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag 725 726 Status error; 727 size_t bytes_written; 728 729 bytes_written = header_size; 730 error = core_file->Write(&header, bytes_written); 731 if (error.Fail() || bytes_written != header_size) { 732 if (bytes_written != header_size) 733 error.SetErrorStringWithFormat( 734 "unable to write the header (written %zd/%zd)", bytes_written, 735 header_size); 736 return error; 737 } 738 739 // write data 740 bytes_written = m_data.GetByteSize(); 741 error = core_file->Write(m_data.GetBytes(), bytes_written); 742 if (error.Fail() || bytes_written != m_data.GetByteSize()) { 743 if (bytes_written != m_data.GetByteSize()) 744 error.SetErrorStringWithFormat( 745 "unable to write the data (written %zd/%" PRIu64 ")", bytes_written, 746 m_data.GetByteSize()); 747 return error; 748 } 749 750 // write directories 751 for (const Directory &dir : m_directories) { 752 bytes_written = directory_size; 753 error = core_file->Write(&dir, bytes_written); 754 if (error.Fail() || bytes_written != directory_size) { 755 if (bytes_written != directory_size) 756 error.SetErrorStringWithFormat( 757 "unable to write the directory (written %zd/%zd)", bytes_written, 758 directory_size); 759 return error; 760 } 761 } 762 763 return error; 764 } 765 766 size_t MinidumpFileBuilder::GetDirectoriesNum() const { 767 return m_directories.size(); 768 } 769 770 size_t MinidumpFileBuilder::GetCurrentDataEndOffset() const { 771 return sizeof(llvm::minidump::Header) + m_data.GetByteSize(); 772 } 773