27using namespace minidump;
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)
41 : m_data_sp(std::move(data_sp)), m_file(std::move(file)) {}
44 return llvm::ArrayRef<uint8_t>(
m_data_sp->GetBytes(),
49 return m_file->getRawStream(stream_type).value_or(llvm::ArrayRef<uint8_t>());
54 GetData().slice(module->CvRecord.RVA, module->CvRecord.DataSize);
57 const llvm::support::ulittle32_t *signature =
nullptr;
63 static_cast<CvSignature>(
static_cast<uint32_t
>(*signature));
71 if (pdb70_uuid->
Age != 0)
72 return UUID(pdb70_uuid,
sizeof(*pdb70_uuid));
74 sizeof(pdb70_uuid->
Uuid));
76 return UUID(*pdb70_uuid);
78 return UUID(cv_record);
86 return *ExpectedThreads;
89 "Failed to read thread list: {0}");
93llvm::ArrayRef<uint8_t>
95 if (location.RVA + location.DataSize >
GetData().size())
97 return GetData().slice(location.RVA, location.DataSize);
100llvm::ArrayRef<uint8_t>
105llvm::ArrayRef<uint8_t>
117 const TEB64 *wow64teb;
141 llvm::Expected<const SystemInfo &> system_info =
m_file->getSystemInfo();
145 "Failed to read SystemInfo stream: {0}");
153 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
155 switch (system_info->ProcessorArch) {
156 case ProcessorArchitecture::X86:
157 triple.setArch(llvm::Triple::ArchType::x86);
159 case ProcessorArchitecture::AMD64:
160 triple.setArch(llvm::Triple::ArchType::x86_64);
162 case ProcessorArchitecture::ARM:
163 triple.setArch(llvm::Triple::ArchType::arm);
165 case ProcessorArchitecture::ARM64:
166 case ProcessorArchitecture::BP_ARM64:
167 triple.setArch(llvm::Triple::ArchType::aarch64);
170 triple.setArch(llvm::Triple::ArchType::UnknownArch);
175 switch (system_info->PlatformId) {
176 case OSPlatform::Win32S:
177 case OSPlatform::Win32Windows:
178 case OSPlatform::Win32NT:
179 case OSPlatform::Win32CE:
180 triple.setOS(llvm::Triple::OSType::Win32);
181 triple.setVendor(llvm::Triple::VendorType::PC);
183 case OSPlatform::Linux:
184 triple.setOS(llvm::Triple::OSType::Linux);
186 case OSPlatform::MacOSX:
187 triple.setOS(llvm::Triple::OSType::MacOSX);
188 triple.setVendor(llvm::Triple::Apple);
190 case OSPlatform::IOS:
191 triple.setOS(llvm::Triple::OSType::IOS);
192 triple.setVendor(llvm::Triple::Apple);
194 case OSPlatform::Android:
195 triple.setOS(llvm::Triple::OSType::Linux);
196 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
199 triple.setOS(llvm::Triple::OSType::UnknownOS);
200 auto ExpectedCSD =
m_file->getString(system_info->CSDVersionRVA);
203 "Failed to CSD Version string: {0}");
205 if (ExpectedCSD->find(
"Linux") != std::string::npos)
206 triple.setOS(llvm::Triple::OSType::Linux);
216 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::MiscInfo);
218 if (data.size() == 0)
225 llvm::ArrayRef<uint8_t> data =
GetStream(StreamType::LinuxProcStatus);
227 if (data.size() == 0)
235 if (misc_info !=
nullptr) {
236 return misc_info->
GetPid();
241 return proc_status->GetPid();
250 return *ExpectedModules;
253 "Failed to read module list: {0}");
259 std::vector<MemoryRegionInfo> ®ions) {
260 auto data = parser.
GetStream(StreamType::LinuxMaps);
266 llvm::toStringRef(data),
267 [®ions, &log](llvm::Expected<MemoryRegionInfo> region) ->
bool {
269 regions.push_back(*region);
272 "Reading memory region from minidump failed: {0}");
275 return !regions.empty();
335 while (region.
GetName() == path) {
347 if (!ExpectedModules) {
349 "Failed to read module list: {0}");
360 llvm::sort(linux_regions);
363 typedef llvm::StringMap<size_t> MapType;
364 MapType module_name_to_filtered_index;
366 std::vector<const minidump::Module *> filtered_modules;
368 for (
const auto &module : *ExpectedModules) {
369 auto ExpectedName =
m_file->getString(module.ModuleNameRVA);
372 "Failed to get module name: {0}");
376 MapType::iterator iter;
381 std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
382 *ExpectedName, filtered_modules.size());
388 filtered_modules.push_back(&module);
398 auto dup_module = filtered_modules[iter->second];
402 bool dup_is_executable =
405 if (is_executable != dup_is_executable) {
407 filtered_modules[iter->second] = &module;
413 if (module.BaseOfImage < dup_module->BaseOfImage)
414 filtered_modules[iter->second] = &module;
417 return filtered_modules;
420llvm::iterator_range<ExceptionStreamsIterator>
425std::optional<minidump::Range>
430 if (!ExpectedMemory) {
432 "Failed to read memory list: {0}");
434 for (
const auto &memory_desc : *ExpectedMemory) {
435 const LocationDescriptor &loc_desc = memory_desc.Memory;
436 const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
437 const size_t range_size = loc_desc.DataSize;
439 if (loc_desc.RVA + loc_desc.DataSize >
GetData().size())
442 if (range_start <= addr && addr < range_start + range_size) {
444 if (!ExpectedSlice) {
446 "Failed to get memory slice: {0}");
454 if (!
GetStream(StreamType::Memory64List).empty()) {
455 llvm::Error err = llvm::Error::success();
456 for (
const auto &memory_desc :
GetMinidumpFile().getMemory64List(err)) {
457 if (memory_desc.first.StartOfMemoryRange <= addr
458 && addr < memory_desc.first.StartOfMemoryRange + memory_desc.first.DataSize) {
459 return minidump::Range(memory_desc.first.StartOfMemoryRange, memory_desc.second);
464 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
484 const size_t offset = addr - range->start;
486 if (addr < range->start || offset >= range->range_ref.size())
489 const size_t overlap = std::min(size, range->range_ref.size() - offset);
490 return range->range_ref.slice(offset, overlap);
494 llvm::ErrorAsOutParameter ErrAsOutParam(&err);
495 return m_file->getMemory64List(err);
500 std::vector<MemoryRegionInfo> ®ions) {
505 "Failed to read memory info list: {0}");
510 for (
const MemoryInfo &entry : *ExpectedInfo) {
515 MemoryProtection prot = entry.Protect;
516 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
518 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
519 MemoryProtection::ExecuteReadWrite |
520 MemoryProtection::ExeciteWriteCopy))
524 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
525 MemoryProtection::ExecuteReadWrite |
526 MemoryProtection::ExeciteWriteCopy))
529 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
530 regions.push_back(region);
532 return !regions.empty();
537 std::vector<MemoryRegionInfo> ®ions) {
542 if (!ExpectedMemory) {
544 "Failed to read memory list: {0}");
546 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
547 if (memory_desc.Memory.DataSize == 0)
554 regions.push_back(region);
558 if (!parser.
GetStream(StreamType::Memory64List).empty()) {
559 llvm::Error err = llvm::Error::success();
561 if (memory_desc.first.DataSize == 0)
568 regions.push_back(region);
572 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
577 regions.shrink_to_fit();
578 return !regions.empty();
589 const auto &return_sorted = [&](
bool is_complete) {
591 return std::make_pair(std::move(result), is_complete);
594 return return_sorted(
true);
596 return return_sorted(
true);
598 return return_sorted(
false);
601#define ENUM_TO_CSTR(ST) \
602 case StreamType::ST: \
607 switch (stream_type) {
655 return "unknown stream type";
662 auto pos = llvm::upper_bound(regions, load_addr);
663 if (pos != regions.begin() &&
664 std::prev(pos)->GetRange().Contains(load_addr)) {
665 return *std::prev(pos);
668 if (pos == regions.begin())
673 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.
bool IsValid() const
Tests if this ArchSpec is valid.
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
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.
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)
llvm::ArrayRef< uint8_t > GetStream(StreamType stream_type)
std::optional< lldb::pid_t > GetPid()
llvm::iterator_range< ExceptionStreamsIterator > GetExceptionStreams()
std::optional< Range > FindMemoryRange(lldb::addr_t addr)
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 > GetMemory(lldb::addr_t addr, size_t size)
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()
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::@41 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]