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