From e50b22b4f07b452b3ce7261fb543a43aa8f70b88 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Sun, 18 Dec 2016 14:48:36 -0800 Subject: [PATCH] Remove Read/WriteProcessMemory from PAL. (#8655) Ifdef more unused code that uses ReadProcessMemory. Move the current memory probing in the transport to PAL_ProbeMemory. Add PAL_ProbeMemory to dac PAL exports. PAL_ProbeMemory may be changed to use write/read on a pipe to validate the memory as soon as we make it perform as well as the current code. Remove ReadProcessMemory tests and add PAL_ProbeMemory pal tests. --- src/debug/daccess/fntableaccess.cpp | 5 +- src/debug/di/rspriv.inl | 2 +- src/debug/shared/dbgtransportsession.cpp | 36 +- src/dlls/mscordac/mscordac_unixexports.src | 1 + src/inc/livedatatarget.h | 2 + src/jit/ee_il_dll.cpp | 4 + src/pal/inc/pal.h | 26 +- src/pal/src/debug/debug.cpp | 1087 +------------------- .../palsuite/filemapping_memmgt/CMakeLists.txt | 2 +- .../CMakeLists.txt | 3 +- .../ProbeMemory/ProbeMemory_neg1/CMakeLists.txt | 19 + .../ProbeMemory_neg1/ProbeMemory_neg.cpp} | 72 +- .../ProbeMemory_neg1}/testinfo.dat | 8 +- .../ProbeMemory/test1/CMakeLists.txt | 19 + .../test1/ProbeMemory.cpp} | 70 +- .../test1}/testinfo.dat | 8 +- .../ReadProcessMemory_neg1/CMakeLists.txt | 19 - .../ReadProcessMemory/test1/CMakeLists.txt | 19 - .../ReadProcessMemory/test2/CMakeLists.txt | 36 - .../ReadProcessMemory/test2/commonconsts.h | 48 - .../ReadProcessMemory/test2/helper.cpp | 249 ----- .../ReadProcessMemory/test2/test2.cpp | 258 ----- .../ReadProcessMemory/test2/testinfo.dat | 18 - src/pal/tests/palsuite/paltestlist.txt | 2 + .../threading/DuplicateHandle/CMakeLists.txt | 1 - src/utilcode/CMakeLists.txt | 2 +- src/vm/debughelp.cpp | 11 +- 27 files changed, 154 insertions(+), 1873 deletions(-) rename src/pal/tests/palsuite/filemapping_memmgt/{ReadProcessMemory => ProbeMemory}/CMakeLists.txt (50%) create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt rename src/pal/tests/palsuite/filemapping_memmgt/{ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.cpp => ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp} (54%) rename src/pal/tests/palsuite/filemapping_memmgt/{ReadProcessMemory/test1 => ProbeMemory/ProbeMemory_neg1}/testinfo.dat (59%) create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt rename src/pal/tests/palsuite/filemapping_memmgt/{ReadProcessMemory/test1/ReadProcessMemory.cpp => ProbeMemory/test1/ProbeMemory.cpp} (53%) rename src/pal/tests/palsuite/filemapping_memmgt/{ReadProcessMemory/ReadProcessMemory_neg1 => ProbeMemory/test1}/testinfo.dat (58%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.cpp delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.cpp delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat diff --git a/src/debug/daccess/fntableaccess.cpp b/src/debug/daccess/fntableaccess.cpp index e7b96ec..6dcd584 100644 --- a/src/debug/daccess/fntableaccess.cpp +++ b/src/debug/daccess/fntableaccess.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" +#ifndef FEATURE_PAL #ifndef _TARGET_X86_ // @@ -388,6 +389,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction #endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO + BOOL ReadMemory(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) { HANDLE hProcess = (HANDLE)pUserContext; @@ -456,6 +458,5 @@ extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx() return STATUS_UNSUCCESSFUL; } - - #endif // !_TARGET_X86_ +#endif // !FEATURE_PAL \ No newline at end of file diff --git a/src/debug/di/rspriv.inl b/src/debug/di/rspriv.inl index 00e4c23..5de99c6 100644 --- a/src/debug/di/rspriv.inl +++ b/src/debug/di/rspriv.inl @@ -162,7 +162,7 @@ void CordbProcess::ForceDacFlush() { if (m_pDacPrimitives != NULL) { - STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d", m_flushCounter); + STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d\n", m_flushCounter); m_flushCounter++; HRESULT hr = S_OK; EX_TRY diff --git a/src/debug/shared/dbgtransportsession.cpp b/src/debug/shared/dbgtransportsession.cpp index 14b509a..95fdf25 100644 --- a/src/debug/shared/dbgtransportsession.cpp +++ b/src/debug/shared/dbgtransportsession.cpp @@ -1140,33 +1140,6 @@ DbgTransportSession::Message * DbgTransportSession::RemoveMessageFromSendQueue(D #ifndef RIGHT_SIDE_COMPILE -#ifdef FEATURE_PAL -__attribute__((noinline)) -__attribute__((optnone)) -static void -ProbeMemory(__in_ecount(cbBuffer) volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) -{ - // Need an throw in this function to fool the C++ runtime into handling the - // possible h/w exception below. - if (pbBuffer == NULL) - { - throw PAL_SEHException(); - } - - // Simple one byte at a time probing - while (cbBuffer > 0) - { - volatile BYTE read = *pbBuffer; - if (fWriteAccess) - { - *pbBuffer = read; - } - ++pbBuffer; - --cbBuffer; - } -} -#endif // FEATURE_PAL - // Check read and optionally write memory access to the specified range of bytes. Used to check // ReadProcessMemory and WriteProcessMemory requests. HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) @@ -1220,14 +1193,7 @@ HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuf } while (cbBuffer > 0); #else - try - { - // Need to explicit h/w exception holder so to catch them in ProbeMemory - CatchHardwareExceptionHolder __catchHardwareException; - - ProbeMemory(pbBuffer, cbBuffer, fWriteAccess); - } - catch(...) + if (!PAL_ProbeMemory(pbBuffer, cbBuffer, fWriteAccess)) { return HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS); } diff --git a/src/dlls/mscordac/mscordac_unixexports.src b/src/dlls/mscordac/mscordac_unixexports.src index ffa5968..7d60c1e 100644 --- a/src/dlls/mscordac/mscordac_unixexports.src +++ b/src/dlls/mscordac/mscordac_unixexports.src @@ -26,6 +26,7 @@ PAL_GetSymbolModuleBase PAL_GetTransportPipeName PAL_InitializeDLL PAL_IsDebuggerPresent +PAL_ProbeMemory PAL_iswspace PAL_memcpy PAL_malloc diff --git a/src/inc/livedatatarget.h b/src/inc/livedatatarget.h index 7282dd4..1ffbca7 100644 --- a/src/inc/livedatatarget.h +++ b/src/inc/livedatatarget.h @@ -14,6 +14,7 @@ // Does not include IXClrData definitions. #include +#ifndef FEATURE_PAL //--------------------------------------------------------------------------------------- // @@ -100,6 +101,7 @@ private: CLRDATA_ADDRESS m_baseAddressOfEngine; }; +#endif // FEATURE_PAL #endif // _LIVEPROC_DATATARGET_H_ diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp index 2cc876a..dcadaa9 100644 --- a/src/jit/ee_il_dll.cpp +++ b/src/jit/ee_il_dll.cpp @@ -1537,6 +1537,9 @@ const char* Compiler::eeGetClassName(CORINFO_CLASS_HANDLE clsHnd) const wchar_t* Compiler::eeGetCPString(size_t strHandle) { +#ifdef FEATURE_PAL + return nullptr; +#else char buff[512 + sizeof(CORINFO_String)]; // make this bulletproof, so it works even if we are wrong. @@ -1558,6 +1561,7 @@ const wchar_t* Compiler::eeGetCPString(size_t strHandle) } return (asString->chars); +#endif // FEATURE_PAL } #endif // DEBUG diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 28c6278..0d7c89e 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -648,6 +648,13 @@ PAL_DeleteExecWatchpoint( #endif +PALIMPORT +BOOL +PALAPI +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess); /******************* winuser.h Entrypoints *******************************/ @@ -3653,16 +3660,6 @@ VirtualQuery( IN SIZE_T dwLength); PALIMPORT -BOOL -PALAPI -ReadProcessMemory( - IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - OUT LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesRead); - -PALIMPORT VOID PALAPI RtlMoveMemory( @@ -4715,15 +4712,6 @@ typedef struct _RUNTIME_FUNCTION { DWORD UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; -PALIMPORT -BOOL -PALAPI -WriteProcessMemory(IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesWritten); - #define STANDARD_RIGHTS_REQUIRED (0x000F0000L) #define SYNCHRONIZE (0x00100000L) #define READ_CONTROL (0x00020000L) diff --git a/src/pal/src/debug/debug.cpp b/src/pal/src/debug/debug.cpp index 756e615..2f7d17c 100644 --- a/src/pal/src/debug/debug.cpp +++ b/src/pal/src/debug/debug.cpp @@ -92,29 +92,6 @@ static const char PAL_OUTPUTDEBUGSTRING[] = "PAL_OUTPUTDEBUGSTRING"; static const char PAL_RUN_ON_DEBUG_BREAK[] = "PAL_RUN_ON_DEBUG_BREAK"; #endif // ENABLE_RUN_ON_DEBUG_BREAK -/* ------------------- Static function prototypes ----------------------------*/ - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -static int -DBGWriteProcMem_Int(DWORD processId, int *addr, int data); -static int -DBGWriteProcMem_IntWithMask(DWORD processId, int *addr, int data, - unsigned int mask); -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -static BOOL -DBGAttachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static BOOL -DBGDetachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static int -DBGSetProcessAttached(CPalThread *pThread, HANDLE hProcess, BOOL bAttach); - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - extern "C" { /*++ @@ -566,457 +543,6 @@ SetThreadContext( return ret; } -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -/*++ -Function: - DBGWriteProcMem_Int - -Abstract - write one int to a process memory address - -Parameter - processId : process handle - addr : memory address where the int should be written - data : int to be written in addr - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_Int(IN DWORD processId, - IN int *addr, - IN int data) -{ - if (PAL_PTRACE( PAL_PT_WRITE_D, processId, addr, data ) == -1) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return 0; - } - - return 1; -} - -/*++ -Function: - DBGWriteProcMem_IntWithMask - -Abstract - write one int to a process memory address space using mask - -Parameter - processId : process ID - addr : memory address where the int should be written - data : int to be written in addr - mask : the mask used to write only a parts of data - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_IntWithMask(IN DWORD processId, - IN int *addr, - IN int data, - IN unsigned int mask ) -{ - int readInt; - - if (mask != ~0) - { - errno = 0; - if (((readInt = PAL_PTRACE( PAL_PT_READ_D, processId, addr, 0 )) == -1) - && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - return 0; - } - data = (data & mask) | (readInt & ~mask); - } - return DBGWriteProcMem_Int(processId, addr, data); -} -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -/*++ -Function: - DBGAttachProcess - -Abstract - - Attach the indicated process to the current process. - - if the indicated process is already attached by the current process, then - increment the number of attachment pending. if ot, attach it to the current - process (with PT_ATTACH). - -Parameter - hProcess : handle to process to attach to - processId : process ID to attach -Return - Return true if it succeeds, or false if it's fails ---*/ -static -BOOL -DBGAttachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int attchmentCount; - int savedErrno; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - attchmentCount = - DBGSetProcessAttached(pThread, hProcess, DBG_ATTACH); - - if (attchmentCount == -1) - { - /* Failed to set the process as attached */ - goto EXIT; - } - - if (attchmentCount == 1) - { -#if HAVE_PROCFS_CTL - struct timespec waitTime; - - // FreeBSD has some trouble when a series of attach/detach sequences - // occurs too close together. When this happens, we'll be able to - // attach to the process, but waiting for the process to stop - // (either via writing "wait" to /proc//ctl or via waitpid) - // will hang. If we pause for a very short amount of time before - // trying to attach, we don't run into this situation. - waitTime.tv_sec = 0; - waitTime.tv_nsec = 50000000; - nanosleep(&waitTime, NULL); - - sprintf_s(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(ctlPath, O_WRONLY); - if (fd == -1) - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH1; - } - - if (write(fd, CTL_ATTACH, sizeof(CTL_ATTACH)) < (int)sizeof(CTL_ATTACH)) - { - ERROR("Failed to attach to %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - goto DETACH1; - } - - if (write(fd, CTL_WAIT, sizeof(CTL_WAIT)) < (int)sizeof(CTL_WAIT)) - { - ERROR("Failed to wait for %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH2; - } - - close(fd); -#elif HAVE_TTRACE - if (ttrace(TT_PROC_ATTACH, processId, 0, TT_DETACH_ON_EXIT, TT_VERSION, 0) == -1) - { - if (errno != ESRCH) - { - ASSERT("ttrace(TT_PROC_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } -#else // HAVE_TTRACE - if (PAL_PTRACE( PAL_PT_ATTACH, processId, 0, 0 ) == -1) - { - if (errno != ESRCH) - { - ASSERT("ptrace(PT_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } - - if (waitpid(processId, NULL, WUNTRACED) == -1) - { - if (errno != ESRCH) - { - ASSERT("waitpid(pid:%d, NULL, WUNTRACED) failed.errno:%d" - " (%s)\n", processId, errno, strerror(errno)); - } - goto DETACH2; - } -#endif // HAVE_PROCFS_CTL - } - - return TRUE; - -#if HAVE_PROCFS_CTL -DETACH2: - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ASSERT("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - } - close(fd); -#elif !HAVE_TTRACE -DETACH2: - if (PAL_PTRACE(PAL_PT_DETACH, processId, 0, 0) == -1) - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", processId, - errno, strerror(errno)); - } -#endif // HAVE_PROCFS_CTL - -DETACH1: - savedErrno = errno; - DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - errno = savedErrno; -EXIT: - if (errno == ESRCH || errno == ENOENT || errno == EBADF) - { - ERROR("Invalid process ID:%d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; -} - -/*++ -Function: - DBGDetachProcess - -Abstract - Detach the indicated process from the current process. - - if the indicated process is already attached by the current process, then - decrement the number of attachment pending and detach it from the current - process (with PT_DETACH) if there's no more attachment left. - -Parameter - hProcess : process handle - processId : process ID - -Return - Return true if it succeeds, or true if it's fails ---*/ -static -BOOL -DBGDetachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int nbAttachLeft; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - nbAttachLeft = DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - - if (nbAttachLeft == -1) - { - /* Failed to set the process as detached */ - return FALSE; - } - - /* check if there's no more attachment left on processId */ - if (nbAttachLeft == 0) - { -#if HAVE_PROCFS_CTL - snprintf(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(pThread, ctlPath, O_WRONLY); - if (fd == -1) - { - if (errno == ENOENT) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } - - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ERROR("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - return FALSE; - } - close(fd); - -#elif HAVE_TTRACE - if (ttrace(TT_PROC_DETACH, processId, 0, 0, 0, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ttrace(TT_PROC_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#else // HAVE_TTRACE - if (PAL_PTRACE(PAL_PT_DETACH, processId, 1, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#endif // HAVE_PROCFS_CTL - -#if !HAVE_TTRACE - if (kill(processId, SIGCONT) == -1) - { - ERROR("Failed to continue the detached process:%d errno:%d (%s)\n", - processId, errno, strerror(errno)); - return FALSE; - } -#endif // !HAVE_TTRACE - } - return TRUE; -} - -/*++ -Function: - DBGSetProcessAttached - -Abstract - saves the current process Id in the attached process structure - -Parameter - hProcess : process handle - bAttach : true (false) to set the process as attached (as detached) -Return - returns the number of attachment left on attachedProcId, or -1 if it fails ---*/ -static int -DBGSetProcessAttached( - CPalThread *pThread, - HANDLE hProcess, - BOOL bAttach - ) -{ - PAL_ERROR palError = NO_ERROR; - IPalObject *pobjProcess = NULL; - IDataLock *pDataLock = NULL; - CProcProcessLocalData *pLocalData = NULL; - int ret = -1; - CAllowedObjectTypes aotProcess(otiProcess); - - palError = g_pObjectManager->ReferenceObjectByHandle( - pThread, - hProcess, - &aotProcess, - 0, - &pobjProcess - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - palError = pobjProcess->GetProcessLocalData( - pThread, - WriteLock, - &pDataLock, - reinterpret_cast(&pLocalData) - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - if (bAttach) - { - pLocalData->lAttachCount += 1; - } - else - { - pLocalData->lAttachCount -= 1; - - if (pLocalData->lAttachCount < 0) - { - ASSERT("pLocalData->lAttachCount < 0 check for extra DBGDetachProcess calls\n"); - palError = ERROR_INTERNAL_ERROR; - goto DBGSetProcessAttachedExit; - } - } - - ret = pLocalData->lAttachCount; - -DBGSetProcessAttachedExit: - - if (NULL != pDataLock) - { - pDataLock->ReleaseLock(pThread, TRUE); - } - - if (NULL != pobjProcess) - { - pobjProcess->ReleaseReference(pThread); - } - - return ret; -} - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - /*++ Function: PAL_CreateExecWatchpoint @@ -1240,605 +766,64 @@ PAL_DeleteExecWatchpointExit: return dwError; } -// We want to enable hardware exception handling for ReadProcessMemory -// and WriteProcessMemory in all cases since it is acceptable if they -// hit AVs, so redefine HardwareExceptionHolder for these two functions -// (here to the end of the file). -#undef HardwareExceptionHolder -#define HardwareExceptionHolder CatchHardwareExceptionHolder __catchHardwareException; - -/*++ -Function: - ReadProcessMemory - -See MSDN doc. ---*/ -BOOL -PALAPI -ReadProcessMemory( - IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - IN LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesRead - ) +__attribute__((noinline)) +__attribute__((optnone)) +void +ProbeMemory(volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile ret = FALSE; - Volatile numberOfBytesRead = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; - LONG_PTR bytesToRead; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T nbInts; - int* ptrInt; - int* lpTmpBuffer; -#endif -#if !HAVE_PROCFS_CTL && !HAVE_TTRACE - int* lpBaseAddressAligned; - SIZE_T offset; -#endif // !HAVE_PROCFS_CTL && !HAVE_TTRACE - - PERF_ENTRY(ReadProcessMemory); - ENTRY("ReadProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesRead=%p)\n",hProcess,lpBaseAddress, - lpBuffer, (unsigned int)nSize, lpNumberOfBytesRead); - - pThread = InternalGetCurrentThread(); - - if (!(processId = PROCGetProcessIDFromHandle(hProcess))) - { - ERROR("Invalid process handler hProcess:%p.",hProcess); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - - // Check if the read request is for the current process. - // We don't need ptrace in that case. - if (GetCurrentProcessId() == processId) + // Need an throw in this function to fool the C++ runtime into handling the + // possible h/w exception below. + if (pbBuffer == NULL) { - TRACE("We are in the same process, so ptrace is not needed\n"); - - struct Param - { - LPCVOID lpBaseAddress; - LPVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesRead; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesRead = numberOfBytesRead; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; inSize; i++) - { - *((char*)(pParam->lpBuffer)+i) = *((char*)(pParam->lpBaseAddress)+i); - } - - pParam->numberOfBytesRead = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesRead = param.numberOfBytesRead; - ret = param.ret; - goto EXIT; + throw PAL_SEHException(); } -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) + // Simple one byte at a time probing + while (cbBuffer > 0) { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - // vm_read_overwrite usually requires that the address be page-aligned - // and the size be a multiple of the page size. We can't differentiate - // between the cases in which that's required and those in which it - // isn't, so we do it all the time. - lpBaseAddressAligned = (int*)((SIZE_T) lpBaseAddress & ~VIRTUAL_PAGE_MASK); - offset = ((SIZE_T) lpBaseAddress & VIRTUAL_PAGE_MASK); - char *data; - data = (char*)alloca(VIRTUAL_PAGE_SIZE); - while (nSize > 0) - { - vm_size_t bytesRead; - - bytesToRead = VIRTUAL_PAGE_SIZE - offset; - if (bytesToRead > (LONG_PTR)nSize) - { - bytesToRead = nSize; - } - bytesRead = VIRTUAL_PAGE_SIZE; - result = vm_read_overwrite(task, (vm_address_t) lpBaseAddressAligned, - VIRTUAL_PAGE_SIZE, (vm_address_t) data, &bytesRead); - if (result != KERN_SUCCESS || bytesRead != VIRTUAL_PAGE_SIZE) + volatile BYTE read = *pbBuffer; + if (fWriteAccess) { - ERROR("vm_read_overwrite failed for %d bytes from %p in %d: %d\n", - VIRTUAL_PAGE_SIZE, (char *) lpBaseAddressAligned, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_INVALID_ACCESS); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; + *pbBuffer = read; } - memcpy((LPSTR)lpBuffer + numberOfBytesRead, data + offset, bytesToRead); - numberOfBytesRead.Store(numberOfBytesRead.Load() + bytesToRead); - lpBaseAddressAligned = (int*)((char*)lpBaseAddressAligned + VIRTUAL_PAGE_SIZE); - nSize -= bytesToRead; - offset = 0; + ++pbBuffer; + --cbBuffer; } - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_RDONLY); - if (fd == -1) - { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; - - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesRead = read(fd, lpBuffer, nSize); - ret = TRUE; - -#else // HAVE_PROCFS_CTL - // Attach the process before calling ttrace/ptrace otherwise it fails. - if (DBGAttachProcess(pThread, hProcess, processId)) - { -#if HAVE_TTRACE - if (ttrace(TT_PROC_RDDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesRead = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - offset = (SIZE_T)lpBaseAddress % sizeof(int); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - offset); - nbInts = (nSize + offset)/sizeof(int) + - ((nSize + offset)%sizeof(int) ? 1:0); - - /* before transferring any data to lpBuffer we should make sure that all - data is accessible for read. so we need to use a temp buffer for that.*/ - if (!(lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int))))) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - for (ptrInt = lpTmpBuffer; nbInts; ptrInt++, - lpBaseAddressAligned++, nbInts--) - { - errno = 0; - *ptrInt = - PAL_PTRACE(PAL_PT_READ_D, processId, lpBaseAddressAligned, 0); - if (*ptrInt == -1 && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - - SetLastError(ptrInt == lpTmpBuffer ? ERROR_ACCESS_DENIED : - ERROR_PARTIAL_COPY); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP2; - } - } - - /* transfer data from temp buffer to lpBuffer */ - memcpy( (char *)lpBuffer, ((char*)lpTmpBuffer) + offset, nSize); - numberOfBytesRead = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesRead) - { - *lpNumberOfBytesRead = numberOfBytesRead; - } - LOGEXIT("ReadProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(ReadProcessMemory); - return ret; } /*++ Function: - WriteProcessMemory + PAL_ProbeMemory -See MSDN doc. +Abstract + +Parameter + pBuffer : address of memory to validate + cbBuffer : size of memory region to validate + fWriteAccess : if true, validate writable access, else just readable. + +Return + true if memory is valid, false if not. --*/ BOOL PALAPI -WriteProcessMemory( - IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesWritten - ) - +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile ret = FALSE; - Volatile numberOfBytesWritten = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - LONG_PTR bytesWritten; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T FirstIntOffset; - SIZE_T LastIntOffset; - unsigned int FirstIntMask; - unsigned int LastIntMask; - SIZE_T nbInts; - int *lpTmpBuffer = 0, *lpInt; - int* lpBaseAddressAligned; -#endif - - PERF_ENTRY(WriteProcessMemory); - ENTRY("WriteProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesWritten=%p)\n", - hProcess,lpBaseAddress, lpBuffer, (unsigned int)nSize, lpNumberOfBytesWritten); - - pThread = InternalGetCurrentThread(); - - if (!(nSize && (processId = PROCGetProcessIDFromHandle(hProcess)))) - { - ERROR("Invalid nSize:%u number or invalid process handler " - "hProcess:%p\n", (unsigned int)nSize, hProcess); - SetLastError(ERROR_INVALID_PARAMETER); - goto EXIT; - } - - // Check if the write request is for the current process. - // In that case we don't need ptrace. - if (GetCurrentProcessId() == processId) - { - TRACE("We are in the same process so we don't need ptrace\n"); - - struct Param - { - LPVOID lpBaseAddress; - LPCVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesWritten; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesWritten = numberOfBytesWritten; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; inSize; i++) - { - *((char*)(pParam->lpBaseAddress)+i) = *((char*)(pParam->lpBuffer)+i); - } - - pParam->numberOfBytesWritten = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesWritten = param.numberOfBytesWritten; - ret = param.ret; - goto EXIT; - } - -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) - { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - result = vm_write(task, (vm_address_t) lpBaseAddress, - (vm_address_t) lpBuffer, nSize); - if (result != KERN_SUCCESS) - { - ERROR("vm_write failed for %d bytes from %p in %d: %d\n", - (int)nSize, lpBaseAddress, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; - } - numberOfBytesWritten = nSize; - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_WRONLY); - if (fd == -1) + try { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; + // Need to explicit h/w exception holder so to catch them in ProbeMemory + CatchHardwareExceptionHolder __catchHardwareException; - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; + ProbeMemory((PBYTE)pBuffer, cbBuffer, fWriteAccess); } - - bytesWritten = write(fd, lpBuffer, nSize); - if (bytesWritten < 0) - { - ERROR("Failed to write to %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesWritten = bytesWritten; - ret = TRUE; - -#else // HAVE_PROCFS_CTL - /* Attach the process before calling ptrace otherwise it fails */ - if (DBGAttachProcess(pThread, hProcess, processId)) + catch(...) { -#if HAVE_TTRACE - if (ttrace(TT_PROC_WRDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesWritten = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - FirstIntOffset = (SIZE_T)lpBaseAddress % sizeof(int); - FirstIntMask = -1; - FirstIntMask <<= (FirstIntOffset * 8); - - nbInts = (nSize + FirstIntOffset) / sizeof(int) + - (((nSize + FirstIntOffset)%sizeof(int)) ? 1:0); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - FirstIntOffset); - - if ((lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int)))) == NULL) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - memcpy((char *)lpTmpBuffer + FirstIntOffset, (char *)lpBuffer, nSize); - lpInt = lpTmpBuffer; - - LastIntOffset = (nSize + FirstIntOffset) % sizeof(int); - LastIntMask = -1; - LastIntMask >>= ((sizeof(int) - LastIntOffset) * 8); - - if (nbInts == 1) - { - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, - LastIntMask & FirstIntMask) - == 0) - { - goto CLEANUP2; - } - numberOfBytesWritten = nSize; - ret = TRUE; - goto CLEANUP2; - } - - if (DBGWriteProcMem_IntWithMask(processId, - lpBaseAddressAligned++, - *lpInt++, FirstIntMask) - == 0) - { - goto CLEANUP2; - } - - while (--nbInts > 1) - { - if (DBGWriteProcMem_Int(processId, lpBaseAddressAligned++, - *lpInt++) == 0) - { - goto CLEANUP2; - } - } - - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, LastIntMask ) == 0) - { - goto CLEANUP2; - } - - numberOfBytesWritten = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // !HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesWritten) - { - *lpNumberOfBytesWritten = numberOfBytesWritten; + return FALSE; } - - LOGEXIT("WriteProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(WriteProcessMemory); - return ret; + return TRUE; } } // extern "C" diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt index 3fc399f..a573dae 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt @@ -17,7 +17,7 @@ add_subdirectory(LockFile) add_subdirectory(MapViewOfFile) add_subdirectory(OpenFileMappingA) add_subdirectory(OpenFileMappingW) -add_subdirectory(ReadProcessMemory) +add_subdirectory(ProbeMemory) add_subdirectory(RtlMoveMemory) add_subdirectory(UnlockFile) add_subdirectory(UnmapViewOfFile) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt similarity index 50% rename from src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt rename to src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt index d2ae61f..c6eddf7 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 2.8.12.2) -add_subdirectory(ReadProcessMemory_neg1) +add_subdirectory(ProbeMemory_neg1) add_subdirectory(test1) -add_subdirectory(test2) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt new file mode 100644 index 0000000..e96c92e --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + ProbeMemory_neg.cpp +) + +add_executable(paltest_probememory_probememory_neg1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_probememory_neg1 coreclrpal) + +target_link_libraries(paltest_probememory_probememory_neg1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp similarity index 54% rename from src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.cpp rename to src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp index aecd5ad..80de809 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.cpp +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp @@ -19,12 +19,7 @@ int __cdecl main(int argc, char *argv[]) { int err; BOOL bResult; - HANDLE ProcessHandle; - DWORD ProcessID; LPVOID lpProcessAddress = NULL; - char ProcessBuffer[REGIONSIZE]; - ULONG_PTR size = 0; - /*Initialize the PAL environment*/ err = PAL_Initialize(argc, argv); @@ -33,24 +28,6 @@ int __cdecl main(int argc, char *argv[]) return FAIL; } - /*retrieve the current process ID*/ - ProcessID = GetCurrentProcessId(); - - /*retrieve the current process handle*/ - ProcessHandle = OpenProcess( - PROCESS_ALL_ACCESS, - FALSE, /*not inherited*/ - ProcessID); - - if(NULL == ProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - - - /*allocate the virtual memory*/ lpProcessAddress = VirtualAlloc( NULL, /*system determine where to allocate the region*/ @@ -64,62 +41,53 @@ int __cdecl main(int argc, char *argv[]) "virtual memory, error code=%u\n", GetLastError()); } - /*zero the memory*/ - memset(ProcessBuffer, 0, REGIONSIZE); - /*try to retrieve the unreadable memory area*/ - bResult = ReadProcessMemory( - ProcessHandle, /*current process handle*/ + /*try to probe the unreadable memory area*/ + bResult = PAL_ProbeMemory( lpProcessAddress, /*base of memory area*/ - (LPVOID)ProcessBuffer, REGIONSIZE, /*buffer length in bytes*/ - &size); - + FALSE); /*read access*/ /*check the return value*/ - if(0 != bResult) + if(bResult) { - Trace("\nFailed to call ReadProcessMemory API for a negative test, " - "Try to read an unreadable memory area will cause fail " - "but it successes\n"); - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } + Trace("\nProbeMemory for read didn't FAILED\n"); /*decommit the specified region*/ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } + Fail(""); } - err = CloseHandle(ProcessHandle); - if(0 == err) + /*try to probe the unwriteable memory area*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*write access */ + + /*check the return value*/ + if(bResult) { - Trace("\nFailed to call CloseHandle API, error code = %u\n", - GetLastError()); + Trace("\nProbeMemory for write didn't FAILED\n"); + /*decommit the specified region*/ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } Fail(""); } + /*decommit the specified region*/ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Fail("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } PAL_Terminate(); diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat similarity index 59% rename from src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat rename to src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat index c56920d..4d11a71 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat @@ -4,9 +4,9 @@ Version = 1.0 Section = Filemapping_memmgt -Function = ReadProcessMemory -Name = Positive test for ReadProcessMemory API to read memory contents +Function = PAL_ProbeMemory +Name = Negative test PAL_ProbeMemory API to read unreadable memory area TYPE = DEFAULT -EXE1 = readprocessmemory +EXE1 = probememory_neg Description -=Test the ReadProcessMemory to read the memory contents +=Test the PAL_ProbeMemory to read unreadable memory area diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt new file mode 100644 index 0000000..739ba62 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + ProbeMemory.cpp +) + +add_executable(paltest_probememory_test1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_test1 coreclrpal) + +target_link_libraries(paltest_probememory_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp similarity index 53% rename from src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.cpp rename to src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp index c9475f1..30b358d 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.cpp +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp @@ -20,12 +20,7 @@ int __cdecl main(int argc, char *argv[]) { int err; BOOL bResult; - HANDLE ProcessHandle; - DWORD ProcessID; LPVOID lpProcessAddress = NULL; - char ProcessBuffer[REGIONSIZE]; - ULONG_PTR size = 0; - /*Initialize the PAL environment*/ err = PAL_Initialize(argc, argv); @@ -34,28 +29,12 @@ int __cdecl main(int argc, char *argv[]) return FAIL; } - /*retrieve the current process ID*/ - ProcessID = GetCurrentProcessId(); - - /*retrieve the current process handle*/ - ProcessHandle = OpenProcess( - PROCESS_VM_READ,/*access flag*/ - FALSE, /*not inherited*/ - ProcessID); - - if(NULL == ProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - /*allocate the virtual memory*/ lpProcessAddress = VirtualAlloc( NULL, /*system determine where to allocate the region*/ REGIONSIZE, /*specify the size*/ MEM_COMMIT, /*allocation type*/ - PAGE_READONLY); /*access protection*/ + PAGE_READWRITE); /*access protection*/ if(NULL == lpProcessAddress) { @@ -63,51 +42,41 @@ int __cdecl main(int argc, char *argv[]) "virtual memory, error code=%u!\n", GetLastError()); } - /*zero the memory*/ - memset(ProcessBuffer, 0, REGIONSIZE); - - /*retrieve the memory contents*/ - bResult = ReadProcessMemory( - ProcessHandle, /*current process handle*/ + /*probe the memory for read*/ + bResult = PAL_ProbeMemory( lpProcessAddress, /*base of memory area*/ - (LPVOID)ProcessBuffer, REGIONSIZE, /*buffer length in bytes*/ - &size); + FALSE); /*read access*/ - if(!bResult || REGIONSIZE != size) + if(!bResult) { - Trace("\nFailed to call ReadProcessMemory API " - "to retrieve the memory contents, error code=%u\n", - GetLastError()); - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } + Trace("\nProbeMemory for read access FAILED\n"); /*decommit the specified region*/ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } + Fail(""); } - err = CloseHandle(ProcessHandle); - if(0 == err) + /*probe the memory for write */ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + TRUE); /*write access*/ + + if(!bResult) { - Trace("\nFailed to call CloseHandle API, error code = %u\n", - GetLastError()); + Trace("\nProbeMemory for write access FAILED\n"); + /*decommit the specified region*/ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } Fail(""); @@ -117,8 +86,7 @@ int __cdecl main(int argc, char *argv[]) err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); if(0 == err) { - Fail("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); } PAL_Terminate(); diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat similarity index 58% rename from src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat rename to src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat index 08c8f32..512b945 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat @@ -4,9 +4,9 @@ Version = 1.0 Section = Filemapping_memmgt -Function = ReadProcessMemory -Name = Negative test ReadProcessMemory API to read unreadable memory area +Function = PAL_ProbeMemory +Name = Positive test for PAL_ProbeMemory API to probe for read/write TYPE = DEFAULT -EXE1 = readprocessmemory_neg +EXE1 = probememory Description -=Test the ReadProcessMemory to read unreadable memory area +=Test the PAL_ProbeMemory to probe for read and write diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt deleted file mode 100644 index 6874834..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - ReadProcessMemory_neg.cpp -) - -add_executable(paltest_readprocessmemory_readprocessmemory_neg1 - ${SOURCES} -) - -add_dependencies(paltest_readprocessmemory_readprocessmemory_neg1 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_readprocessmemory_neg1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt deleted file mode 100644 index abaa09f..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - ReadProcessMemory.cpp -) - -add_executable(paltest_readprocessmemory_test1 - ${SOURCES} -) - -add_dependencies(paltest_readprocessmemory_test1 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt deleted file mode 100644 index 0a9d5e3..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(TESTSOURCES - test2.cpp -) - -add_executable(paltest_readprocessmemory_test2 - ${TESTSOURCES} -) - -add_dependencies(paltest_readprocessmemory_test2 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test2 - pthread - m - coreclrpal -) - - -set(HELPERSOURCES - helper.cpp -) - -add_executable(paltest_readprocessmemory_test2_helper - ${HELPERSOURCES} -) - -add_dependencies(paltest_readprocessmemory_test2_helper coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test2_helper - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h deleted file mode 100644 index 433d820..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: commonconsts.h -** -** -**============================================================*/ - -#ifndef _COMMONCONSTS_H_ -#define _COMMONCONSTS_H_ - -#include -#define REGIONSIZE 1024 - -const int TIMEOUT = 40000; - -const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' }; -const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' }; - -const char initialValue = '-'; -const char nextValue = '|'; -const char guardValue = '*'; -const char *commsFileName = "AddrNLen.dat"; - - -/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any - * zero return codes in a generic way. with little typing */ -#define PEDANTIC(function, parameters) \ -{ \ - if (! (function parameters) ) \ - { \ - Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ - __FILE__, #function, #parameters, GetLastError(), errno); \ - } \ -} -#define PEDANTIC1(function, parameters) \ -{ \ - if ( (function parameters) ) \ - { \ - Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ - __FILE__, #function, #parameters, GetLastError(), errno); \ - } \ -} - -#endif diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.cpp deleted file mode 100644 index a10ad92..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: helper.c -** -** Purpose: This helper process sets up a several blocks of memory, -** then uses a file to tell its parent process where that memory is -** So it can do a WriteProcessMemory on it. When the parent process is done -** we check here that it was written properly. -** -** -**============================================================*/ - -#include "commonconsts.h" - -#include - -#if defined(BIT64) && defined(PLATFORM_UNIX) -#define LLFORMAT "%I64u" -#else -#define LLFORMAT "%u" -#endif - -struct allhandles_t -{ - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - char *valuesFileName; -}; - - -/* function: wpmDoIt - * - * This is a general WriteProcessMemory testing function that sets up - * the RAM pointed to and tells the companion process on the other end - * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at - * '*pDest'. - * - * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region - * surrounding the '*pDest'[0..'lenDest'] region so that this function - * can verify that only the proper bytes were altered. - */ - -int wpmDoIt(struct allhandles_t Comms, - char * pBuffer, unsigned int lenBuffer, - char * pDest, unsigned int lenDest, - const char* storageDescription) -{ - char *pCurr; - FILE *commsFile; - DWORD dwRet; - - if (pBuffer > pDest || lenDest > lenBuffer) - { - Trace("WriteProcessMemory::DoIt() test implementation: " - "(pBuffer > pDest || lenDest > lenBuffer)\n"); - return FALSE; - } - - /* set up the storage */ - memset(pBuffer, guardValue, lenBuffer); - memset(pDest, initialValue, lenDest); - - /* tell the parent what RAM to adjust */ - if(!(commsFile = fopen(Comms.valuesFileName, "w"))) - { - Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - if (!fprintf(commsFile, LLFORMAT " " LLFORMAT " '%s'\n", - pDest, lenDest, storageDescription)) - { - Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - PEDANTIC1(fclose, (commsFile)); - - /* Tell the parent the data is ready for it to adjust */ - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - PEDANTIC(SetEvent, (Comms.hEvFromHelper)); - - dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ - if (dwRet != WAIT_OBJECT_0) - { - Trace("helper WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - return FALSE; - } - - /* check the stuff that SHOULD have changed */ - for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) - { - if ( *pCurr != nextValue) - { - Trace("When testing '%s': alteration test failed " - "at " LLFORMAT " offset " LLFORMAT " Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - /* check the stuff that should NOT have changed */ - for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': leading guard zone test failed " - "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': trailing guard zone test failed " - "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.", - storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - - return TRUE; -} - -int __cdecl main(int argc, char *argv[]) -{ - - BOOL success = TRUE; /* assume success */ - struct allhandles_t Comms = {0,0,0} ; - - /* variables to track storage to alter */ - char *pTarget = NULL; - unsigned int sizeTarget; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* hook up with the events created by the parent */ - Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); - if (!Comms.hEvToHelper) - { - Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcToHelperEvName, GetLastError()); - } - Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); - if (!Comms.hEvToHelper) - { - Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcFromHelperEvName, GetLastError()); - success = FALSE; - goto EXIT; - } - Comms.valuesFileName = argv[1]; - - { - char autoAllocatedOnStack[51]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "const size array on stack with int sized guards"); - } - - /* Get the parent process to write to stuff on the heap */ - sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ - if (!(pTarget = (char*)malloc(sizeTarget))) - { - Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" - "(%u).\n", - argv[3], sizeTarget, GetLastError()); - success = FALSE; - goto EXIT; - - } - success &= wpmDoIt(Comms, pTarget, sizeTarget, - pTarget + sizeof(int), - sizeTarget - 2 * sizeof(int), - "array on heap with int sized guards"); - - /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ - { - char autoAllocatedOnStack[16]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "another 16 byte array on stack with int sized guards inside"); - } - - /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims - * it writes 8 bytes in that case! */ - - /* and 1 byte long... */ - { - char autoAllocatedOnStack[1+ 2 * sizeof(int)]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - 1, - "no bytes with int sized guards outside on stack"); - } - - -EXIT: - /* Tell the parent that we are done */ - if (!DeleteFile(Comms.valuesFileName)) - { - Trace("helper: DeleteFile failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - if (!SetEvent(Comms.hEvFromHelper)) - { - Trace("helper: SetEvent failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - - free(pTarget); - PEDANTIC(CloseHandle, (Comms.hEvToHelper)); - PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); - - if (!success) - { - Fail(""); - } - - PAL_Terminate(); - - return success ? PASS : FAIL; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.cpp deleted file mode 100644 index 3aea80e..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: test2.c -** -** Purpose: Create a child process and some events for communications with it. -** When the child gets back to us with a memory location and a length, -** Call WriteProcessMemory on this location and check to see that it -** writes successfully. Then call ReadProcessMemory to check if the -** contents read are same as those written -** -** -**============================================================*/ - -#define UNICODE - -#include "commonconsts.h" - -#include - -#if defined(BIT64) && defined(PLATFORM_UNIX) -#define LLFORMAT "%I64u" -#else -#define LLFORMAT "%u" -#endif - -int __cdecl main(int argc, char *argv[]) -{ - - PROCESS_INFORMATION pi; - STARTUPINFO si; - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - DWORD dwExitCode; - - DWORD dwRet; - char cmdComposeBuf[MAX_PATH]; - PWCHAR uniString; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Create the signals we need for cross process communication */ - hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcToHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcToHelperEvName); - } - hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcFromHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcFromHelperEvName); - } - ResetEvent(hEvFromHelper); - ResetEvent(hEvToHelper); - - if (!sprintf_s(cmdComposeBuf, _countof(cmdComposeBuf), "helper %s", commsFileName)) - { - Fail("Could not convert command line\n"); - } - uniString = convert(cmdComposeBuf); - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - /* Create a new process. This is the process that will ask for - * memory munging */ - if(!CreateProcess( NULL, uniString, NULL, NULL, - FALSE, 0, NULL, NULL, &si, &pi)) - { - Trace("ERROR: CreateProcess failed to load executable '%S'. " - "GetLastError() returned %u.\n", - uniString, GetLastError()); - free(uniString); - Fail(""); - } - free(uniString); - - - while(1) - { - FILE *commsFile; - char* pSrcMemory; - char* pDestMemory; - SIZE_T Count; - SIZE_T wpmCount; - char incomingCMDBuffer[MAX_PATH + 1]; - - int err; - HANDLE readProcessHandle; - DWORD readProcessID; - char readProcessBuffer[REGIONSIZE]; // size 1024 - BOOL bResult; - size_t size = 0; - - readProcessID = pi.dwProcessId; - - /* wait until the helper tells us that it has given us - * something to do */ - dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - break; /* no more work incoming */ - } - - /* get the parameters to test WriteProcessMemory with */ - if (!(commsFile = fopen(commsFileName, "r"))) - { - /* no file means there is no more work */ - break; - } - if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) - { - Fail ("unable to read from communication file %s " - "for reasons %u & %u\n", - errno, GetLastError()); - } - PEDANTIC1(fclose,(commsFile)); - sscanf_s(incomingCMDBuffer, LLFORMAT " " LLFORMAT, &pDestMemory, &Count); - if (argc > 1) - { - Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT "('%s')\n", - Count, pDestMemory, incomingCMDBuffer); - } - - /* compose some data to write to the client process */ - if (!(pSrcMemory = (char*)malloc(Count))) - { - Trace("could not dynamically allocate memory to copy from " - "for reasons %u & %u\n", - errno, GetLastError()); - goto doneIteration; - } - memset(pSrcMemory, nextValue, Count); - Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')[%u]\n", - Count, pDestMemory, incomingCMDBuffer, pSrcMemory); - - /* do the work */ - dwRet = WriteProcessMemory(pi.hProcess, - pDestMemory, - pSrcMemory, - Count, - &wpmCount); - - if (!dwRet) - { - Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("test1 WriteProcessMemory returned a (!=0) (GLE=%u)\n", - GetLastError()); - } - if(Count != wpmCount) - { - Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("The number of bytes written should have been " - LLFORMAT ", but was reported as " LLFORMAT " \n", Count, wpmCount); - } - - readProcessHandle = OpenProcess( - PROCESS_VM_READ, - FALSE, - readProcessID); - - if(NULL == readProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - - /*zero the memory*/ - memset(readProcessBuffer, 0, size); - - /*retrieve the memory contents*/ - bResult = ReadProcessMemory( - readProcessHandle, /*current process handle*/ - pDestMemory, /*base of memory area*/ - (LPVOID)readProcessBuffer, - Count, /*buffer length in bytes*/ - &size); - - - if( !bResult || (Count != size) ) - { - Trace("\nFailed to call ReadProcessMemory API " - "to retrieve the memory contents, error code=%u; Bresult[%u] Count[" LLFORMAT "], Size[%d]\n", - GetLastError(), bResult, Count, size); - - err = CloseHandle(readProcessHandle); - - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } - dwExitCode = FAIL; - } - - if( !memcmp (pDestMemory, readProcessBuffer, Count ) ) - { - Trace("Difference in memory contents, expected [%s], but received [%s]\n", pDestMemory, readProcessBuffer); - dwExitCode = FAIL; - } - - Trace("ReadProcessBuffer contains [%s]\n", readProcessBuffer); - err = CloseHandle(readProcessHandle); - - free(pSrcMemory); - - doneIteration: - PEDANTIC(ResetEvent, (hEvFromHelper)); - PEDANTIC(SetEvent, (hEvToHelper)); - } - - /* wait for the child process to complete */ - WaitForSingleObject ( pi.hProcess, TIMEOUT ); - /* this may return a failure code on a success path */ - - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) - { - Trace( "GetExitCodeProcess call failed with error code %u\n", - GetLastError() ); - dwExitCode = FAIL; - } - - - PEDANTIC(CloseHandle, (hEvToHelper)); - PEDANTIC(CloseHandle, (hEvFromHelper)); - PEDANTIC(CloseHandle, (pi.hThread)); - PEDANTIC(CloseHandle, (pi.hProcess)); - - PAL_TerminateEx(dwExitCode); - return dwExitCode; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat deleted file mode 100644 index 58a9935..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed to the .NET Foundation under one or more agreements. -# The .NET Foundation licenses this file to you under the MIT license. -# See the LICENSE file in the project root for more information. - -Version = 1.0 -Section = Debug -Function = ReadProcessMemory -Name = Check that writing/reading text to/from process memory succeeds. -TYPE = DEFAULT -EXE1 = test2 -EXE2 = helper -Description -= Create a child process and attempt to write to its memory -= at the places and lengths it specifies via a data file. -= the child verifies that all the specified memory was altered -= with no overruns. Parent then tries to read memory from child -= and does memory compare to ensure it read memory contents -= correctly diff --git a/src/pal/tests/palsuite/paltestlist.txt b/src/pal/tests/palsuite/paltestlist.txt index a5e241d..2cedca2 100644 --- a/src/pal/tests/palsuite/paltestlist.txt +++ b/src/pal/tests/palsuite/paltestlist.txt @@ -483,6 +483,8 @@ filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3 filemapping_memmgt/MapViewOfFile/test4/paltest_mapviewoffile_test4 filemapping_memmgt/MapViewOfFile/test5/paltest_mapviewoffile_test5 filemapping_memmgt/MapViewOfFile/test6/paltest_mapviewoffile_test6 +filemapping_memmgt/ProbeMemory/test1/paltest_probememory_test1 +filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/paltest_probememory_probememory_neg1 filemapping_memmgt/RtlMoveMemory/test1/paltest_rtlmovememory_test1 filemapping_memmgt/RtlMoveMemory/test3/paltest_rtlmovememory_test3 filemapping_memmgt/RtlMoveMemory/test4/paltest_rtlmovememory_test4 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt index b908c12..9d5fc53 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt @@ -11,5 +11,4 @@ add_subdirectory(test5) add_subdirectory(test6) add_subdirectory(test7) add_subdirectory(test8) -add_subdirectory(test9) diff --git a/src/utilcode/CMakeLists.txt b/src/utilcode/CMakeLists.txt index 9d35a7e..7c39673 100644 --- a/src/utilcode/CMakeLists.txt +++ b/src/utilcode/CMakeLists.txt @@ -41,7 +41,6 @@ set(UTILCODE_COMMON_SOURCES outstring.cpp ilformatter.cpp opinfo.cpp - dacutil.cpp sortversioning.cpp corimage.cpp format1.cpp @@ -71,6 +70,7 @@ set(UTILCODE_COMMON_SOURCES if(WIN32) list(APPEND UTILCODE_COMMON_SOURCES appxutil.cpp + dacutil.cpp dlwrap.cpp downlevel.cpp loadrc.cpp diff --git a/src/vm/debughelp.cpp b/src/vm/debughelp.cpp index f40f7db..abe45d5 100644 --- a/src/vm/debughelp.cpp +++ b/src/vm/debughelp.cpp @@ -6,9 +6,9 @@ #include "common.h" /*******************************************************************/ -/* The folowing routines used to exist in all builds so they could called from the +/* The following routines used to exist in all builds so they could called from the * debugger before we had strike. - * Now most of them are only inclued in debug builds for diagnostics purposes. + * Now most of them are only included in debug builds for diagnostics purposes. */ /*******************************************************************/ @@ -24,6 +24,12 @@ BOOL isMemoryReadable(const TADDR start, unsigned len) } CONTRACTL_END; +#if !defined(DACCESS_COMPILE) && defined(FEATURE_PAL) + + return PAL_ProbeMemory((PVOID)start, len, FALSE); + +#else // !DACCESS_COMPILE && FEATURE_PAL + // // To accomplish this in a no-throw way, we have to touch each and every page // and see if it is in memory or not. @@ -87,6 +93,7 @@ BOOL isMemoryReadable(const TADDR start, unsigned len) } return 1; +#endif // !DACCESS_COMPILE && FEATURE_PAL } -- 2.7.4