29llvm::Expected<MinidumpParser>
31 auto ExpectedFile = llvm::object::MinidumpFile::create(
32 llvm::MemoryBufferRef(toStringRef(data_sp->GetData()),
"minidump"));
34 return ExpectedFile.takeError();
40 std::unique_ptr<llvm::object::MinidumpFile> file)
44 return llvm::ArrayRef<uint8_t>(
m_data_sp->GetBytes(),
49 return m_file->getRawStream(stream_type).value_or(llvm::ArrayRef<uint8_t>());
52std::optional<llvm::ArrayRef<uint8_t>>
54 return m_file->getRawStream(stream_type);
59 GetData().slice(module->CvRecord.RVA, module->CvRecord.DataSize);
62 const llvm::support::ulittle32_t *signature =
nullptr;
68 static_cast<CvSignature>(
static_cast<uint32_t
>(*signature));
76 if (pdb70_uuid->
Age != 0)
77 return UUID(pdb70_uuid,
sizeof(*pdb70_uuid));
78 return UUID(&pdb70_uuid->
Uuid,
sizeof(pdb70_uuid->
Uuid));
80 return UUID(*pdb70_uuid);
82 return UUID(cv_record);
90 return *ExpectedThreads;
93 "Failed to read thread list: {0}");
97llvm::ArrayRef<uint8_t>
99 if (location.RVA + location.DataSize >
GetData().size())
101 return GetData().slice(location.RVA, location.DataSize);
104llvm::ArrayRef<uint8_t>
109llvm::ArrayRef<uint8_t>
118 auto teb_mem_maybe =
GetMemory(td.EnvironmentBlock,
sizeof(
TEB64));
119 if (!teb_mem_maybe) {
121 "Failed to read Thread Environment Block: {0}");
125 auto teb_mem = *teb_mem_maybe;
129 const TEB64 *wow64teb;
139 if (!context_maybe) {
141 "Failed to read WOW Thread Context: {0}");
145 auto context = *context_maybe;
161 llvm::Expected<const SystemInfo &> system_info =
m_file->getSystemInfo();
165 "Failed to read SystemInfo stream: {0}");
173 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
175 switch (system_info->ProcessorArch) {
176 case ProcessorArchitecture::X86:
177 triple.setArch(llvm::Triple::ArchType::x86);
179 case ProcessorArchitecture::AMD64:
180 triple.setArch(llvm::Triple::ArchType::x86_64);
182 case ProcessorArchitecture::ARM:
183 triple.setArch(llvm::Triple::ArchType::arm);
185 case ProcessorArchitecture::ARM64:
186 case ProcessorArchitecture::BP_ARM64:
187 triple.setArch(llvm::Triple::ArchType::aarch64);
190 triple.setArch(llvm::Triple::ArchType::UnknownArch);
195 switch (system_info->PlatformId) {
196 case OSPlatform::Win32S:
197 case OSPlatform::Win32Windows:
198 case OSPlatform::Win32NT:
199 case OSPlatform::Win32CE:
200 triple.setOS(llvm::Triple::OSType::Win32);
201 triple.setVendor(llvm::Triple::VendorType::PC);
203 case OSPlatform::Linux:
204 triple.setOS(llvm::Triple::OSType::Linux);
206 case OSPlatform::MacOSX:
207 triple.setOS(llvm::Triple::OSType::MacOSX);
208 triple.setVendor(llvm::Triple::Apple);
210 case OSPlatform::IOS:
211 triple.setOS(llvm::Triple::OSType::IOS);
212 triple.setVendor(llvm::Triple::Apple);
214 case OSPlatform::Android:
215 triple.setOS(llvm::Triple::OSType::Linux);
216 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
219 triple.setOS(llvm::Triple::OSType::UnknownOS);
220 auto ExpectedCSD =
m_file->getString(system_info->CSDVersionRVA);
223 "Failed to CSD Version string: {0}");
225 if (ExpectedCSD->find(
"Linux") != std::string::npos)
226 triple.setOS(llvm::Triple::OSType::Linux);
236 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::MiscInfo);
238 if (data.size() == 0)
245 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::LinuxProcStatus);
247 if (data.size() == 0)
255 if (misc_info !=
nullptr) {
256 return misc_info->
GetPid();
261 return proc_status->GetPid();
270 return *ExpectedModules;
273 "Failed to read module list: {0}");
279 std::vector<MemoryRegionInfo> ®ions) {
280 auto data = parser.
GetStream(StreamType::LinuxMaps);
286 llvm::toStringRef(data),
287 [®ions, &log](llvm::Expected<MemoryRegionInfo> region) ->
bool {
289 regions.push_back(*region);
292 "Reading memory region from minidump failed: {0}");
295 return !regions.empty();
355 while (region.
GetName() == path) {
367 if (!ExpectedModules) {
369 "Failed to read module list: {0}");
380 llvm::sort(linux_regions);
383 typedef llvm::StringMap<size_t> MapType;
384 MapType module_name_to_filtered_index;
386 std::vector<const minidump::Module *> filtered_modules;
388 for (
const auto &module : *ExpectedModules) {
389 auto ExpectedName =
m_file->getString(module.ModuleNameRVA);
392 "Failed to get module name: {0}");
396 MapType::iterator iter;
401 std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
402 *ExpectedName, filtered_modules.size());
408 filtered_modules.push_back(&module);
418 auto dup_module = filtered_modules[iter->second];
422 bool dup_is_executable =
425 if (is_executable != dup_is_executable) {
427 filtered_modules[iter->second] = &
module;
433 if (module.BaseOfImage < dup_module->BaseOfImage)
434 filtered_modules[iter->second] = &
module;
437 return filtered_modules;
440llvm::iterator_range<ExceptionStreamsIterator>
445std::optional<minidump::Range>
461 if (ExpectedMemory) {
462 for (
const auto &memory_desc : *ExpectedMemory) {
463 const LocationDescriptor &loc_desc = memory_desc.Memory;
464 const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
465 const size_t range_size = loc_desc.DataSize;
467 if (!ExpectedSlice) {
469 "Failed to get memory slice: {0}");
473 range_start, range_size,
478 "Failed to read memory list: {0}");
481 if (!
GetStream(StreamType::Memory64List).empty()) {
482 llvm::Error err = llvm::Error::success();
483 for (
const auto &memory_desc :
GetMinidumpFile().getMemory64List(err)) {
485 memory_desc.first.StartOfMemoryRange, memory_desc.first.DataSize,
487 memory_desc.second)));
491 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
497llvm::Expected<llvm::ArrayRef<uint8_t>>
501 return llvm::createStringError(
502 llvm::inconvertibleErrorCode(),
503 "No memory range found for address (0x%" PRIx64
")", addr);
509 const size_t offset = addr - range->start;
511 if (addr < range->start || offset >= range->range_ref.size())
512 return llvm::createStringError(
513 llvm::inconvertibleErrorCode(),
514 "Address (0x%" PRIx64
") is not in range [0x%" PRIx64
" - 0x%" PRIx64
516 addr, range->start, range->start + range->range_ref.size());
518 const size_t overlap = std::min(size, range->range_ref.size() - offset);
519 return range->range_ref.slice(offset, overlap);
522llvm::iterator_range<FallibleMemory64Iterator>
524 llvm::ErrorAsOutParameter ErrAsOutParam(&err);
525 return m_file->getMemory64List(err);
530 std::vector<MemoryRegionInfo> ®ions) {
535 "Failed to read memory info list: {0}");
540 for (
const MemoryInfo &entry : *ExpectedInfo) {
545 MemoryProtection prot = entry.Protect;
546 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
548 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
549 MemoryProtection::ExecuteReadWrite |
550 MemoryProtection::ExeciteWriteCopy))
554 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
555 MemoryProtection::ExecuteReadWrite |
556 MemoryProtection::ExeciteWriteCopy))
559 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
560 regions.push_back(region);
562 return !regions.empty();
567 std::vector<MemoryRegionInfo> ®ions) {
572 if (!ExpectedMemory) {
574 "Failed to read memory list: {0}");
576 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
577 if (memory_desc.Memory.DataSize == 0)
584 regions.push_back(region);
588 if (!parser.
GetStream(StreamType::Memory64List).empty()) {
589 llvm::Error err = llvm::Error::success();
591 if (memory_desc.first.DataSize == 0)
598 regions.push_back(region);
602 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
607 regions.shrink_to_fit();
608 return !regions.empty();
619 const auto &return_sorted = [&](
bool is_complete) {
621 return std::make_pair(std::move(result), is_complete);
624 return return_sorted(
true);
626 return return_sorted(
true);
628 return return_sorted(
false);
631#define ENUM_TO_CSTR(ST) \
632 case StreamType::ST: \
636 switch (stream_type) {
685 return "unknown stream type";
692 auto pos = llvm::upper_bound(regions, load_addr);
693 if (pos != regions.begin() &&
694 std::prev(pos)->GetRange().Contains(load_addr)) {
695 return *std::prev(pos);
698 if (pos == regions.begin())
703 if (pos == regions.end())
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
static bool CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser, std::vector< MemoryRegionInfo > ®ions)
static bool CheckForLinuxExecutable(ConstString path, const MemoryRegionInfos ®ions, lldb::addr_t base_of_image)
Check for the memory regions starting at load_addr for a contiguous section that has execute permissi...
static bool CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser, std::vector< MemoryRegionInfo > ®ions)
static bool CreateRegionsCacheFromMemoryList(MinidumpParser &parser, std::vector< MemoryRegionInfo > ®ions)
An architecture specification class.
A uniqued constant string class.
void SetMapped(OptionalBool val)
ConstString GetName() const
void SetReadable(OptionalBool val)
void SetExecutable(OptionalBool val)
void SetWritable(OptionalBool val)
OptionalBool GetExecutable() const
A collection class for Module objects.
RangeData< lldb::addr_t, lldb::addr_t, minidump::Range > Entry
Represents UUID's of various sizes.
static std::optional< LinuxProcStatus > Parse(llvm::ArrayRef< uint8_t > &data)
MinidumpParser(lldb::DataBufferSP data_sp, std::unique_ptr< llvm::object::MinidumpFile > file)
std::pair< MemoryRegionInfos, bool > BuildMemoryRegions()
Returns a list of memory regions and a flag indicating whether the list is complete (includes all reg...
llvm::ArrayRef< minidump::Module > GetModuleList()
llvm::object::MinidumpFile & GetMinidumpFile()
ArchSpec GetArchitecture()
llvm::ArrayRef< uint8_t > GetData()
static MemoryRegionInfo GetMemoryRegionInfo(const MemoryRegionInfos ®ions, lldb::addr_t load_addr)
MemoryRangeVector m_memory_ranges
llvm::ArrayRef< uint8_t > GetStream(StreamType stream_type)
std::optional< lldb::pid_t > GetPid()
std::optional< llvm::ArrayRef< uint8_t > > GetRawStream(StreamType stream_type)
llvm::iterator_range< ExceptionStreamsIterator > GetExceptionStreams()
std::optional< Range > FindMemoryRange(lldb::addr_t addr)
void PopulateMemoryRanges()
static llvm::Expected< MinidumpParser > Create(const lldb::DataBufferSP &data_buf_sp)
std::unique_ptr< llvm::object::MinidumpFile > m_file
std::vector< const minidump::Module * > GetFilteredModuleList()
llvm::iterator_range< FallibleMemory64Iterator > GetMemory64Iterator(llvm::Error &err)
lldb::DataBufferSP m_data_sp
std::optional< LinuxProcStatus > GetLinuxProcStatus()
llvm::ArrayRef< uint8_t > GetThreadContext(const LocationDescriptor &location)
llvm::ArrayRef< uint8_t > GetThreadContextWow64(const minidump::Thread &td)
UUID GetModuleUUID(const minidump::Module *module)
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type)
llvm::ArrayRef< minidump::Thread > GetThreads()
llvm::Expected< llvm::ArrayRef< uint8_t > > GetMemory(lldb::addr_t addr, size_t size)
const MinidumpMiscInfo * GetMiscInfo()
Status consumeObject(llvm::ArrayRef< uint8_t > &Buffer, const T *&Object)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
void ParseLinuxMapRegions(llvm::StringRef linux_map, LinuxMapCallback const &callback)
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
void SetRangeEnd(BaseType end)
SizeType GetByteSize() const
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
void SetByteSize(SizeType s)
struct lldb_private::UUID::CvRecordPdb70::@031031370151201011001273071037042037235035311007 Uuid
llvm::support::ulittle32_t Age
static const MinidumpMiscInfo * Parse(llvm::ArrayRef< uint8_t > &data)
std::optional< lldb::pid_t > GetPid() const
llvm::support::ulittle64_t tls_slots[64]