]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / Process / Utility / LinuxProcMaps.cpp
1 //===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LinuxProcMaps.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "lldb/Target/MemoryRegionInfo.h"
12 #include "lldb/Utility/Status.h"
13 #include "lldb/Utility/StringExtractor.h"
14
15 using namespace lldb_private;
16
17 static Status
18 ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef maps_line,
19                                       MemoryRegionInfo &memory_region_info) {
20   memory_region_info.Clear();
21   
22   StringExtractor line_extractor(maps_line);
23   
24   // Format: {address_start_hex}-{address_end_hex} perms offset  dev   inode
25   // pathname perms: rwxp   (letter is present if set, '-' if not, final
26   // character is p=private, s=shared).
27   
28   // Parse out the starting address
29   lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
30   
31   // Parse out hyphen separating start and end address from range.
32   if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
33     return Status(
34         "malformed /proc/{pid}/maps entry, missing dash between address range");
35   
36   // Parse out the ending address
37   lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
38   
39   // Parse out the space after the address.
40   if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
41     return Status(
42         "malformed /proc/{pid}/maps entry, missing space after range");
43   
44   // Save the range.
45   memory_region_info.GetRange().SetRangeBase(start_address);
46   memory_region_info.GetRange().SetRangeEnd(end_address);
47   
48   // Any memory region in /proc/{pid}/maps is by definition mapped into the
49   // process.
50   memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
51   
52   // Parse out each permission entry.
53   if (line_extractor.GetBytesLeft() < 4)
54     return Status("malformed /proc/{pid}/maps entry, missing some portion of "
55                   "permissions");
56   
57   // Handle read permission.
58   const char read_perm_char = line_extractor.GetChar();
59   if (read_perm_char == 'r')
60     memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
61   else if (read_perm_char == '-')
62     memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
63   else
64     return Status("unexpected /proc/{pid}/maps read permission char");
65   
66   // Handle write permission.
67   const char write_perm_char = line_extractor.GetChar();
68   if (write_perm_char == 'w')
69     memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
70   else if (write_perm_char == '-')
71     memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
72   else
73     return Status("unexpected /proc/{pid}/maps write permission char");
74   
75   // Handle execute permission.
76   const char exec_perm_char = line_extractor.GetChar();
77   if (exec_perm_char == 'x')
78     memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
79   else if (exec_perm_char == '-')
80     memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
81   else
82     return Status("unexpected /proc/{pid}/maps exec permission char");
83   
84   line_extractor.GetChar();              // Read the private bit
85   line_extractor.SkipSpaces();           // Skip the separator
86   line_extractor.GetHexMaxU64(false, 0); // Read the offset
87   line_extractor.GetHexMaxU64(false, 0); // Read the major device number
88   line_extractor.GetChar();              // Read the device id separator
89   line_extractor.GetHexMaxU64(false, 0); // Read the major device number
90   line_extractor.SkipSpaces();           // Skip the separator
91   line_extractor.GetU64(0, 10);          // Read the inode number
92   
93   line_extractor.SkipSpaces();
94   const char *name = line_extractor.Peek();
95   if (name)
96     memory_region_info.SetName(name);
97   
98   return Status();
99 }
100
101 void lldb_private::ParseLinuxMapRegions(llvm::StringRef linux_map,
102                                         LinuxMapCallback const &callback) {
103   llvm::StringRef lines(linux_map);
104   llvm::StringRef line;
105   while (!lines.empty()) {
106     std::tie(line, lines) = lines.split('\n');
107     MemoryRegionInfo region;
108     Status error = ParseMemoryRegionInfoFromProcMapsLine(line, region);
109     if (!callback(region, error))
110       break;
111   }
112 }