Error ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) { Error error; llvm::sys::ScopedLock lock(m_mutex); if (!m_session_data) { error.SetErrorString("GetMemoryRegionInfo called with no debugging session."); WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); return error; } HostProcess process = m_session_data->m_debugger->GetProcess(); lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { error.SetErrorString("GetMemoryRegionInfo called with an invalid target process."); WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); return error; } WINLOG_IFALL(WINDOWS_LOG_MEMORY, "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); void *addr = reinterpret_cast<void *>(vm_addr); MEMORY_BASIC_INFORMATION mem_info = {0}; SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); if (result == 0) { error.SetError(::GetLastError(), eErrorTypeWin32); WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", error.GetError(), vm_addr); return error; } const bool readable = IsPageReadable(mem_info.Protect); const bool executable = IsPageExecutable(mem_info.Protect); const bool writable = IsPageWritable(mem_info.Protect); info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); error.SetError(::GetLastError(), eErrorTypeWin32); WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s", BOOL_STR(readable), BOOL_STR(executable), BOOL_STR(writable)); return error; }
ErrorCode Process::getMemoryRegionInfo(Address const &address, MemoryRegionInfo &info) { if (!address.valid()) return kErrorInvalidArgument; info.clear(); return kErrorNotFound; }
Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) { Error error; llvm::sys::ScopedLock lock(m_mutex); if (!m_session_data) { error.SetErrorString("ProcessWindows::GetMemoryRegionInfo called with no debugging session."); return error; } HostProcess process = m_session_data->m_debugger->GetProcess(); lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { error.SetErrorString("ProcessWindows::GetMemoryRegionInfo called with an invalid target process."); return error; } void *addr = reinterpret_cast<void *>(vm_addr); MEMORY_BASIC_INFORMATION mem_info = {0}; SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); if (result == 0) { error.SetError(::GetLastError(), eErrorTypeWin32); return error; } bool readable = !(mem_info.Protect & PAGE_NOACCESS); bool executable = mem_info.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); bool writable = mem_info.Protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY); info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); return error; }
Error ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_info) { region_info.Clear(); const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); if (permission_entry) { if (permission_entry->Contains(load_addr)) { region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); const Flags permissions(permission_entry->data); region_info.SetReadable(permissions.Test(ePermissionsReadable) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); region_info.SetWritable(permissions.Test(ePermissionsWritable) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); region_info.SetExecutable(permissions.Test(ePermissionsExecutable) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); } else if (load_addr < permission_entry->GetRangeBase()) { region_info.GetRange().SetRangeBase(load_addr); region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); region_info.SetReadable(MemoryRegionInfo::eNo); region_info.SetWritable(MemoryRegionInfo::eNo); region_info.SetExecutable(MemoryRegionInfo::eNo); } return Error(); } return Error("invalid address"); }
ErrorCode Process::getMemoryRegionInfo(Address const &address, MemoryRegionInfo &info) { if (!address.valid()) return kErrorInvalidArgument; info.clear(); FILE *fp = ProcFS::OpenFILE(_pid, "maps"); if (fp == nullptr) { return Platform::TranslateError(); } uint64_t last = 0; bool found = false; while (!found) { // Each line can contain one path and some additional addresses and // such, so PATH_MAX * 2 should be enough. char buf[PATH_MAX * 2]; uint64_t start, end; char r, w, x, p; uint64_t offset; unsigned int devMinor, devMajor; uint64_t inode; int nread; if (std::fgets(buf, sizeof(buf), fp) == nullptr) break; if (std::sscanf(buf, "%" PRIx64 "-%" PRIx64 " %c%c%c%c %" PRIx64 " %x:%x %" PRIu64 " %n", &start, &end, &r, &w, &x, &p, &offset, &devMinor, &devMajor, &inode, &nread) != 10) { continue; } if (address >= last && address <= start) { // // A hole. // info.start = last; info.length = start - last; found = true; } else if (address >= start && address < end) { // // A defined region. // info.start = start; info.length = end - start; info.protection = 0; if (r == 'r') info.protection |= ds2::kProtectionRead; if (w == 'w') info.protection |= ds2::kProtectionWrite; if (x == 'x') info.protection |= ds2::kProtectionExecute; while (buf[nread] != '\0' && std::isspace(buf[nread])) ++nread; info.backingFile = buf + nread; info.backingFileOffset = offset; info.backingFileInode = inode; found = true; } else { last = end; } } std::fclose(fp); if (!found) { info.start = last; // // We need to obtain the end of the address space, first // we need to know if it's 64-bit. // ErrorCode error = updateInfo(); if (error != kSuccess && error != kErrorAlreadyExist) return error; if (CPUTypeIs64Bit(_info.cpuType)) { info.length = std::numeric_limits<uint64_t>::max() - info.start; } else { info.length = std::numeric_limits<uint32_t>::max() - info.start; } } return kSuccess; }