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 = 276 static_cast<llvm::support::ulittle32_t>(std::time(nullptr)); 277 m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>( 278 size_before + module_stream_size + helper_data.GetByteSize()); 279 m.VersionInfo = info; 280 m.CvRecord = ld_cv; 281 m.MiscRecord = ld; 282 283 error = WriteString(module_name, &helper_data); 284 285 if (error.Fail()) 286 return error; 287 288 m_data.AppendData(&m, sizeof(llvm::minidump::Module)); 289 } 290 291 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 292 return error; 293 } 294 295 uint16_t read_register_u16_raw(RegisterContext *reg_ctx, 296 const std::string ®_name) { 297 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 298 if (!reg_info) 299 return 0; 300 lldb_private::RegisterValue reg_value; 301 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 302 if (!success) 303 return 0; 304 return reg_value.GetAsUInt16(); 305 } 306 307 uint32_t read_register_u32_raw(RegisterContext *reg_ctx, 308 const std::string ®_name) { 309 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 310 if (!reg_info) 311 return 0; 312 lldb_private::RegisterValue reg_value; 313 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 314 if (!success) 315 return 0; 316 return reg_value.GetAsUInt32(); 317 } 318 319 uint64_t read_register_u64_raw(RegisterContext *reg_ctx, 320 const std::string ®_name) { 321 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); 322 if (!reg_info) 323 return 0; 324 lldb_private::RegisterValue reg_value; 325 bool success = reg_ctx->ReadRegister(reg_info, reg_value); 326 if (!success) 327 return 0; 328 return reg_value.GetAsUInt64(); 329 } 330 331 llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, 332 const std::string ®_name) { 333 return static_cast<llvm::support::ulittle16_t>( 334 read_register_u16_raw(reg_ctx, reg_name)); 335 } 336 337 llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx, 338 const std::string ®_name) { 339 return static_cast<llvm::support::ulittle32_t>( 340 read_register_u32_raw(reg_ctx, reg_name)); 341 } 342 343 llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, 344 const std::string ®_name) { 345 return static_cast<llvm::support::ulittle64_t>( 346 read_register_u64_raw(reg_ctx, reg_name)); 347 } 348 349 lldb_private::minidump::MinidumpContext_x86_64 350 GetThreadContext_64(RegisterContext *reg_ctx) { 351 lldb_private::minidump::MinidumpContext_x86_64 thread_context; 352 thread_context.context_flags = static_cast<uint32_t>( 353 lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag | 354 lldb_private::minidump::MinidumpContext_x86_64_Flags::Control | 355 lldb_private::minidump::MinidumpContext_x86_64_Flags::Segments | 356 lldb_private::minidump::MinidumpContext_x86_64_Flags::Integer); 357 thread_context.rax = read_register_u64(reg_ctx, "rax"); 358 thread_context.rbx = read_register_u64(reg_ctx, "rbx"); 359 thread_context.rcx = read_register_u64(reg_ctx, "rcx"); 360 thread_context.rdx = read_register_u64(reg_ctx, "rdx"); 361 thread_context.rdi = read_register_u64(reg_ctx, "rdi"); 362 thread_context.rsi = read_register_u64(reg_ctx, "rsi"); 363 thread_context.rbp = read_register_u64(reg_ctx, "rbp"); 364 thread_context.rsp = read_register_u64(reg_ctx, "rsp"); 365 thread_context.r8 = read_register_u64(reg_ctx, "r8"); 366 thread_context.r9 = read_register_u64(reg_ctx, "r9"); 367 thread_context.r10 = read_register_u64(reg_ctx, "r10"); 368 thread_context.r11 = read_register_u64(reg_ctx, "r11"); 369 thread_context.r12 = read_register_u64(reg_ctx, "r12"); 370 thread_context.r13 = read_register_u64(reg_ctx, "r13"); 371 thread_context.r14 = read_register_u64(reg_ctx, "r14"); 372 thread_context.r15 = read_register_u64(reg_ctx, "r15"); 373 thread_context.rip = read_register_u64(reg_ctx, "rip"); 374 thread_context.eflags = read_register_u32(reg_ctx, "rflags"); 375 thread_context.cs = read_register_u16(reg_ctx, "cs"); 376 thread_context.fs = read_register_u16(reg_ctx, "fs"); 377 thread_context.gs = read_register_u16(reg_ctx, "gs"); 378 thread_context.ss = read_register_u16(reg_ctx, "ss"); 379 thread_context.ds = read_register_u16(reg_ctx, "ds"); 380 return thread_context; 381 } 382 383 // Function returns start and size of the memory region that contains 384 // memory location pointed to by the current stack pointer. 385 llvm::Expected<std::pair<addr_t, addr_t>> 386 findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp) { 387 MemoryRegionInfo range_info; 388 Status error = process_sp->GetMemoryRegionInfo(rsp, range_info); 389 // Skip failed memory region requests or any regions with no permissions. 390 if (error.Fail() || range_info.GetLLDBPermissions() == 0) 391 return llvm::createStringError( 392 std::errc::not_supported, 393 "unable to load stack segment of the process"); 394 395 const addr_t addr = range_info.GetRange().GetRangeBase(); 396 const addr_t size = range_info.GetRange().GetByteSize(); 397 398 if (size == 0) 399 return llvm::createStringError(std::errc::not_supported, 400 "stack segment of the process is empty"); 401 402 return std::make_pair(addr, size); 403 } 404 405 Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) { 406 constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread); 407 lldb_private::ThreadList thread_list = process_sp->GetThreadList(); 408 409 // size of the entire thread stream consists of: 410 // number of threads and threads array 411 size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) + 412 thread_list.GetSize() * minidump_thread_size; 413 // save for the ability to set up RVA 414 size_t size_before = GetCurrentDataEndOffset(); 415 416 AddDirectory(StreamType::ThreadList, thread_stream_size); 417 418 llvm::support::ulittle32_t thread_count = 419 static_cast<llvm::support::ulittle32_t>(thread_list.GetSize()); 420 m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t)); 421 422 DataBufferHeap helper_data; 423 424 const uint32_t num_threads = thread_list.GetSize(); 425 426 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { 427 ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx)); 428 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 429 Status error; 430 431 if (!reg_ctx_sp) { 432 error.SetErrorString("Unable to get the register context."); 433 return error; 434 } 435 RegisterContext *reg_ctx = reg_ctx_sp.get(); 436 auto thread_context = GetThreadContext_64(reg_ctx); 437 uint64_t rsp = read_register_u64_raw(reg_ctx, "rsp"); 438 auto expected_address_range = findStackHelper(process_sp, rsp); 439 440 if (!expected_address_range) { 441 error.SetErrorString("Unable to get the stack address."); 442 return error; 443 } 444 445 std::pair<uint64_t, uint64_t> range = std::move(*expected_address_range); 446 uint64_t addr = range.first; 447 uint64_t size = range.second; 448 449 auto data_up = std::make_unique<DataBufferHeap>(size, 0); 450 const size_t stack_bytes_read = 451 process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); 452 453 if (error.Fail()) 454 return error; 455 456 LocationDescriptor stack_memory; 457 stack_memory.DataSize = 458 static_cast<llvm::support::ulittle32_t>(stack_bytes_read); 459 stack_memory.RVA = static_cast<llvm::support::ulittle32_t>( 460 size_before + thread_stream_size + helper_data.GetByteSize()); 461 462 MemoryDescriptor stack; 463 stack.StartOfMemoryRange = static_cast<llvm::support::ulittle64_t>(addr); 464 stack.Memory = stack_memory; 465 466 helper_data.AppendData(data_up->GetBytes(), stack_bytes_read); 467 468 LocationDescriptor thread_context_memory_locator; 469 thread_context_memory_locator.DataSize = 470 static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); 471 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( 472 size_before + thread_stream_size + helper_data.GetByteSize()); 473 474 helper_data.AppendData( 475 &thread_context, 476 sizeof(lldb_private::minidump::MinidumpContext_x86_64)); 477 478 llvm::minidump::Thread t; 479 t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); 480 t.SuspendCount = static_cast<llvm::support::ulittle32_t>( 481 (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0); 482 t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0); 483 t.Priority = static_cast<llvm::support::ulittle32_t>(0); 484 t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0); 485 t.Stack = stack, t.Context = thread_context_memory_locator; 486 487 m_data.AppendData(&t, sizeof(llvm::minidump::Thread)); 488 } 489 490 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 491 return Status(); 492 } 493 494 Status MinidumpFileBuilder::AddException(const lldb::ProcessSP &process_sp) { 495 Status error; 496 lldb_private::ThreadList thread_list = process_sp->GetThreadList(); 497 498 const uint32_t num_threads = thread_list.GetSize(); 499 uint32_t stop_reason_thread_idx = 0; 500 for (stop_reason_thread_idx = 0; stop_reason_thread_idx < num_threads; 501 ++stop_reason_thread_idx) { 502 ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); 503 StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); 504 505 if (stop_info_sp && stop_info_sp->IsValid()) 506 break; 507 } 508 509 if (stop_reason_thread_idx == num_threads) { 510 error.SetErrorString("No stop reason thread found."); 511 return error; 512 } 513 514 constexpr size_t minidump_exception_size = 515 sizeof(llvm::minidump::ExceptionStream); 516 AddDirectory(StreamType::Exception, minidump_exception_size); 517 size_t size_before = GetCurrentDataEndOffset(); 518 519 ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); 520 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 521 RegisterContext *reg_ctx = reg_ctx_sp.get(); 522 auto thread_context = GetThreadContext_64(reg_ctx); 523 StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); 524 525 DataBufferHeap helper_data; 526 527 LocationDescriptor thread_context_memory_locator; 528 thread_context_memory_locator.DataSize = 529 static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); 530 thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( 531 size_before + minidump_exception_size + helper_data.GetByteSize()); 532 533 helper_data.AppendData( 534 &thread_context, sizeof(lldb_private::minidump::MinidumpContext_x86_64)); 535 536 Exception exp_record; 537 exp_record.ExceptionCode = 538 static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue()); 539 exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0); 540 exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0); 541 exp_record.ExceptionAddress = read_register_u64(reg_ctx, "rip"); 542 exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0); 543 exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); 544 // exp_record.ExceptionInformation; 545 546 ExceptionStream exp_stream; 547 exp_stream.ThreadId = 548 static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); 549 exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); 550 exp_stream.ExceptionRecord = exp_record; 551 exp_stream.ThreadContext = thread_context_memory_locator; 552 553 m_data.AppendData(&exp_stream, minidump_exception_size); 554 m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); 555 return error; 556 } 557 558 lldb_private::Status 559 MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp) { 560 Status error; 561 562 if (error.Fail()) { 563 error.SetErrorString("Process doesn't support getting memory region info."); 564 return error; 565 } 566 567 // Get interesting addresses 568 std::vector<size_t> interesting_addresses; 569 auto thread_list = process_sp->GetThreadList(); 570 for (size_t i = 0; i < thread_list.GetSize(); ++i) { 571 ThreadSP thread_sp(thread_list.GetThreadAtIndex(i)); 572 RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 573 RegisterContext *reg_ctx = reg_ctx_sp.get(); 574 575 interesting_addresses.push_back(read_register_u64(reg_ctx, "rsp")); 576 interesting_addresses.push_back(read_register_u64(reg_ctx, "rip")); 577 } 578 579 DataBufferHeap helper_data; 580 std::vector<MemoryDescriptor> mem_descriptors; 581 582 std::set<addr_t> visited_region_base_addresses; 583 for (size_t interesting_address : interesting_addresses) { 584 MemoryRegionInfo range_info; 585 error = process_sp->GetMemoryRegionInfo(interesting_address, range_info); 586 // Skip failed memory region requests or any regions with no permissions. 587 if (error.Fail() || range_info.GetLLDBPermissions() == 0) 588 continue; 589 const addr_t addr = range_info.GetRange().GetRangeBase(); 590 // Skip any regions we have already saved out. 591 if (visited_region_base_addresses.insert(addr).second == false) 592 continue; 593 const addr_t size = range_info.GetRange().GetByteSize(); 594 if (size == 0) 595 continue; 596 auto data_up = std::make_unique<DataBufferHeap>(size, 0); 597 const size_t bytes_read = 598 process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); 599 if (bytes_read == 0) 600 continue; 601 // We have a good memory region with valid bytes to store. 602 LocationDescriptor memory_dump; 603 memory_dump.DataSize = static_cast<llvm::support::ulittle32_t>(bytes_read); 604 memory_dump.RVA = 605 static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset()); 606 MemoryDescriptor memory_desc; 607 memory_desc.StartOfMemoryRange = 608 static_cast<llvm::support::ulittle64_t>(addr); 609 memory_desc.Memory = memory_dump; 610 mem_descriptors.push_back(memory_desc); 611 m_data.AppendData(data_up->GetBytes(), bytes_read); 612 } 613 614 AddDirectory(StreamType::MemoryList, 615 sizeof(llvm::support::ulittle32_t) + 616 mem_descriptors.size() * 617 sizeof(llvm::minidump::MemoryDescriptor)); 618 llvm::support::ulittle32_t memory_ranges_num(mem_descriptors.size()); 619 620 m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle32_t)); 621 for (auto memory_descriptor : mem_descriptors) { 622 m_data.AppendData(&memory_descriptor, 623 sizeof(llvm::minidump::MemoryDescriptor)); 624 } 625 626 return error; 627 } 628 629 void MinidumpFileBuilder::AddMiscInfo(const lldb::ProcessSP &process_sp) { 630 AddDirectory(StreamType::MiscInfo, 631 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 632 633 lldb_private::minidump::MinidumpMiscInfo misc_info; 634 misc_info.size = static_cast<llvm::support::ulittle32_t>( 635 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 636 // Default set flags1 to 0, in case that we will not be able to 637 // get any information 638 misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0); 639 640 lldb_private::ProcessInstanceInfo process_info; 641 process_sp->GetProcessInfo(process_info); 642 if (process_info.ProcessIDIsValid()) { 643 // Set flags1 to reflect that PID is filled in 644 misc_info.flags1 = 645 static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>( 646 lldb_private::minidump::MinidumpMiscInfoFlags::ProcessID)); 647 misc_info.process_id = 648 static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID()); 649 } 650 651 m_data.AppendData(&misc_info, 652 sizeof(lldb_private::minidump::MinidumpMiscInfo)); 653 } 654 655 std::unique_ptr<llvm::MemoryBuffer> 656 getFileStreamHelper(const std::string &path) { 657 auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path); 658 if (!maybe_stream) 659 return nullptr; 660 return std::move(maybe_stream.get()); 661 } 662 663 void MinidumpFileBuilder::AddLinuxFileStreams( 664 const lldb::ProcessSP &process_sp) { 665 std::vector<std::pair<StreamType, std::string>> files_with_stream_types = { 666 {StreamType::LinuxCPUInfo, "/proc/cpuinfo"}, 667 {StreamType::LinuxLSBRelease, "/etc/lsb-release"}, 668 }; 669 670 lldb_private::ProcessInstanceInfo process_info; 671 process_sp->GetProcessInfo(process_info); 672 if (process_info.ProcessIDIsValid()) { 673 lldb::pid_t pid = process_info.GetProcessID(); 674 std::string pid_str = std::to_string(pid); 675 files_with_stream_types.push_back( 676 {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"}); 677 files_with_stream_types.push_back( 678 {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"}); 679 files_with_stream_types.push_back( 680 {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"}); 681 files_with_stream_types.push_back( 682 {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"}); 683 files_with_stream_types.push_back( 684 {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"}); 685 files_with_stream_types.push_back( 686 {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"}); 687 files_with_stream_types.push_back( 688 {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"}); 689 } 690 691 for (const auto &entry : files_with_stream_types) { 692 StreamType stream = entry.first; 693 std::string path = entry.second; 694 auto memory_buffer = getFileStreamHelper(path); 695 696 if (memory_buffer) { 697 size_t size = memory_buffer->getBufferSize(); 698 if (size == 0) 699 continue; 700 AddDirectory(stream, size); 701 m_data.AppendData(memory_buffer->getBufferStart(), size); 702 } 703 } 704 } 705 706 Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const { 707 constexpr size_t header_size = sizeof(llvm::minidump::Header); 708 constexpr size_t directory_size = sizeof(llvm::minidump::Directory); 709 710 // write header 711 llvm::minidump::Header header; 712 header.Signature = static_cast<llvm::support::ulittle32_t>( 713 llvm::minidump::Header::MagicSignature); 714 header.Version = static_cast<llvm::support::ulittle32_t>( 715 llvm::minidump::Header::MagicVersion); 716 header.NumberOfStreams = 717 static_cast<llvm::support::ulittle32_t>(GetDirectoriesNum()); 718 header.StreamDirectoryRVA = 719 static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset()); 720 header.Checksum = static_cast<llvm::support::ulittle32_t>( 721 0u), // not used in most of the writers 722 header.TimeDateStamp = 723 static_cast<llvm::support::ulittle32_t>(std::time(nullptr)); 724 header.Flags = 725 static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag 726 727 Status error; 728 size_t bytes_written; 729 730 bytes_written = header_size; 731 error = core_file->Write(&header, bytes_written); 732 if (error.Fail() || bytes_written != header_size) { 733 if (bytes_written != header_size) 734 error.SetErrorStringWithFormat( 735 "unable to write the header (written %zd/%zd)", bytes_written, 736 header_size); 737 return error; 738 } 739 740 // write data 741 bytes_written = m_data.GetByteSize(); 742 error = core_file->Write(m_data.GetBytes(), bytes_written); 743 if (error.Fail() || bytes_written != m_data.GetByteSize()) { 744 if (bytes_written != m_data.GetByteSize()) 745 error.SetErrorStringWithFormat( 746 "unable to write the data (written %zd/%" PRIu64 ")", bytes_written, 747 m_data.GetByteSize()); 748 return error; 749 } 750 751 // write directories 752 for (const Directory &dir : m_directories) { 753 bytes_written = directory_size; 754 error = core_file->Write(&dir, bytes_written); 755 if (error.Fail() || bytes_written != directory_size) { 756 if (bytes_written != directory_size) 757 error.SetErrorStringWithFormat( 758 "unable to write the directory (written %zd/%zd)", bytes_written, 759 directory_size); 760 return error; 761 } 762 } 763 764 return error; 765 } 766 767 size_t MinidumpFileBuilder::GetDirectoriesNum() const { 768 return m_directories.size(); 769 } 770 771 size_t MinidumpFileBuilder::GetCurrentDataEndOffset() const { 772 return sizeof(llvm::minidump::Header) + m_data.GetByteSize(); 773 } 774