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