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