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>
432 llvm::ArrayRef<uint8_t> data64 =
GetStream(StreamType::Memory64List);
436 if (!ExpectedMemory) {
438 "Failed to read memory list: {0}");
440 for (
const auto &memory_desc : *ExpectedMemory) {
441 const LocationDescriptor &loc_desc = memory_desc.Memory;
442 const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
443 const size_t range_size = loc_desc.DataSize;
445 if (loc_desc.RVA + loc_desc.DataSize >
GetData().size())
448 if (range_start <= addr && addr < range_start + range_size) {
450 if (!ExpectedSlice) {
452 "Failed to get memory slice: {0}");
465 if (!data64.empty()) {
466 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
468 std::tie(memory64_list, base_rva) =
471 if (memory64_list.empty())
474 for (
const auto &memory_desc64 : memory64_list) {
475 const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
476 const size_t range_size = memory_desc64.data_size;
478 if (base_rva + range_size >
GetData().size())
481 if (range_start <= addr && addr < range_start + range_size) {
483 GetData().slice(base_rva, range_size));
485 base_rva += range_size;
506 const size_t offset = addr - range->start;
508 if (addr < range->start || offset >= range->range_ref.size())
511 const size_t overlap = std::min(size, range->range_ref.size() - offset);
512 return range->range_ref.slice(offset, overlap);
517 std::vector<MemoryRegionInfo> ®ions) {
522 "Failed to read memory info list: {0}");
527 for (
const MemoryInfo &entry : *ExpectedInfo) {
532 MemoryProtection prot = entry.Protect;
533 region.
SetReadable(
bool(prot & MemoryProtection::NoAccess) ? no : yes);
535 bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
536 MemoryProtection::ExecuteReadWrite |
537 MemoryProtection::ExeciteWriteCopy))
541 bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
542 MemoryProtection::ExecuteReadWrite |
543 MemoryProtection::ExeciteWriteCopy))
546 region.
SetMapped(entry.State != MemoryState::Free ? yes : no);
547 regions.push_back(region);
549 return !regions.empty();
554 std::vector<MemoryRegionInfo> ®ions) {
557 if (!ExpectedMemory) {
559 "Failed to read memory list: {0}");
562 regions.reserve(ExpectedMemory->size());
563 for (
const MemoryDescriptor &memory_desc : *ExpectedMemory) {
564 if (memory_desc.Memory.DataSize == 0)
571 regions.push_back(region);
573 regions.shrink_to_fit();
574 return !regions.empty();
579 std::vector<MemoryRegionInfo> ®ions) {
580 llvm::ArrayRef<uint8_t> data =
581 parser.
GetStream(StreamType::Memory64List);
584 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
586 std::tie(memory64_list, base_rva) =
589 if (memory64_list.empty())
592 regions.reserve(memory64_list.size());
593 for (
const auto &memory_desc : memory64_list) {
594 if (memory_desc.data_size == 0)
601 regions.push_back(region);
603 regions.shrink_to_fit();
604 return !regions.empty();
615 const auto &return_sorted = [&](
bool is_complete) {
617 return std::make_pair(std::move(result), is_complete);
620 return return_sorted(
true);
622 return return_sorted(
true);
624 return return_sorted(
false);
626 return return_sorted(
false);
629#define ENUM_TO_CSTR(ST) \
630 case StreamType::ST: \
635 switch (stream_type) {
683 return "unknown stream type";
690 auto pos = llvm::upper_bound(regions, load_addr);
691 if (pos != regions.begin() &&
692 std::prev(pos)->GetRange().Contains(load_addr)) {
693 return *std::prev(pos);
696 if (pos == regions.begin())
701 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 CreateRegionsCacheFromMemory64List(MinidumpParser &parser, std::vector< MemoryRegionInfo > ®ions)
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()
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 std::pair< llvm::ArrayRef< MinidumpMemoryDescriptor64 >, uint64_t > ParseMemory64List(llvm::ArrayRef< uint8_t > &data)
static const MinidumpMiscInfo * Parse(llvm::ArrayRef< uint8_t > &data)
std::optional< lldb::pid_t > GetPid() const
llvm::support::ulittle64_t tls_slots[64]