//===-- MinidumpParser.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MinidumpParser.h" #include "NtStructures.h" #include "RegisterContextMinidump_x86_32.h" #include "Plugins/Process/Utility/LinuxProcMaps.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" // C includes // C++ includes #include <algorithm> #include <map> #include <optional> #include <vector> #include <utility> usingnamespacelldb_private; usingnamespaceminidump; llvm::Expected<MinidumpParser> MinidumpParser::Create(const lldb::DataBufferSP &data_sp) { … } MinidumpParser::MinidumpParser(lldb::DataBufferSP data_sp, std::unique_ptr<llvm::object::MinidumpFile> file) : … { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetData() { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetStream(StreamType stream_type) { … } UUID MinidumpParser::GetModuleUUID(const minidump::Module *module) { … } llvm::ArrayRef<minidump::Thread> MinidumpParser::GetThreads() { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetThreadContext(const LocationDescriptor &location) { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetThreadContext(const minidump::Thread &td) { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetThreadContextWow64(const minidump::Thread &td) { … } ArchSpec MinidumpParser::GetArchitecture() { … } const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() { … } std::optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() { … } std::optional<lldb::pid_t> MinidumpParser::GetPid() { … } llvm::ArrayRef<minidump::Module> MinidumpParser::GetModuleList() { … } static bool CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser, std::vector<MemoryRegionInfo> ®ions) { … } /// Check for the memory regions starting at \a load_addr for a contiguous /// section that has execute permissions that matches the module path. /// /// When we load a breakpad generated minidump file, we might have the /// /proc/<pid>/maps text for a process that details the memory map of the /// process that the minidump is describing. This checks the sorted memory /// regions for a section that has execute permissions. A sample maps files /// might look like: /// /// 00400000-00401000 r--p 00000000 fd:01 2838574 /tmp/a.out /// 00401000-00402000 r-xp 00001000 fd:01 2838574 /tmp/a.out /// 00402000-00403000 r--p 00002000 fd:01 2838574 /tmp/a.out /// 00403000-00404000 r--p 00002000 fd:01 2838574 /tmp/a.out /// 00404000-00405000 rw-p 00003000 fd:01 2838574 /tmp/a.out /// ... /// /// This function should return true when given 0x00400000 and "/tmp/a.out" /// is passed in as the path since it has a consecutive memory region for /// "/tmp/a.out" that has execute permissions at 0x00401000. This will help us /// differentiate if a file has been memory mapped into a process for reading /// and breakpad ends up saving a minidump file that has two module entries for /// a given file: one that is read only for the entire file, and then one that /// is the real executable that is loaded into memory for execution. For memory /// mapped files they will typically show up and r--p permissions and a range /// matcning the entire range of the file on disk: /// /// 00800000-00805000 r--p 00000000 fd:01 2838574 /tmp/a.out /// 00805000-00806000 r-xp 00001000 fd:01 1234567 /usr/lib/libc.so /// /// This function should return false when asked about 0x00800000 with /// "/tmp/a.out" as the path. /// /// \param[in] path /// The path to the module to check for in the memory regions. Only sequential /// memory regions whose paths match this path will be considered when looking /// for execute permissions. /// /// \param[in] regions /// A sorted list of memory regions obtained from a call to /// CreateRegionsCacheFromLinuxMaps. /// /// \param[in] base_of_image /// The load address of this module from BaseOfImage in the modules list. /// /// \return /// True if a contiguous region of memory belonging to the module with a /// matching path exists that has executable permissions. Returns false if /// \a regions is empty or if there are no regions with execute permissions /// that match \a path. static bool CheckForLinuxExecutable(ConstString path, const MemoryRegionInfos ®ions, lldb::addr_t base_of_image) { … } std::vector<const minidump::Module *> MinidumpParser::GetFilteredModuleList() { … } llvm::iterator_range<ExceptionStreamsIterator> MinidumpParser::GetExceptionStreams() { … } std::optional<minidump::Range> MinidumpParser::FindMemoryRange(lldb::addr_t addr) { … } llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr, size_t size) { … } llvm::iterator_range<FallibleMemory64Iterator> MinidumpParser::GetMemory64Iterator(llvm::Error &err) { … } static bool CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser, std::vector<MemoryRegionInfo> ®ions) { … } static bool CreateRegionsCacheFromMemoryList(MinidumpParser &parser, std::vector<MemoryRegionInfo> ®ions) { … } std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() { … } #define ENUM_TO_CSTR(ST) … llvm::StringRef MinidumpParser::GetStreamTypeAsString(StreamType stream_type) { … } MemoryRegionInfo MinidumpParser::GetMemoryRegionInfo(const MemoryRegionInfos ®ions, lldb::addr_t load_addr) { … }