26 using namespace minidump;
28 llvm::Expected<MinidumpParser>
30 auto ExpectedFile = llvm::object::MinidumpFile::create(
31 llvm::MemoryBufferRef(toStringRef(data_sp->GetData()),
"minidump"));
33 return ExpectedFile.takeError();
39 std::unique_ptr<llvm::object::MinidumpFile> file)
40 : m_data_sp(std::move(data_sp)), m_file(std::move(file)) {}
43 return llvm::ArrayRef<uint8_t>(
m_data_sp->GetBytes(),
48 return m_file->getRawStream(stream_type).value_or(llvm::ArrayRef<uint8_t>());
53 GetData().slice(module->CvRecord.RVA, module->CvRecord.DataSize);
56 const llvm::support::ulittle32_t *signature =
nullptr;
70 if (pdb70_uuid->
Age != 0)
73 sizeof(pdb70_uuid->
Uuid));
85 return *ExpectedThreads;
88 "Failed to read thread list: {0}");
92 llvm::ArrayRef<uint8_t>
94 if (location.RVA + location.DataSize >
GetData().size())
96 return GetData().slice(location.RVA, location.DataSize);
99 llvm::ArrayRef<uint8_t>
104 llvm::ArrayRef<uint8_t>
116 const TEB64 *wow64teb;
140 llvm::Expected<const SystemInfo &> system_info =
m_file->getSystemInfo();
144 "Failed to read SystemInfo stream: {0}");
152 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
154 switch (system_info->ProcessorArch) {
155 case ProcessorArchitecture::X86:
156 triple.setArch(llvm::Triple::ArchType::x86);
158 case ProcessorArchitecture::AMD64:
159 triple.setArch(llvm::Triple::ArchType::x86_64);
161 case ProcessorArchitecture::ARM:
162 triple.setArch(llvm::Triple::ArchType::arm);
164 case ProcessorArchitecture::ARM64:
165 case ProcessorArchitecture::BP_ARM64:
166 triple.setArch(llvm::Triple::ArchType::aarch64);
169 triple.setArch(llvm::Triple::ArchType::UnknownArch);
174 switch (system_info->PlatformId) {
175 case OSPlatform::Win32S:
176 case OSPlatform::Win32Windows:
177 case OSPlatform::Win32NT:
178 case OSPlatform::Win32CE:
179 triple.setOS(llvm::Triple::OSType::Win32);
180 triple.setVendor(llvm::Triple::VendorType::PC);
182 case OSPlatform::Linux:
183 triple.setOS(llvm::Triple::OSType::Linux);
185 case OSPlatform::MacOSX:
186 triple.setOS(llvm::Triple::OSType::MacOSX);
187 triple.setVendor(llvm::Triple::Apple);
189 case OSPlatform::IOS:
190 triple.setOS(llvm::Triple::OSType::IOS);
191 triple.setVendor(llvm::Triple::Apple);
193 case OSPlatform::Android:
194 triple.setOS(llvm::Triple::OSType::Linux);
195 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
198 triple.setOS(llvm::Triple::OSType::UnknownOS);
199 auto ExpectedCSD =
m_file->getString(system_info->CSDVersionRVA);
202 "Failed to CSD Version string: {0}");
204 if (ExpectedCSD->find(
"Linux") != std::string::npos)
205 triple.setOS(llvm::Triple::OSType::Linux);
215 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::MiscInfo);
217 if (data.size() == 0)
224 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::LinuxProcStatus);
226 if (data.size() == 0)
234 if (misc_info !=
nullptr) {
235 return misc_info->
GetPid();
240 return proc_status->GetPid();
249 return *ExpectedModules;
252 "Failed to read module list: {0}");
258 std::vector<MemoryRegionInfo> ®ions) {
259 auto data = parser.
GetStream(StreamType::LinuxMaps);
265 llvm::toStringRef(data),
266 [®ions, &log](llvm::Expected<MemoryRegionInfo> region) ->
bool {
268 regions.push_back(*region);
271 "Reading memory region from minidump failed: {0}");
274 return !regions.empty();
334 while (region.
GetName() == path) {
346 if (!ExpectedModules) {
348 "Failed to read module list: {0}");
359 llvm::sort(linux_regions);
362 typedef llvm::StringMap<size_t> MapType;
363 MapType module_name_to_filtered_index;
365 std::vector<const minidump::Module *> filtered_modules;
367 for (
const auto &module : *ExpectedModules) {
368 auto ExpectedName =
m_file->getString(module.ModuleNameRVA);
371 "Failed to get module name: {0}");
375 MapType::iterator iter;
380 std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
381 *ExpectedName, filtered_modules.size());
387 filtered_modules.push_back(&module);
397 auto dup_module = filtered_modules[iter->second];
401 bool dup_is_executable =
404 if (is_executable != dup_is_executable) {
406 filtered_modules[iter->second] = &module;
412 if (module.BaseOfImage < dup_module->BaseOfImage)
413 filtered_modules[iter->second] = &module;
416 return filtered_modules;
422 return &*ExpectedStream;
425 "Failed to read minidump exception stream: {0}");
429 llvm::Optional<minidump::Range>
431 llvm::ArrayRef<uint8_t> data64 =
GetStream(StreamType::Memory64List);
435 if (!ExpectedMemory) {
437 "Failed to read memory list: {0}");
439 for (
const auto &memory_desc : *ExpectedMemory) {
440 const LocationDescriptor &loc_desc = memory_desc.Memory;
441 const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
442 const size_t range_size = loc_desc.DataSize;
444 if (loc_desc.RVA + loc_desc.DataSize >
GetData().size())
447 if (range_start <= addr && addr < range_start + range_size) {
449 if (!ExpectedSlice) {
451 "Failed to get memory slice: {0}");
464 if (!data64.empty()) {
465 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
467 std::tie(memory64_list, base_rva) =
470 if (memory64_list.empty())
473 for (
const auto &memory_desc64 : memory64_list) {
474 const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
475 const size_t range_size = memory_desc64.data_size;
477 if (base_rva + range_size >
GetData().size())
480 if (range_start <= addr && addr < range_start + range_size) {
482 GetData().slice(base_rva, range_size));
484 base_rva += range_size;
505 const size_t offset = addr - range->start;
507 if (addr < range->start || offset >= range->range_ref.size())
510 const size_t overlap = std::min(size, range->range_ref.size() - offset);
511 return range->range_ref.slice(offset, overlap);
516 std::vector<MemoryRegionInfo> ®ions) {
521 "Failed to read memory info list: {0}");
526 for (
const MemoryInfo &entry : *ExpectedInfo) {
531 MemoryProtection prot = entry.Protect;
532 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
534 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
535 MemoryProtection::ExecuteReadWrite |
536 MemoryProtection::ExeciteWriteCopy))
540 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
541 MemoryProtection::ExecuteReadWrite |
542 MemoryProtection::ExeciteWriteCopy))
545 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
546 regions.push_back(region);
548 return !regions.empty();
553 std::vector<MemoryRegionInfo> ®ions) {
556 if (!ExpectedMemory) {
558 "Failed to read memory list: {0}");
561 regions.reserve(ExpectedMemory->size());
562 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
563 if (memory_desc.Memory.DataSize == 0)
570 regions.push_back(region);
572 regions.shrink_to_fit();
573 return !regions.empty();
578 std::vector<MemoryRegionInfo> ®ions) {
579 llvm::ArrayRef<uint8_t> data =
580 parser.
GetStream(StreamType::Memory64List);
583 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
585 std::tie(memory64_list, base_rva) =
588 if (memory64_list.empty())
591 regions.reserve(memory64_list.size());
592 for (
const auto &memory_desc : memory64_list) {
593 if (memory_desc.data_size == 0)
600 regions.push_back(region);
602 regions.shrink_to_fit();
603 return !regions.empty();
614 const auto &return_sorted = [&](
bool is_complete) {
616 return std::make_pair(std::move(result), is_complete);
619 return return_sorted(
true);
621 return return_sorted(
true);
623 return return_sorted(
false);
625 return return_sorted(
false);
628 #define ENUM_TO_CSTR(ST) \
629 case StreamType::ST: \
634 switch (stream_type) {
682 return "unknown stream type";
689 auto pos = llvm::upper_bound(regions, load_addr);
690 if (pos != regions.begin() &&
691 std::prev(pos)->GetRange().Contains(load_addr)) {
692 return *std::prev(pos);
695 if (pos == regions.begin())
700 if (pos == regions.end())