diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index bccbb8553a916..4592b0d253a55 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -16,10 +16,8 @@ CrashInfo::CrashInfo(pid_t pid) : m_task = 0; #else m_auxvValues.fill(0); -#ifndef HAVE_PROCESS_VM_READV m_fd = -1; #endif -#endif } CrashInfo::~CrashInfo() diff --git a/src/coreclr/debug/createdump/crashinfo.h b/src/coreclr/debug/createdump/crashinfo.h index 9bdf63be49e78..46b0825c0a7e3 100644 --- a/src/coreclr/debug/createdump/crashinfo.h +++ b/src/coreclr/debug/createdump/crashinfo.h @@ -45,9 +45,8 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, #ifdef __APPLE__ vm_map_t m_task; // the mach task for the process #else -#ifndef HAVE_PROCESS_VM_READV + bool m_canUseProcVmReadSyscall; int m_fd; // /proc//mem handle -#endif #endif std::string m_coreclrPath; // the path of the coreclr module or empty if none #ifdef __APPLE__ @@ -112,7 +111,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, void VisitModule(uint64_t baseAddress, std::string& moduleName); void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr); bool EnumerateModuleMappings(); -#endif +#endif bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess); bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess); diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index d300d343d54a0..93a55394a5d8a 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -8,7 +8,6 @@ bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, std::string* name); bool CrashInfo::Initialize() { -#ifndef HAVE_PROCESS_VM_READV char memPath[128]; _snprintf_s(memPath, sizeof(memPath), sizeof(memPath), "/proc/%lu/mem", m_pid); @@ -18,12 +17,13 @@ CrashInfo::Initialize() fprintf(stderr, "open(%s) FAILED %d (%s)\n", memPath, errno, strerror(errno)); return false; } -#endif // Get the process info if (!GetStatus(m_pid, &m_ppid, &m_tgid, &m_name)) { return false; } + + m_canUseProcVmReadSyscall = true; return true; } @@ -39,13 +39,11 @@ CrashInfo::CleanupAndResumeProcess() waitpid(thread->Tid(), &waitStatus, __WALL); } } -#ifndef HAVE_PROCESS_VM_READV if (m_fd != -1) { close(m_fd); m_fd = -1; } -#endif } // @@ -253,7 +251,7 @@ CrashInfo::GetDSOInfo() int phnum = m_auxvValues[AT_PHNUM]; assert(m_auxvValues[AT_PHENT] == sizeof(Phdr)); assert(phnum != PN_XNUM); - return EnumerateElfInfo(phdrAddr, phnum); + return EnumerateElfInfo(phdrAddr, phnum); } // @@ -334,17 +332,31 @@ CrashInfo::ReadProcessMemory(void* address, void* buffer, size_t size, size_t* r { assert(buffer != nullptr); assert(read != nullptr); + *read = 0; #ifdef HAVE_PROCESS_VM_READV - iovec local{ buffer, size }; - iovec remote{ address, size }; - *read = process_vm_readv(m_pid, &local, 1, &remote, 1, 0); -#else - assert(m_fd != -1); - *read = pread64(m_fd, buffer, size, (off64_t)address); + if (m_canUseProcVmReadSyscall) + { + iovec local{ buffer, size }; + iovec remote{ address, size }; + *read = process_vm_readv(m_pid, &local, 1, &remote, 1, 0); + } + + if (!m_canUseProcVmReadSyscall || (*read == (size_t)-1 && errno == EPERM)) #endif + { + // If we've failed, avoid going through expensive syscalls + // After all, the use of process_vm_readv is largely as a + // performance optimization. + m_canUseProcVmReadSyscall = false; + assert(m_fd != -1); + *read = pread64(m_fd, buffer, size, (off64_t)address); + } + if (*read == (size_t)-1) { + int readErrno = errno; + TRACE_VERBOSE("ReadProcessMemory FAILED, addr: %" PRIA PRIx ", size: %zu, ERRNO %d: %s\n", address, size, readErrno, strerror(readErrno)); return false; } return true;