]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Process / Utility / LinuxProcMaps.cpp
1 //===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
15
16 using namespace lldb_private;
17
18 static Status
19 ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef maps_line,
20                                       MemoryRegionInfo &memory_region_info) {
21   memory_region_info.Clear();
22   
23   StringExtractor line_extractor(maps_line);
24   
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).
28   
29   // Parse out the starting address
30   lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
31   
32   // Parse out hyphen separating start and end address from range.
33   if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
34     return Status(
35         "malformed /proc/{pid}/maps entry, missing dash between address range");
36   
37   // Parse out the ending address
38   lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
39   
40   // Parse out the space after the address.
41   if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
42     return Status(
43         "malformed /proc/{pid}/maps entry, missing space after range");
44   
45   // Save the range.
46   memory_region_info.GetRange().SetRangeBase(start_address);
47   memory_region_info.GetRange().SetRangeEnd(end_address);
48   
49   // Any memory region in /proc/{pid}/maps is by definition mapped into the
50   // process.
51   memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
52   
53   // Parse out each permission entry.
54   if (line_extractor.GetBytesLeft() < 4)
55     return Status("malformed /proc/{pid}/maps entry, missing some portion of "
56                   "permissions");
57   
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);
64   else
65     return Status("unexpected /proc/{pid}/maps read permission char");
66   
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);
73   else
74     return Status("unexpected /proc/{pid}/maps write permission char");
75   
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);
82   else
83     return Status("unexpected /proc/{pid}/maps exec permission char");
84   
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
93   
94   line_extractor.SkipSpaces();
95   const char *name = line_extractor.Peek();
96   if (name)
97     memory_region_info.SetName(name);
98   
99   return Status();
100 }
101
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))
111       break;
112   }
113 }