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 } 114