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;
423 return &*ExpectedStream;
426 "Failed to read minidump exception stream: {0}");
430std::optional<minidump::Range>
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}");
459 if (!
GetStream(StreamType::Memory64List).empty()) {
460 llvm::Error err = llvm::Error::success();
461 for (
const auto &memory_desc :
GetMinidumpFile().getMemory64List(err)) {
462 if (memory_desc.first.StartOfMemoryRange <= addr
463 && addr < memory_desc.first.StartOfMemoryRange + memory_desc.first.DataSize) {
464 return minidump::Range(memory_desc.first.StartOfMemoryRange, memory_desc.second);
469 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
489 const size_t offset = addr - range->start;
491 if (addr < range->start || offset >= range->range_ref.size())
494 const size_t overlap = std::min(size, range->range_ref.size() - offset);
495 return range->range_ref.slice(offset, overlap);
499 llvm::ErrorAsOutParameter ErrAsOutParam(&err);
500 return m_file->getMemory64List(err);
505 std::vector<MemoryRegionInfo> ®ions) {
510 "Failed to read memory info list: {0}");
515 for (
const MemoryInfo &entry : *ExpectedInfo) {
520 MemoryProtection prot = entry.Protect;
521 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
523 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
524 MemoryProtection::ExecuteReadWrite |
525 MemoryProtection::ExeciteWriteCopy))
529 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
530 MemoryProtection::ExecuteReadWrite |
531 MemoryProtection::ExeciteWriteCopy))
534 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
535 regions.push_back(region);
537 return !regions.empty();
542 std::vector<MemoryRegionInfo> ®ions) {
547 if (!ExpectedMemory) {
549 "Failed to read memory list: {0}");
551 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
552 if (memory_desc.Memory.DataSize == 0)
559 regions.push_back(region);
563 if (!parser.
GetStream(StreamType::Memory64List).empty()) {
564 llvm::Error err = llvm::Error::success();
566 if (memory_desc.first.DataSize == 0)
573 regions.push_back(region);
577 LLDB_LOG_ERROR(log, std::move(err),
"Failed to read memory64 list: {0}");
582 regions.shrink_to_fit();
583 return !regions.empty();
594 const auto &return_sorted = [&](
bool is_complete) {
596 return std::make_pair(std::move(result), is_complete);
599 return return_sorted(
true);
601 return return_sorted(
true);
603 return return_sorted(
false);
606#define ENUM_TO_CSTR(ST) \
607 case StreamType::ST: \
612 switch (stream_type) {
660 return "unknown stream type";
667 auto pos = llvm::upper_bound(regions, load_addr);
668 if (pos != regions.begin() &&
669 std::prev(pos)->GetRange().Contains(load_addr)) {
670 return *std::prev(pos);
673 if (pos == regions.begin())
678 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()
std::optional< Range > FindMemoryRange(lldb::addr_t addr)
const llvm::minidump::ExceptionStream * GetExceptionStream()
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]