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