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