diff options
| author | Greg Clayton <gclayton@apple.com> | 2018-12-14 19:36:01 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2018-12-14 19:36:01 +0000 |
| commit | 026e1bf56a4be9f10131f3a3f81f11b06377a5c5 (patch) | |
| tree | 3d7789c4fc1cab6a3e05e58a9a1c2dccc2b9b545 /lldb/source/Plugins/Process/Utility | |
| parent | cac3d118ae775647f432c2d0159eca562c486744 (diff) | |
| download | bcm5719-llvm-026e1bf56a4be9f10131f3a3f81f11b06377a5c5.tar.gz bcm5719-llvm-026e1bf56a4be9f10131f3a3f81f11b06377a5c5.zip | |
Cache memory regions in ProcessMinidump and use the linux maps as the source of the information if available
Breakpad creates minidump files that sometimes have:
- linux maps textual content
- no MemoryInfoList
Right now unless the file has a MemoryInfoList we get no region information.
This patch:
- reads and caches the memory region info one time and sorts it for easy subsequent access
- get the region info from the best source in this order:
- linux maps info (if available)
- MemoryInfoList (if available)
- MemoryList or Memory64List
- returns memory region info for the gaps between regions (before the first and after the last)
Differential Revision: https://reviews.llvm.org/D55522
llvm-svn: 349182
Diffstat (limited to 'lldb/source/Plugins/Process/Utility')
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp | 113 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/LinuxProcMaps.h | 28 |
3 files changed, 142 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt index b43756acea6..e36ce4dec98 100644 --- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt +++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt @@ -5,6 +5,7 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN HistoryThread.cpp HistoryUnwind.cpp InferiorCallPOSIX.cpp + LinuxProcMaps.cpp LinuxSignals.cpp MipsLinuxSignals.cpp NativeRegisterContextRegisterInfo.cpp diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp new file mode 100644 index 00000000000..d45bf6dcd84 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp @@ -0,0 +1,113 @@ +//===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LinuxProcMaps.h" +#include "llvm/ADT/StringRef.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StringExtractor.h" + +using namespace lldb_private; + +static Status +ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef maps_line, + MemoryRegionInfo &memory_region_info) { + memory_region_info.Clear(); + + StringExtractor line_extractor(maps_line); + + // Format: {address_start_hex}-{address_end_hex} perms offset dev inode + // pathname perms: rwxp (letter is present if set, '-' if not, final + // character is p=private, s=shared). + + // Parse out the starting address + lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0); + + // Parse out hyphen separating start and end address from range. + if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-')) + return Status( + "malformed /proc/{pid}/maps entry, missing dash between address range"); + + // Parse out the ending address + lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address); + + // Parse out the space after the address. + if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' ')) + return Status( + "malformed /proc/{pid}/maps entry, missing space after range"); + + // Save the range. + memory_region_info.GetRange().SetRangeBase(start_address); + memory_region_info.GetRange().SetRangeEnd(end_address); + + // Any memory region in /proc/{pid}/maps is by definition mapped into the + // process. + memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); + + // Parse out each permission entry. + if (line_extractor.GetBytesLeft() < 4) + return Status("malformed /proc/{pid}/maps entry, missing some portion of " + "permissions"); + + // Handle read permission. + const char read_perm_char = line_extractor.GetChar(); + if (read_perm_char == 'r') + memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes); + else if (read_perm_char == '-') + memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + else + return Status("unexpected /proc/{pid}/maps read permission char"); + + // Handle write permission. + const char write_perm_char = line_extractor.GetChar(); + if (write_perm_char == 'w') + memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes); + else if (write_perm_char == '-') + memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + else + return Status("unexpected /proc/{pid}/maps write permission char"); + + // Handle execute permission. + const char exec_perm_char = line_extractor.GetChar(); + if (exec_perm_char == 'x') + memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes); + else if (exec_perm_char == '-') + memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + else + return Status("unexpected /proc/{pid}/maps exec permission char"); + + line_extractor.GetChar(); // Read the private bit + line_extractor.SkipSpaces(); // Skip the separator + line_extractor.GetHexMaxU64(false, 0); // Read the offset + line_extractor.GetHexMaxU64(false, 0); // Read the major device number + line_extractor.GetChar(); // Read the device id separator + line_extractor.GetHexMaxU64(false, 0); // Read the major device number + line_extractor.SkipSpaces(); // Skip the separator + line_extractor.GetU64(0, 10); // Read the inode number + + line_extractor.SkipSpaces(); + const char *name = line_extractor.Peek(); + if (name) + memory_region_info.SetName(name); + + return Status(); +} + +void lldb_private::ParseLinuxMapRegions(llvm::StringRef linux_map, + LinuxMapCallback const &callback) { + llvm::StringRef lines(linux_map); + llvm::StringRef line; + while (!lines.empty()) { + std::tie(line, lines) = lines.split('\n'); + MemoryRegionInfo region; + Status error = ParseMemoryRegionInfoFromProcMapsLine(line, region); + if (!callback(region, error)) + break; + } +} diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h new file mode 100644 index 00000000000..e6eabb28fc8 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.h @@ -0,0 +1,28 @@ +//===-- LinuxProcMaps.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LinuxProcMaps_H_ +#define liblldb_LinuxProcMaps_H_ + +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" +#include <functional> + + +namespace lldb_private { + +typedef std::function<bool(const lldb_private::MemoryRegionInfo &, + const lldb_private::Status &)> LinuxMapCallback; + +void ParseLinuxMapRegions(llvm::StringRef linux_map, + LinuxMapCallback const &callback); + +} // namespace lldb_private + +#endif // liblldb_LinuxProcMaps_H_ |

