diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp | 112 | 
1 files changed, 112 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp new file mode 100644 index 000000000000..1ba432aa542b --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp @@ -0,0 +1,112 @@ +//===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===// +// +// 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 "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; +  } +}  | 
