1 //===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "LinuxProcMaps.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "lldb/Target/MemoryRegionInfo.h"
13 #include "lldb/Utility/Status.h"
14 #include "lldb/Utility/StringExtractor.h"
16 using namespace lldb_private;
19 ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef maps_line,
20 MemoryRegionInfo &memory_region_info) {
21 memory_region_info.Clear();
23 StringExtractor line_extractor(maps_line);
25 // Format: {address_start_hex}-{address_end_hex} perms offset dev inode
26 // pathname perms: rwxp (letter is present if set, '-' if not, final
27 // character is p=private, s=shared).
29 // Parse out the starting address
30 lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
32 // Parse out hyphen separating start and end address from range.
33 if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
35 "malformed /proc/{pid}/maps entry, missing dash between address range");
37 // Parse out the ending address
38 lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
40 // Parse out the space after the address.
41 if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
43 "malformed /proc/{pid}/maps entry, missing space after range");
46 memory_region_info.GetRange().SetRangeBase(start_address);
47 memory_region_info.GetRange().SetRangeEnd(end_address);
49 // Any memory region in /proc/{pid}/maps is by definition mapped into the
51 memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
53 // Parse out each permission entry.
54 if (line_extractor.GetBytesLeft() < 4)
55 return Status("malformed /proc/{pid}/maps entry, missing some portion of "
58 // Handle read permission.
59 const char read_perm_char = line_extractor.GetChar();
60 if (read_perm_char == 'r')
61 memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
62 else if (read_perm_char == '-')
63 memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
65 return Status("unexpected /proc/{pid}/maps read permission char");
67 // Handle write permission.
68 const char write_perm_char = line_extractor.GetChar();
69 if (write_perm_char == 'w')
70 memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
71 else if (write_perm_char == '-')
72 memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
74 return Status("unexpected /proc/{pid}/maps write permission char");
76 // Handle execute permission.
77 const char exec_perm_char = line_extractor.GetChar();
78 if (exec_perm_char == 'x')
79 memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
80 else if (exec_perm_char == '-')
81 memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
83 return Status("unexpected /proc/{pid}/maps exec permission char");
85 line_extractor.GetChar(); // Read the private bit
86 line_extractor.SkipSpaces(); // Skip the separator
87 line_extractor.GetHexMaxU64(false, 0); // Read the offset
88 line_extractor.GetHexMaxU64(false, 0); // Read the major device number
89 line_extractor.GetChar(); // Read the device id separator
90 line_extractor.GetHexMaxU64(false, 0); // Read the major device number
91 line_extractor.SkipSpaces(); // Skip the separator
92 line_extractor.GetU64(0, 10); // Read the inode number
94 line_extractor.SkipSpaces();
95 const char *name = line_extractor.Peek();
97 memory_region_info.SetName(name);
102 void lldb_private::ParseLinuxMapRegions(llvm::StringRef linux_map,
103 LinuxMapCallback const &callback) {
104 llvm::StringRef lines(linux_map);
105 llvm::StringRef line;
106 while (!lines.empty()) {
107 std::tie(line, lines) = lines.split('\n');
108 MemoryRegionInfo region;
109 Status error = ParseMemoryRegionInfoFromProcMapsLine(line, region);
110 if (!callback(region, error))