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);
58 llvm::Expected<llvm::ArrayRef<uint8_t>> expected_cv_record =
60 if (!expected_cv_record) {
62 "Failed to read the CodeView record: {0}");
65 llvm::ArrayRef<uint8_t> cv_record = *expected_cv_record;
68 const llvm::support::ulittle32_t *signature =
nullptr;
74 static_cast<CvSignature>(
static_cast<uint32_t
>(*signature));
82 if (pdb70_uuid->
Age != 0)
83 return UUID(pdb70_uuid,
sizeof(*pdb70_uuid));
84 return UUID(&pdb70_uuid->
Uuid,
sizeof(pdb70_uuid->
Uuid));
86 return UUID(*pdb70_uuid);
88 return UUID(cv_record);
96 return *ExpectedThreads;
99 "Failed to read thread list: {0}");
103llvm::ArrayRef<uint8_t>
106 llvm::Expected<llvm::ArrayRef<uint8_t>> expected_context =
108 if (!expected_context) {
110 "Failed to read the thread context: {0}");
113 return *expected_context;
116llvm::ArrayRef<uint8_t>
121llvm::ArrayRef<uint8_t>
130 auto teb_mem_maybe =
GetMemory(td.EnvironmentBlock,
sizeof(
TEB64));
131 if (!teb_mem_maybe) {
133 "Failed to read Thread Environment Block: {0}");
137 auto teb_mem = *teb_mem_maybe;
141 const TEB64 *wow64teb;
151 if (!context_maybe) {
153 "Failed to read WOW Thread Context: {0}");
157 auto context = *context_maybe;
173 llvm::Expected<const SystemInfo &> system_info =
m_file->getSystemInfo();
177 "Failed to read SystemInfo stream: {0}");
185 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
187 switch (system_info->ProcessorArch) {
188 case ProcessorArchitecture::X86:
189 triple.setArch(llvm::Triple::ArchType::x86);
191 case ProcessorArchitecture::AMD64:
192 triple.setArch(llvm::Triple::ArchType::x86_64);
194 case ProcessorArchitecture::ARM:
195 triple.setArch(llvm::Triple::ArchType::arm);
197 case ProcessorArchitecture::ARM64:
198 case ProcessorArchitecture::BP_ARM64:
199 triple.setArch(llvm::Triple::ArchType::aarch64);
202 triple.setArch(llvm::Triple::ArchType::UnknownArch);
207 switch (system_info->PlatformId) {
208 case OSPlatform::Win32S:
209 case OSPlatform::Win32Windows:
210 case OSPlatform::Win32NT:
211 case OSPlatform::Win32CE:
212 triple.setOS(llvm::Triple::OSType::Win32);
213 triple.setVendor(llvm::Triple::VendorType::PC);
215 case OSPlatform::Linux:
216 triple.setOS(llvm::Triple::OSType::Linux);
218 case OSPlatform::MacOSX:
219 triple.setOS(llvm::Triple::OSType::MacOSX);
220 triple.setVendor(llvm::Triple::Apple);
222 case OSPlatform::IOS:
223 triple.setOS(llvm::Triple::OSType::IOS);
224 triple.setVendor(llvm::Triple::Apple);
226 case OSPlatform::Android:
227 triple.setOS(llvm::Triple::OSType::Linux);
228 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
231 triple.setOS(llvm::Triple::OSType::UnknownOS);
232 auto ExpectedCSD =
m_file->getString(system_info->CSDVersionRVA);
235 "Failed to CSD Version string: {0}");
237 if (ExpectedCSD->find(
"Linux") != std::string::npos)
238 triple.setOS(llvm::Triple::OSType::Linux);
248 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::MiscInfo);
250 if (data.size() == 0)
257 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::LinuxProcStatus);
259 if (data.size() == 0)
267 if (misc_info !=
nullptr) {
268 return misc_info->
GetPid();
273 return proc_status->GetPid();
282 return *ExpectedModules;
285 "Failed to read module list: {0}");
291 std::vector<MemoryRegionInfo> ®ions) {
292 auto data = parser.
GetStream(StreamType::LinuxMaps);
298 llvm::toStringRef(data),
299 [®ions, &log](llvm::Expected<MemoryRegionInfo> region) ->
bool {
301 regions.push_back(*region);
304 "Reading memory region from minidump failed: {0}");
307 return !regions.empty();
367 while (region.
GetName() == path) {
379 if (!ExpectedModules) {
381 "Failed to read module list: {0}");
392 llvm::sort(linux_regions);
395 typedef llvm::StringMap<size_t> MapType;
396 MapType module_name_to_filtered_index;
398 std::vector<const minidump::Module *> filtered_modules;
400 for (
const auto &module : *ExpectedModules) {
401 auto ExpectedName =
m_file->getString(module.ModuleNameRVA);
404 "Failed to get module name: {0}");
408 MapType::iterator iter;
413 std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
414 *ExpectedName, filtered_modules.size());
420 filtered_modules.push_back(&module);
430 auto dup_module = filtered_modules[iter->second];
434 bool dup_is_executable =
437 if (is_executable != dup_is_executable) {
439 filtered_modules[iter->second] = &
module;
445 if (module.BaseOfImage < dup_module->BaseOfImage)
446 filtered_modules[iter->second] = &
module;
449 return filtered_modules;
452llvm::iterator_range<ExceptionStreamsIterator>
457std::optional<minidump::Range>
473 if (ExpectedMemory) {
474 for (
const auto &memory_desc : *ExpectedMemory) {
475 const LocationDescriptor &loc_desc = memory_desc.Memory;
476 const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
477 const size_t range_size = loc_desc.DataSize;
479 if (!ExpectedSlice) {
481 "Failed to get memory slice: {0}");
485 range_start, range_size,
490 "Failed to read memory list: {0}");
493 if (!
GetStream(StreamType::Memory64List).empty()) {
494 llvm::Error err = llvm::Error::success();
495 for (
const auto &memory_desc :
GetMinidumpFile().getMemory64List(err)) {
497 memory_desc.first.StartOfMemoryRange, memory_desc.first.DataSize,
499 memory_desc.second)));
503 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
509llvm::Expected<llvm::ArrayRef<uint8_t>>
513 return llvm::createStringError(
514 llvm::inconvertibleErrorCode(),
515 "No memory range found for address (0x%" PRIx64
")", addr);
521 const size_t offset = addr - range->start;
523 if (addr < range->start || offset >= range->range_ref.size())
524 return llvm::createStringError(
525 llvm::inconvertibleErrorCode(),
526 "Address (0x%" PRIx64
") is not in range [0x%" PRIx64
" - 0x%" PRIx64
528 addr, range->start, range->start + range->range_ref.size());
530 const size_t overlap = std::min(size, range->range_ref.size() - offset);
531 return range->range_ref.slice(offset, overlap);
534llvm::iterator_range<FallibleMemory64Iterator>
536 llvm::ErrorAsOutParameter ErrAsOutParam(&err);
537 return m_file->getMemory64List(err);
542 std::vector<MemoryRegionInfo> ®ions) {
547 "Failed to read memory info list: {0}");
552 for (
const MemoryInfo &entry : *ExpectedInfo) {
557 MemoryProtection prot = entry.Protect;
558 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
560 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
561 MemoryProtection::ExecuteReadWrite |
562 MemoryProtection::ExeciteWriteCopy))
566 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
567 MemoryProtection::ExecuteReadWrite |
568 MemoryProtection::ExeciteWriteCopy))
571 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
572 regions.push_back(region);
574 return !regions.empty();
579 std::vector<MemoryRegionInfo> ®ions) {
584 if (!ExpectedMemory) {
586 "Failed to read memory list: {0}");
588 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
589 if (memory_desc.Memory.DataSize == 0)
596 regions.push_back(region);
600 if (!parser.
GetStream(StreamType::Memory64List).empty()) {
601 llvm::Error err = llvm::Error::success();
603 if (memory_desc.first.DataSize == 0)
610 regions.push_back(region);
614 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
619 regions.shrink_to_fit();
620 return !regions.empty();
631 const auto &return_sorted = [&](
bool is_complete) {
633 return std::make_pair(std::move(result), is_complete);
636 return return_sorted(
true);
638 return return_sorted(
true);
640 return return_sorted(
false);
643#define ENUM_TO_CSTR(ST) \
644 case StreamType::ST: \
648 switch (stream_type) {
697 return "unknown stream type";
704 auto pos = llvm::upper_bound(regions, load_addr);
705 if (pos != regions.begin() &&
706 std::prev(pos)->GetRange().Contains(load_addr)) {
707 return *std::prev(pos);
710 if (pos == regions.begin())
715 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 SetReadable(LazyBool val)
ConstString GetName() const
LazyBool GetExecutable() const
void SetMapped(LazyBool val)
void SetExecutable(LazyBool val)
void SetWritable(LazyBool val)
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::@270014123013057306020052025020177330273131255133 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]