1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
15 Implementation of Win32 debugging API functions.
24 #undef _LARGEFILE64_SOURCE
25 #undef _FILE_OFFSET_BITS
28 #include "pal/dbgmsg.h"
29 SET_DEFAULT_DEBUG_CHANNEL(DEBUG); // some headers have code with asserts, so do this first
31 #include "pal/thread.hpp"
32 #include "pal/procobj.hpp"
33 #include "pal/file.hpp"
35 #include "pal/palinternal.h"
36 #include "pal/process.h"
37 #include "pal/context.h"
38 #include "pal/debug.h"
39 #include "pal/environ.h"
40 #include "pal/malloc.hpp"
41 #include "pal/module.h"
42 #include "pal/stackstring.hpp"
43 #include "pal/virtual.h"
49 #elif HAVE_TTRACE // HAVE_PROCFS_CTL
50 #include <sys/ttrace.h>
52 #include <sys/ptrace.h>
53 #endif // HAVE_PROCFS_CTL
55 #include <mach/mach.h>
56 #endif // HAVE_VM_READ
58 #include <sys/types.h>
63 #endif // HAVE_PROCFS_H
65 #if HAVE_MACH_EXCEPTIONS
66 #include "../exception/machexception.h"
67 #endif // HAVE_MACH_EXCEPTIONS
69 using namespace CorUnix;
71 extern "C" void DBG_DebugBreak_End();
74 #define CTL_ATTACH "attach"
75 #define CTL_DETACH "detach"
76 #define CTL_WAIT "wait"
77 #endif // HAVE_PROCFS_CTL
79 /* ------------------- Constant definitions ----------------------------------*/
81 #if !HAVE_VM_READ && !HAVE_PROCFS_CTL
82 const BOOL DBG_ATTACH = TRUE;
83 const BOOL DBG_DETACH = FALSE;
85 static const char PAL_OUTPUTDEBUGSTRING[] = "PAL_OUTPUTDEBUGSTRING";
88 #define ENABLE_RUN_ON_DEBUG_BREAK 1
91 #ifdef ENABLE_RUN_ON_DEBUG_BREAK
92 static const char PAL_RUN_ON_DEBUG_BREAK[] = "PAL_RUN_ON_DEBUG_BREAK";
93 #endif // ENABLE_RUN_ON_DEBUG_BREAK
95 /* ------------------- Static function prototypes ----------------------------*/
97 #if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE
99 DBGWriteProcMem_Int(DWORD processId, int *addr, int data);
101 DBGWriteProcMem_IntWithMask(DWORD processId, int *addr, int data,
103 #endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE
105 #if !HAVE_VM_READ && !HAVE_PROCFS_CTL
108 DBGAttachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId);
111 DBGDetachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId);
114 DBGSetProcessAttached(CPalThread *pThread, HANDLE hProcess, BOOL bAttach);
116 #endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL
122 FlushInstructionCache
124 The FlushInstructionCache function flushes the instruction cache for
125 the specified process.
129 This is a no-op for x86 architectures where the instruction and data
130 caches are coherent in hardware. For non-X86 architectures, this call
131 usually maps to a kernel API to flush the D-caches on all processors.
136 FlushInstructionCache(
138 IN LPCVOID lpBaseAddress,
143 PERF_ENTRY(FlushInstructionCache);
144 ENTRY("FlushInstructionCache (hProcess=%p, lpBaseAddress=%p dwSize=%d)\
145 \n", hProcess, lpBaseAddress, dwSize);
147 if (lpBaseAddress != NULL)
149 Ret = DBG_FlushInstructionCache(lpBaseAddress, dwSize);
156 LOGEXIT("FlushInstructionCache returns BOOL %d\n", Ret);
157 PERF_EXIT(FlushInstructionCache);
171 IN LPCSTR lpOutputString)
173 PERF_ENTRY(OutputDebugStringA);
174 ENTRY("OutputDebugStringA (lpOutputString=%p (%s))\n",
175 lpOutputString ? lpOutputString : "NULL",
176 lpOutputString ? lpOutputString : "NULL");
178 // As we don't support debug events, we are going to output the debug string
179 // to stderr instead of generating OUT_DEBUG_STRING_EVENT. It's safe to tell
180 // EnvironGetenv not to make a copy of the value here since we only want to
181 // check whether it exists, not actually use it.
182 if ((lpOutputString != NULL) &&
183 (NULL != EnvironGetenv(PAL_OUTPUTDEBUGSTRING, /* copyValue */ FALSE)))
185 fprintf(stderr, "%s", lpOutputString);
188 LOGEXIT("OutputDebugStringA returns\n");
189 PERF_EXIT(OutputDebugStringA);
201 IN LPCWSTR lpOutputString)
203 CHAR *lpOutputStringA;
206 PERF_ENTRY(OutputDebugStringW);
207 ENTRY("OutputDebugStringW (lpOutputString=%p (%S))\n",
208 lpOutputString ? lpOutputString: W16_NULLSTRING,
209 lpOutputString ? lpOutputString: W16_NULLSTRING);
211 if (lpOutputString == NULL)
213 OutputDebugStringA("");
217 if ((strLen = WideCharToMultiByte(CP_ACP, 0, lpOutputString, -1, NULL, 0,
221 ASSERT("failed to get wide chars length\n");
222 SetLastError(ERROR_INTERNAL_ERROR);
226 /* strLen includes the null terminator */
227 if ((lpOutputStringA = (LPSTR) InternalMalloc((strLen * sizeof(CHAR)))) == NULL)
229 ERROR("Insufficient memory available !\n");
230 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
234 if(! WideCharToMultiByte(CP_ACP, 0, lpOutputString, -1,
235 lpOutputStringA, strLen, NULL, NULL))
237 ASSERT("failed to convert wide chars to multibytes\n");
238 SetLastError(ERROR_INTERNAL_ERROR);
239 free(lpOutputStringA);
243 OutputDebugStringA(lpOutputStringA);
244 free(lpOutputStringA);
247 LOGEXIT("OutputDebugStringW returns\n");
248 PERF_EXIT(OutputDebugStringW);
251 #ifdef ENABLE_RUN_ON_DEBUG_BREAK
253 When DebugBreak() is called, if PAL_RUN_ON_DEBUG_BREAK is set,
254 DebugBreak() will execute whatever command is in there.
256 PAL_RUN_ON_DEBUG_BREAK must be no longer than 255 characters.
258 This command string inherits the current process's environment,
260 PAL_EXE_PID - the process ID of the current process
261 PAL_EXE_NAME - the name of the executable of the current process
263 When DebugBreak() runs this string, it periodically polls the child process
264 and blocks until it finishes. If you use this mechanism to start a
265 debugger, you can break this poll loop by setting the "spin" variable in
266 run_debug_command()'s frame to 0, and then the parent process can
269 suggested values for PAL_RUN_ON_DEBUG_BREAK:
270 to halt the process for later inspection:
271 'echo stopping $PAL_EXE_PID; kill -STOP $PAL_EXE_PID; sleep 10'
273 to print out the stack trace:
274 'pstack $PAL_EXE_PID'
276 to invoke the gdb debugger on the process:
277 'set -x; gdb $PAL_EXE_NAME $PAL_EXE_PID'
279 to invoke the ddd debugger on the process (requires X11):
280 'set -x; ddd $PAL_EXE_NAME $PAL_EXE_PID'
285 run_debug_command (const char *command)
288 Volatile<int> spin = 1;
294 printf("Spawning command: %s\n", command);
301 const char *argv[4] = { "sh", "-c", command, 0 };
302 execv("/bin/sh", (char **)argv);
306 /* We continue either when the spawned process has stopped, or when
307 an attached debugger sets spin to 0 */
310 int ret = waitpid(pid, &status, WNOHANG);
313 /* I tried to use sleep for this, and that works everywhere except
314 FreeBSD. The problem on FreeBSD is that if the process gets a
315 signal while blocked in sleep(), gdb is confused by the stack */
316 for (i = 0; i < 1000000; i++)
319 else if (ret == -1) {
320 if (errno != EINTR) {
324 else if (WIFEXITED(status)) {
325 return WEXITSTATUS(status);
328 fprintf (stderr, "unexpected return from waitpid\n");
334 #endif // ENABLE_RUN_ON_DEBUG_BREAK
336 #define PID_TEXT "PAL_EXE_PID="
337 #define EXE_TEXT "PAL_EXE_NAME="
343 #ifdef ENABLE_RUN_ON_DEBUG_BREAK
344 extern MODSTRUCT exe_module;
346 char *command_string = EnvironGetenv(PAL_RUN_ON_DEBUG_BREAK);
349 char pid_buf[sizeof (PID_TEXT) + 32];
350 PathCharString exe_bufString;
351 int libNameLength = 10;
353 if (exe_module.lib_name != NULL)
355 libNameLength = PAL_wcslen(exe_module.lib_name);
358 SIZE_T dwexe_buf = strlen(EXE_TEXT) + libNameLength + 1;
359 CHAR * exe_buf = exe_bufString.OpenStringBuffer(dwexe_buf);
366 if (snprintf (pid_buf, sizeof (pid_buf), PID_TEXT "%d", getpid()) <= 0)
371 if (snprintf (exe_buf, sizeof (CHAR) * (dwexe_buf + 1), EXE_TEXT "%ls", (wchar_t *)exe_module.lib_name) <= 0)
376 exe_bufString.CloseBuffer(dwexe_buf);
377 /* strictly speaking, we might want to only set these environment
378 variables in the child process, but if we do that we can't check
379 for errors. putenv/setenv can fail when out of memory */
381 if (!EnvironPutenv (pid_buf, FALSE) || !EnvironPutenv (exe_buf, FALSE))
386 if (run_debug_command (command_string))
391 free(command_string);
400 free(command_string);
403 fprintf (stderr, "Failed to execute command: '%s'\n", command_string);
405 #else // ENABLE_RUN_ON_DEBUG_BREAK
407 #endif // ENABLE_RUN_ON_DEBUG_BREAK
421 PERF_ENTRY(DebugBreak);
422 ENTRY("DebugBreak()\n");
424 if (DebugBreakCommand() <= 0) {
425 // either didn't do anything, or failed
426 TRACE("Calling DBG_DebugBreak\n");
430 LOGEXIT("DebugBreak returns\n");
431 PERF_EXIT(DebugBreak);
438 Returns true if the address is in DBG_DebugBreak.
442 IsInDebugBreak(void *addr)
444 return (addr >= (void *)DBG_DebugBreak) && (addr <= (void *)DBG_DebugBreak_End);
457 IN OUT LPCONTEXT lpContext)
461 CPalThread *pTargetThread;
462 IPalObject *pobjThread = NULL;
465 PERF_ENTRY(GetThreadContext);
466 ENTRY("GetThreadContext (hThread=%p, lpContext=%p)\n",hThread,lpContext);
468 pThread = InternalGetCurrentThread();
470 palError = InternalGetThreadDataFromHandle(
473 0, // THREAD_GET_CONTEXT
478 if (NO_ERROR == palError)
480 if (!pTargetThread->IsDummy())
482 ret = CONTEXT_GetThreadContext(
483 GetCurrentProcessId(),
484 pTargetThread->GetPThreadSelf(),
490 ASSERT("Dummy thread handle passed to GetThreadContext\n");
491 pThread->SetLastError(ERROR_INVALID_HANDLE);
496 pThread->SetLastError(palError);
499 if (NULL != pobjThread)
501 pobjThread->ReleaseReference(pThread);
504 LOGEXIT("GetThreadContext returns ret:%d\n", ret);
505 PERF_EXIT(GetThreadContext);
519 IN CONST CONTEXT *lpContext)
523 CPalThread *pTargetThread;
524 IPalObject *pobjThread = NULL;
527 PERF_ENTRY(SetThreadContext);
528 ENTRY("SetThreadContext (hThread=%p, lpContext=%p)\n",hThread,lpContext);
530 pThread = InternalGetCurrentThread();
532 palError = InternalGetThreadDataFromHandle(
535 0, // THREAD_SET_CONTEXT
540 if (NO_ERROR == palError)
542 if (!pTargetThread->IsDummy())
544 ret = CONTEXT_SetThreadContext(
545 GetCurrentProcessId(),
546 pTargetThread->GetPThreadSelf(),
552 ASSERT("Dummy thread handle passed to SetThreadContext\n");
553 pThread->SetLastError(ERROR_INVALID_HANDLE);
558 pThread->SetLastError(palError);
561 if (NULL != pobjThread)
563 pobjThread->ReleaseReference(pThread);
569 #if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE
575 write one int to a process memory address
578 processId : process handle
579 addr : memory address where the int should be written
580 data : int to be written in addr
583 Return 1 if it succeeds, or 0 if it's fails
587 DBGWriteProcMem_Int(IN DWORD processId,
591 if (PAL_PTRACE( PAL_PT_WRITE_D, processId, addr, data ) == -1)
595 ERROR("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed "
596 "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno));
597 SetLastError(ERROR_INVALID_ADDRESS);
601 ASSERT("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed "
602 "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno));
603 SetLastError(ERROR_INTERNAL_ERROR);
613 DBGWriteProcMem_IntWithMask
616 write one int to a process memory address space using mask
619 processId : process ID
620 addr : memory address where the int should be written
621 data : int to be written in addr
622 mask : the mask used to write only a parts of data
625 Return 1 if it succeeds, or 0 if it's fails
629 DBGWriteProcMem_IntWithMask(IN DWORD processId,
632 IN unsigned int mask )
639 if (((readInt = PAL_PTRACE( PAL_PT_READ_D, processId, addr, 0 )) == -1)
644 ERROR("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed "
645 "errno:%d (%s)\n", processId, addr, errno, strerror(errno));
646 SetLastError(ERROR_INVALID_ADDRESS);
650 ASSERT("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed "
651 "errno:%d (%s)\n", processId, addr, errno, strerror(errno));
652 SetLastError(ERROR_INTERNAL_ERROR);
657 data = (data & mask) | (readInt & ~mask);
659 return DBGWriteProcMem_Int(processId, addr, data);
661 #endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE
663 #if !HAVE_VM_READ && !HAVE_PROCFS_CTL
671 Attach the indicated process to the current process.
673 if the indicated process is already attached by the current process, then
674 increment the number of attachment pending. if ot, attach it to the current
675 process (with PT_ATTACH).
678 hProcess : handle to process to attach to
679 processId : process ID to attach
681 Return true if it succeeds, or false if it's fails
696 #endif // HAVE_PROCFS_CTL
699 DBGSetProcessAttached(pThread, hProcess, DBG_ATTACH);
701 if (attchmentCount == -1)
703 /* Failed to set the process as attached */
707 if (attchmentCount == 1)
710 struct timespec waitTime;
712 // FreeBSD has some trouble when a series of attach/detach sequences
713 // occurs too close together. When this happens, we'll be able to
714 // attach to the process, but waiting for the process to stop
715 // (either via writing "wait" to /proc/<pid>/ctl or via waitpid)
716 // will hang. If we pause for a very short amount of time before
717 // trying to attach, we don't run into this situation.
719 waitTime.tv_nsec = 50000000;
720 nanosleep(&waitTime, NULL);
722 sprintf_s(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId);
723 fd = InternalOpen(ctlPath, O_WRONLY);
726 ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath,
727 errno, strerror(errno));
731 if (write(fd, CTL_ATTACH, sizeof(CTL_ATTACH)) < (int)sizeof(CTL_ATTACH))
733 ERROR("Failed to attach to %s: errno is %d (%s)\n", ctlPath,
734 errno, strerror(errno));
739 if (write(fd, CTL_WAIT, sizeof(CTL_WAIT)) < (int)sizeof(CTL_WAIT))
741 ERROR("Failed to wait for %s: errno is %d (%s)\n", ctlPath,
742 errno, strerror(errno));
748 if (ttrace(TT_PROC_ATTACH, processId, 0, TT_DETACH_ON_EXIT, TT_VERSION, 0) == -1)
752 ASSERT("ttrace(TT_PROC_ATTACH, pid:%d) failed errno:%d (%s)\n",
753 processId, errno, strerror(errno));
758 if (PAL_PTRACE( PAL_PT_ATTACH, processId, 0, 0 ) == -1)
762 ASSERT("ptrace(PT_ATTACH, pid:%d) failed errno:%d (%s)\n",
763 processId, errno, strerror(errno));
768 if (waitpid(processId, NULL, WUNTRACED) == -1)
772 ASSERT("waitpid(pid:%d, NULL, WUNTRACED) failed.errno:%d"
773 " (%s)\n", processId, errno, strerror(errno));
777 #endif // HAVE_PROCFS_CTL
784 if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH))
786 ASSERT("Failed to detach from %s: errno is %d (%s)\n", ctlPath,
787 errno, strerror(errno));
792 if (PAL_PTRACE(PAL_PT_DETACH, processId, 0, 0) == -1)
794 ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", processId,
795 errno, strerror(errno));
797 #endif // HAVE_PROCFS_CTL
801 DBGSetProcessAttached(pThread, hProcess, DBG_DETACH);
804 if (errno == ESRCH || errno == ENOENT || errno == EBADF)
806 ERROR("Invalid process ID:%d\n", processId);
807 SetLastError(ERROR_INVALID_PARAMETER);
811 SetLastError(ERROR_INTERNAL_ERROR);
821 Detach the indicated process from the current process.
823 if the indicated process is already attached by the current process, then
824 decrement the number of attachment pending and detach it from the current
825 process (with PT_DETACH) if there's no more attachment left.
828 hProcess : process handle
829 processId : process ID
832 Return true if it succeeds, or true if it's fails
846 #endif // HAVE_PROCFS_CTL
848 nbAttachLeft = DBGSetProcessAttached(pThread, hProcess, DBG_DETACH);
850 if (nbAttachLeft == -1)
852 /* Failed to set the process as detached */
856 /* check if there's no more attachment left on processId */
857 if (nbAttachLeft == 0)
860 sprintf(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId);
861 fd = InternalOpen(pThread, ctlPath, O_WRONLY);
866 ERROR("Invalid process ID: %d\n", processId);
867 SetLastError(ERROR_INVALID_PARAMETER);
871 ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath,
872 errno, strerror(errno));
873 SetLastError(ERROR_INTERNAL_ERROR);
878 if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH))
880 ERROR("Failed to detach from %s: errno is %d (%s)\n", ctlPath,
881 errno, strerror(errno));
888 if (ttrace(TT_PROC_DETACH, processId, 0, 0, 0, 0) == -1)
892 ERROR("Invalid process ID: %d\n", processId);
893 SetLastError(ERROR_INVALID_PARAMETER);
897 ASSERT("ttrace(TT_PROC_DETACH, pid:%d) failed. errno:%d (%s)\n",
898 processId, errno, strerror(errno));
899 SetLastError(ERROR_INTERNAL_ERROR);
904 if (PAL_PTRACE(PAL_PT_DETACH, processId, 1, 0) == -1)
908 ERROR("Invalid process ID: %d\n", processId);
909 SetLastError(ERROR_INVALID_PARAMETER);
913 ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n",
914 processId, errno, strerror(errno));
915 SetLastError(ERROR_INTERNAL_ERROR);
919 #endif // HAVE_PROCFS_CTL
922 if (kill(processId, SIGCONT) == -1)
924 ERROR("Failed to continue the detached process:%d errno:%d (%s)\n",
925 processId, errno, strerror(errno));
928 #endif // !HAVE_TTRACE
935 DBGSetProcessAttached
938 saves the current process Id in the attached process structure
941 hProcess : process handle
942 bAttach : true (false) to set the process as attached (as detached)
944 returns the number of attachment left on attachedProcId, or -1 if it fails
947 DBGSetProcessAttached(
953 PAL_ERROR palError = NO_ERROR;
954 IPalObject *pobjProcess = NULL;
955 IDataLock *pDataLock = NULL;
956 CProcProcessLocalData *pLocalData = NULL;
958 CAllowedObjectTypes aotProcess(otiProcess);
960 palError = g_pObjectManager->ReferenceObjectByHandle(
968 if (NO_ERROR != palError)
970 goto DBGSetProcessAttachedExit;
973 palError = pobjProcess->GetProcessLocalData(
977 reinterpret_cast<void **>(&pLocalData)
980 if (NO_ERROR != palError)
982 goto DBGSetProcessAttachedExit;
987 pLocalData->lAttachCount += 1;
991 pLocalData->lAttachCount -= 1;
993 if (pLocalData->lAttachCount < 0)
995 ASSERT("pLocalData->lAttachCount < 0 check for extra DBGDetachProcess calls\n");
996 palError = ERROR_INTERNAL_ERROR;
997 goto DBGSetProcessAttachedExit;
1001 ret = pLocalData->lAttachCount;
1003 DBGSetProcessAttachedExit:
1005 if (NULL != pDataLock)
1007 pDataLock->ReleaseLock(pThread, TRUE);
1010 if (NULL != pobjProcess)
1012 pobjProcess->ReleaseReference(pThread);
1018 #endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL
1022 PAL_CreateExecWatchpoint
1025 Creates an OS exec watchpoint for the specified instruction
1026 and thread. This function should only be called on architectures
1027 that do not support a hardware single-step mode (e.g., SPARC).
1030 hThread : the thread for which the watchpoint is to apply
1031 pvInstruction : the instruction on which the watchpoint is to be set
1038 PAL_CreateExecWatchpoint(
1043 PERF_ENTRY(PAL_CreateExecWatchpoint);
1044 ENTRY("PAL_CreateExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction);
1046 DWORD dwError = ERROR_NOT_SUPPORTED;
1050 CPalThread *pThread = NULL;
1051 CPalThread *pTargetThread = NULL;
1052 IPalObject *pobjThread = NULL;
1063 // We must never set a watchpoint on an instruction that enters a syscall;
1064 // if such a request comes in we succeed it w/o actually creating the
1065 // watchpoint. This mirrors the behavior of setting the single-step flag
1066 // in a thread context when the thread is w/in a system service -- the
1067 // flag is ignored and will not be present when the thread returns
1071 #if defined(_SPARC_)
1072 if (*(DWORD*)pvInstruction == 0x91d02008) // ta 8
1074 TRACE("Watchpoint requested on sysenter instruction -- ignoring");
1075 dwError = ERROR_SUCCESS;
1076 goto PAL_CreateExecWatchpointExit;
1079 #error Need syscall instruction for this platform
1082 pThread = InternalGetCurrentThread();
1084 dwError = InternalGetThreadDataFromHandle(
1087 0, // THREAD_SET_CONTEXT
1092 if (NO_ERROR != dwError)
1094 goto PAL_CreateExecWatchpointExit;
1097 snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId());
1099 fd = InternalOpen(pThread, ctlPath, O_WRONLY);
1102 ERROR("Failed to open %s\n", ctlPath);
1103 dwError = ERROR_INVALID_ACCESS;
1104 goto PAL_CreateExecWatchpointExit;
1107 ctlStruct.ctlCode = PCWATCH;
1108 ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction;
1109 ctlStruct.prwatch.pr_size = sizeof(DWORD);
1110 ctlStruct.prwatch.pr_wflags = WA_EXEC | WA_TRAPAFTER;
1112 if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct))
1114 ERROR("Failure writing control structure (errno = %u)\n", errno);
1115 dwError = ERROR_INTERNAL_ERROR;
1116 goto PAL_CreateExecWatchpointExit;
1119 dwError = ERROR_SUCCESS;
1121 PAL_CreateExecWatchpointExit:
1123 if (NULL != pobjThread)
1125 pobjThread->ReleaseReference(pThread);
1133 #endif // HAVE_PRWATCH_T
1135 LOGEXIT("PAL_CreateExecWatchpoint returns ret:%d\n", dwError);
1136 PERF_EXIT(PAL_CreateExecWatchpoint);
1142 PAL_DeleteExecWatchpoint
1145 Deletes an OS exec watchpoint for the specified instruction
1146 and thread. This function should only be called on architectures
1147 that do not support a hardware single-step mode (e.g., SPARC).
1150 hThread : the thread to remove the watchpoint from
1151 pvInstruction : the instruction for which the watchpoint is to be removed
1154 A Win32 error code. Attempting to delete a watchpoint that does not exist
1155 may or may not result in an error, depending on the behavior of the
1156 underlying operating system.
1160 PAL_DeleteExecWatchpoint(
1165 PERF_ENTRY(PAL_DeleteExecWatchpoint);
1166 ENTRY("PAL_DeleteExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction);
1168 DWORD dwError = ERROR_NOT_SUPPORTED;
1172 CPalThread *pThread = NULL;
1173 CPalThread *pTargetThread = NULL;
1174 IPalObject *pobjThread = NULL;
1185 pThread = InternalGetCurrentThread();
1187 dwError = InternalGetThreadDataFromHandle(
1190 0, // THREAD_SET_CONTEXT
1195 if (NO_ERROR != dwError)
1197 goto PAL_DeleteExecWatchpointExit;
1200 snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId());
1202 fd = InternalOpen(pThread, ctlPath, O_WRONLY);
1205 ERROR("Failed to open %s\n", ctlPath);
1206 dwError = ERROR_INVALID_ACCESS;
1207 goto PAL_DeleteExecWatchpointExit;
1210 ctlStruct.ctlCode = PCWATCH;
1211 ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction;
1212 ctlStruct.prwatch.pr_size = sizeof(DWORD);
1213 ctlStruct.prwatch.pr_wflags = 0;
1215 if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct))
1217 ERROR("Failure writing control structure (errno = %u)\n", errno);
1218 dwError = ERROR_INTERNAL_ERROR;
1219 goto PAL_DeleteExecWatchpointExit;
1222 dwError = ERROR_SUCCESS;
1224 PAL_DeleteExecWatchpointExit:
1226 if (NULL != pobjThread)
1228 pobjThread->ReleaseReference(pThread);
1236 #endif // HAVE_PRWATCH_T
1238 LOGEXIT("PAL_DeleteExecWatchpoint returns ret:%d\n", dwError);
1239 PERF_EXIT(PAL_DeleteExecWatchpoint);
1243 // We want to enable hardware exception handling for ReadProcessMemory
1244 // and WriteProcessMemory in all cases since it is acceptable if they
1245 // hit AVs, so redefine HardwareExceptionHolder for these two functions
1246 // (here to the end of the file).
1247 #undef HardwareExceptionHolder
1248 #define HardwareExceptionHolder CatchHardwareExceptionHolder __catchHardwareException;
1260 IN LPCVOID lpBaseAddress,
1263 OUT SIZE_T * lpNumberOfBytesRead
1266 CPalThread *pThread;
1268 Volatile<BOOL> ret = FALSE;
1269 Volatile<SIZE_T> numberOfBytesRead = 0;
1271 kern_return_t result;
1273 LONG_PTR bytesToRead;
1274 #elif HAVE_PROCFS_CTL
1283 #if !HAVE_PROCFS_CTL && !HAVE_TTRACE
1284 int* lpBaseAddressAligned;
1286 #endif // !HAVE_PROCFS_CTL && !HAVE_TTRACE
1288 PERF_ENTRY(ReadProcessMemory);
1289 ENTRY("ReadProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, "
1290 "nSize=%u, lpNumberOfBytesRead=%p)\n",hProcess,lpBaseAddress,
1291 lpBuffer, (unsigned int)nSize, lpNumberOfBytesRead);
1293 pThread = InternalGetCurrentThread();
1295 if (!(processId = PROCGetProcessIDFromHandle(hProcess)))
1297 ERROR("Invalid process handler hProcess:%p.",hProcess);
1298 SetLastError(ERROR_INVALID_HANDLE);
1302 // Check if the read request is for the current process.
1303 // We don't need ptrace in that case.
1304 if (GetCurrentProcessId() == processId)
1306 TRACE("We are in the same process, so ptrace is not needed\n");
1310 LPCVOID lpBaseAddress;
1313 SIZE_T numberOfBytesRead;
1316 param.lpBaseAddress = lpBaseAddress;
1317 param.lpBuffer = lpBuffer;
1318 param.nSize = nSize;
1319 param.numberOfBytesRead = numberOfBytesRead;
1322 PAL_TRY(Param *, pParam, ¶m)
1326 // Seg fault in memcpy can't be caught
1327 // so we simulate the memcpy here
1329 for (i = 0; i<pParam->nSize; i++)
1331 *((char*)(pParam->lpBuffer)+i) = *((char*)(pParam->lpBaseAddress)+i);
1334 pParam->numberOfBytesRead = pParam->nSize;
1337 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1339 SetLastError(ERROR_ACCESS_DENIED);
1343 numberOfBytesRead = param.numberOfBytesRead;
1349 result = task_for_pid(mach_task_self(), processId, &task);
1350 if (result != KERN_SUCCESS)
1352 ERROR("No Mach task for pid %d: %d\n", processId, ret.Load());
1353 SetLastError(ERROR_INVALID_HANDLE);
1356 // vm_read_overwrite usually requires that the address be page-aligned
1357 // and the size be a multiple of the page size. We can't differentiate
1358 // between the cases in which that's required and those in which it
1359 // isn't, so we do it all the time.
1360 lpBaseAddressAligned = (int*)((SIZE_T) lpBaseAddress & ~VIRTUAL_PAGE_MASK);
1361 offset = ((SIZE_T) lpBaseAddress & VIRTUAL_PAGE_MASK);
1363 data = (char*)alloca(VIRTUAL_PAGE_SIZE);
1366 vm_size_t bytesRead;
1368 bytesToRead = VIRTUAL_PAGE_SIZE - offset;
1369 if (bytesToRead > (LONG_PTR)nSize)
1371 bytesToRead = nSize;
1373 bytesRead = VIRTUAL_PAGE_SIZE;
1374 result = vm_read_overwrite(task, (vm_address_t) lpBaseAddressAligned,
1375 VIRTUAL_PAGE_SIZE, (vm_address_t) data, &bytesRead);
1376 if (result != KERN_SUCCESS || bytesRead != VIRTUAL_PAGE_SIZE)
1378 ERROR("vm_read_overwrite failed for %d bytes from %p in %d: %d\n",
1379 VIRTUAL_PAGE_SIZE, (char *) lpBaseAddressAligned, task, result);
1380 if (result <= KERN_RETURN_MAX)
1382 SetLastError(ERROR_INVALID_ACCESS);
1386 SetLastError(ERROR_INTERNAL_ERROR);
1390 memcpy((LPSTR)lpBuffer + numberOfBytesRead, data + offset, bytesToRead);
1391 numberOfBytesRead.Store(numberOfBytesRead.Load() + bytesToRead);
1392 lpBaseAddressAligned = (int*)((char*)lpBaseAddressAligned + VIRTUAL_PAGE_SIZE);
1393 nSize -= bytesToRead;
1397 #else // HAVE_VM_READ
1399 snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME);
1400 fd = InternalOpen(memPath, O_RDONLY);
1403 ERROR("Failed to open %s\n", memPath);
1404 SetLastError(ERROR_INVALID_ACCESS);
1409 // off_t may be greater in size than void*, so first cast to
1410 // an unsigned type to ensure that no sign extension takes place
1413 offset = (off_t) (UINT_PTR) lpBaseAddress;
1415 if (lseek(fd, offset, SEEK_SET) == -1)
1417 ERROR("Failed to seek to base address\n");
1418 SetLastError(ERROR_INVALID_ACCESS);
1422 numberOfBytesRead = read(fd, lpBuffer, nSize);
1425 #else // HAVE_PROCFS_CTL
1426 // Attach the process before calling ttrace/ptrace otherwise it fails.
1427 if (DBGAttachProcess(pThread, hProcess, processId))
1430 if (ttrace(TT_PROC_RDDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1)
1432 if (errno == EFAULT)
1434 ERROR("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed"
1435 " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer,
1436 errno, strerror(errno));
1438 SetLastError(ERROR_ACCESS_DENIED);
1442 ASSERT("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed"
1443 " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer,
1444 errno, strerror(errno));
1445 SetLastError(ERROR_INTERNAL_ERROR);
1451 numberOfBytesRead = nSize;
1454 #else // HAVE_TTRACE
1456 offset = (SIZE_T)lpBaseAddress % sizeof(int);
1457 lpBaseAddressAligned = (int*)((char*)lpBaseAddress - offset);
1458 nbInts = (nSize + offset)/sizeof(int) +
1459 ((nSize + offset)%sizeof(int) ? 1:0);
1461 /* before transferring any data to lpBuffer we should make sure that all
1462 data is accessible for read. so we need to use a temp buffer for that.*/
1463 if (!(lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int)))))
1465 ERROR("Insufficient memory available !\n");
1466 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1470 for (ptrInt = lpTmpBuffer; nbInts; ptrInt++,
1471 lpBaseAddressAligned++, nbInts--)
1475 PAL_PTRACE(PAL_PT_READ_D, processId, lpBaseAddressAligned, 0);
1476 if (*ptrInt == -1 && errno)
1478 if (errno == EFAULT)
1480 ERROR("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed"
1481 " errno=%d (%s)\n", processId, lpBaseAddressAligned,
1482 errno, strerror(errno));
1484 SetLastError(ptrInt == lpTmpBuffer ? ERROR_ACCESS_DENIED :
1485 ERROR_PARTIAL_COPY);
1489 ASSERT("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed"
1490 " errno=%d (%s)\n", processId, lpBaseAddressAligned,
1491 errno, strerror(errno));
1492 SetLastError(ERROR_INTERNAL_ERROR);
1499 /* transfer data from temp buffer to lpBuffer */
1500 memcpy( (char *)lpBuffer, ((char*)lpTmpBuffer) + offset, nSize);
1501 numberOfBytesRead = nSize;
1503 #endif // HAVE_TTRACE
1507 /* Failed to attach processId */
1510 #endif // HAVE_PROCFS_CTL
1524 #endif // !HAVE_TTRACE
1526 #if !HAVE_PROCFS_CTL
1528 if (!DBGDetachProcess(pThread, hProcess, processId))
1530 /* Failed to detach processId */
1533 #endif // HAVE_PROCFS_CTL
1534 #endif // HAVE_VM_READ
1537 if (lpNumberOfBytesRead)
1539 *lpNumberOfBytesRead = numberOfBytesRead;
1541 LOGEXIT("ReadProcessMemory returns BOOL %d\n", ret.Load());
1542 PERF_EXIT(ReadProcessMemory);
1556 IN LPVOID lpBaseAddress,
1557 IN LPCVOID lpBuffer,
1559 OUT SIZE_T * lpNumberOfBytesWritten
1563 CPalThread *pThread;
1565 Volatile<BOOL> ret = FALSE;
1566 Volatile<SIZE_T> numberOfBytesWritten = 0;
1568 kern_return_t result;
1570 #elif HAVE_PROCFS_CTL
1573 LONG_PTR bytesWritten;
1576 SIZE_T FirstIntOffset;
1577 SIZE_T LastIntOffset;
1578 unsigned int FirstIntMask;
1579 unsigned int LastIntMask;
1581 int *lpTmpBuffer = 0, *lpInt;
1582 int* lpBaseAddressAligned;
1585 PERF_ENTRY(WriteProcessMemory);
1586 ENTRY("WriteProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, "
1587 "nSize=%u, lpNumberOfBytesWritten=%p)\n",
1588 hProcess,lpBaseAddress, lpBuffer, (unsigned int)nSize, lpNumberOfBytesWritten);
1590 pThread = InternalGetCurrentThread();
1592 if (!(nSize && (processId = PROCGetProcessIDFromHandle(hProcess))))
1594 ERROR("Invalid nSize:%u number or invalid process handler "
1595 "hProcess:%p\n", (unsigned int)nSize, hProcess);
1596 SetLastError(ERROR_INVALID_PARAMETER);
1600 // Check if the write request is for the current process.
1601 // In that case we don't need ptrace.
1602 if (GetCurrentProcessId() == processId)
1604 TRACE("We are in the same process so we don't need ptrace\n");
1608 LPVOID lpBaseAddress;
1611 SIZE_T numberOfBytesWritten;
1614 param.lpBaseAddress = lpBaseAddress;
1615 param.lpBuffer = lpBuffer;
1616 param.nSize = nSize;
1617 param.numberOfBytesWritten = numberOfBytesWritten;
1620 PAL_TRY(Param *, pParam, ¶m)
1624 // Seg fault in memcpy can't be caught
1625 // so we simulate the memcpy here
1627 for (i = 0; i<pParam->nSize; i++)
1629 *((char*)(pParam->lpBaseAddress)+i) = *((char*)(pParam->lpBuffer)+i);
1632 pParam->numberOfBytesWritten = pParam->nSize;
1635 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1637 SetLastError(ERROR_ACCESS_DENIED);
1641 numberOfBytesWritten = param.numberOfBytesWritten;
1647 result = task_for_pid(mach_task_self(), processId, &task);
1648 if (result != KERN_SUCCESS)
1650 ERROR("No Mach task for pid %d: %d\n", processId, ret.Load());
1651 SetLastError(ERROR_INVALID_HANDLE);
1654 result = vm_write(task, (vm_address_t) lpBaseAddress,
1655 (vm_address_t) lpBuffer, nSize);
1656 if (result != KERN_SUCCESS)
1658 ERROR("vm_write failed for %d bytes from %p in %d: %d\n",
1659 (int)nSize, lpBaseAddress, task, result);
1660 if (result <= KERN_RETURN_MAX)
1662 SetLastError(ERROR_ACCESS_DENIED);
1666 SetLastError(ERROR_INTERNAL_ERROR);
1670 numberOfBytesWritten = nSize;
1672 #else // HAVE_VM_READ
1674 snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME);
1675 fd = InternalOpen(memPath, O_WRONLY);
1678 ERROR("Failed to open %s\n", memPath);
1679 SetLastError(ERROR_INVALID_ACCESS);
1684 // off_t may be greater in size than void*, so first cast to
1685 // an unsigned type to ensure that no sign extension takes place
1688 offset = (off_t) (UINT_PTR) lpBaseAddress;
1690 if (lseek(fd, offset, SEEK_SET) == -1)
1692 ERROR("Failed to seek to base address\n");
1693 SetLastError(ERROR_INVALID_ACCESS);
1697 bytesWritten = write(fd, lpBuffer, nSize);
1698 if (bytesWritten < 0)
1700 ERROR("Failed to write to %s\n", memPath);
1701 SetLastError(ERROR_INVALID_ACCESS);
1705 numberOfBytesWritten = bytesWritten;
1708 #else // HAVE_PROCFS_CTL
1709 /* Attach the process before calling ptrace otherwise it fails */
1710 if (DBGAttachProcess(pThread, hProcess, processId))
1713 if (ttrace(TT_PROC_WRDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1)
1715 if (errno == EFAULT)
1717 ERROR("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed"
1718 " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer,
1719 errno, strerror(errno));
1721 SetLastError(ERROR_ACCESS_DENIED);
1725 ASSERT("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed"
1726 " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer,
1727 errno, strerror(errno));
1728 SetLastError(ERROR_INTERNAL_ERROR);
1734 numberOfBytesWritten = nSize;
1737 #else // HAVE_TTRACE
1739 FirstIntOffset = (SIZE_T)lpBaseAddress % sizeof(int);
1741 FirstIntMask <<= (FirstIntOffset * 8);
1743 nbInts = (nSize + FirstIntOffset) / sizeof(int) +
1744 (((nSize + FirstIntOffset)%sizeof(int)) ? 1:0);
1745 lpBaseAddressAligned = (int*)((char*)lpBaseAddress - FirstIntOffset);
1747 if ((lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int)))) == NULL)
1749 ERROR("Insufficient memory available !\n");
1750 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1754 memcpy((char *)lpTmpBuffer + FirstIntOffset, (char *)lpBuffer, nSize);
1755 lpInt = lpTmpBuffer;
1757 LastIntOffset = (nSize + FirstIntOffset) % sizeof(int);
1759 LastIntMask >>= ((sizeof(int) - LastIntOffset) * 8);
1763 if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned,
1765 LastIntMask & FirstIntMask)
1770 numberOfBytesWritten = nSize;
1775 if (DBGWriteProcMem_IntWithMask(processId,
1776 lpBaseAddressAligned++,
1777 *lpInt++, FirstIntMask)
1783 while (--nbInts > 1)
1785 if (DBGWriteProcMem_Int(processId, lpBaseAddressAligned++,
1792 if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned,
1793 *lpInt, LastIntMask ) == 0)
1798 numberOfBytesWritten = nSize;
1800 #endif // HAVE_TTRACE
1804 /* Failed to attach processId */
1807 #endif // HAVE_PROCFS_CTL
1821 #endif // !HAVE_TTRACE
1823 #if !HAVE_PROCFS_CTL
1825 if (!DBGDetachProcess(pThread, hProcess, processId))
1827 /* Failed to detach processId */
1830 #endif // !HAVE_PROCFS_CTL
1831 #endif // HAVE_VM_READ
1834 if (lpNumberOfBytesWritten)
1836 *lpNumberOfBytesWritten = numberOfBytesWritten;
1839 LOGEXIT("WriteProcessMemory returns BOOL %d\n", ret.Load());
1840 PERF_EXIT(WriteProcessMemory);