void perror (const char *s) { if (s && *s) fprintf (stderr, "%s: %s\n", s, strwinerror (GetLastError ())); else fprintf (stderr, "%s\n", strwinerror (GetLastError ())); }
/* Attach to a running process. PID is the process ID to attach to, specified by the user or a higher layer. */ static int win32_attach (unsigned long pid) { HANDLE h; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; DWORD err; #ifdef _WIN32_WCE HMODULE dll = GetModuleHandle (_T("COREDLL.DLL")); #else HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL")); #endif DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); if (h != NULL) { if (DebugActiveProcess (pid)) { if (DebugSetProcessKillOnExit != NULL) DebugSetProcessKillOnExit (FALSE); /* win32_wait needs to know we're attaching. */ attaching = 1; do_initial_child_stuff (h, pid, 1); return 0; } CloseHandle (h); } err = GetLastError (); error ("Attach to process failed (error %d): %s\n", (int) err, strwinerror (err)); }
/* Resume all artificially suspended threads if we are continuing execution. */ static int continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr) { struct thread_info *thread = (struct thread_info *) this_thread; int thread_id = * (int *) id_ptr; win32_thread_info *th = inferior_target_data (thread); if ((thread_id == -1 || thread_id == th->tid) && th->suspended) { if (th->context.ContextFlags) { win32_set_thread_context (th); th->context.ContextFlags = 0; } if (ResumeThread (th->h) == (DWORD) -1) { DWORD err = GetLastError (); OUTMSG (("warning: ResumeThread failed in continue_one_thread, " "(error %d): %s\n", (int) err, strwinerror (err))); } th->suspended = 0; } return 0; }
/* Find a thread record given a thread id. If GET_CONTEXT is set then also retrieve the context for this thread. */ static win32_thread_info * thread_rec (ptid_t ptid, int get_context) { struct thread_info *thread; win32_thread_info *th; thread = (struct thread_info *) find_inferior_id (&all_threads, ptid); if (thread == NULL) return NULL; th = inferior_target_data (thread); if (get_context && th->context.ContextFlags == 0) { if (!th->suspended) { if (SuspendThread (th->h) == (DWORD) -1) { DWORD err = GetLastError (); OUTMSG (("warning: SuspendThread failed in thread_rec, " "(error %d): %s\n", (int) err, strwinerror (err))); } else th->suspended = 1; } win32_get_thread_context (th); } return th; }
char * strerror (int error) { static char buf[1024]; DWORD winerr = (DWORD) error; const char *str = get_errstr (winerr); if (str != NULL) strcpy (buf, str); else strwinerror (buf, winerr); return buf; }
static void suspend_one_thread (struct inferior_list_entry *entry) { struct thread_info *thread = (struct thread_info *) entry; win32_thread_info *th = inferior_target_data (thread); if (!th->suspended) { if (SuspendThread (th->h) == (DWORD) -1) { DWORD err = GetLastError (); OUTMSG (("warning: SuspendThread failed in suspend_one_thread, " "(error %d): %s\n", (int) err, strwinerror (err))); } else th->suspended = 1; } }
void win32_require_context (win32_thread_info *th) { if (th->context.ContextFlags == 0) { if (!th->suspended) { if (SuspendThread (th->h) == (DWORD) -1) { DWORD err = GetLastError (); OUTMSG (("warning: SuspendThread failed in thread_rec, " "(error %d): %s\n", (int) err, strwinerror (err))); } else th->suspended = 1; } win32_get_thread_context (th); } }
/* Start a new process. PROGRAM is a path to the program to execute. ARGS is a standard NULL-terminated array of arguments, to be passed to the inferior as ``argv''. Returns the new PID on success, -1 on failure. Registers the new process with the process list. */ static int win32_create_inferior (char *program, char **program_args) { #ifndef USE_WIN32API char real_path[MAXPATHLEN]; char *orig_path, *new_path, *path_ptr; #endif BOOL ret; DWORD flags; char *args; int argslen; int argc; PROCESS_INFORMATION pi; DWORD err; /* win32_wait needs to know we're not attaching. */ attaching = 0; if (!program) error ("No executable specified, specify executable to debug.\n"); flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; #ifndef USE_WIN32API orig_path = NULL; path_ptr = getenv ("PATH"); if (path_ptr) { orig_path = alloca (strlen (path_ptr) + 1); new_path = alloca (cygwin_posix_to_win32_path_list_buf_size (path_ptr)); strcpy (orig_path, path_ptr); cygwin_posix_to_win32_path_list (path_ptr, new_path); setenv ("PATH", new_path, 1); } cygwin_conv_to_win32_path (program, real_path); program = real_path; #endif argslen = 1; for (argc = 1; program_args[argc]; argc++) argslen += strlen (program_args[argc]) + 1; args = alloca (argslen); args[0] = '\0'; for (argc = 1; program_args[argc]; argc++) { /* FIXME: Can we do better about quoting? How does Cygwin handle this? */ strcat (args, " "); strcat (args, program_args[argc]); } OUTMSG2 (("Command line is \"%s\"\n", args)); #ifdef CREATE_NEW_PROCESS_GROUP flags |= CREATE_NEW_PROCESS_GROUP; #endif ret = create_process (program, args, flags, &pi); err = GetLastError (); if (!ret && err == ERROR_FILE_NOT_FOUND) { char *exename = alloca (strlen (program) + 5); strcat (strcpy (exename, program), ".exe"); ret = create_process (exename, args, flags, &pi); err = GetLastError (); } #ifndef USE_WIN32API if (orig_path) setenv ("PATH", orig_path, 1); #endif if (!ret) { error ("Error creating process \"%s%s\", (error %d): %s\n", program, args, (int) err, strwinerror (err)); } else { OUTMSG2 (("Process created: %s\n", (char *) args)); } #ifndef _WIN32_WCE /* On Windows CE this handle can't be closed. The OS reuses it in the debug events, while the 9x/NT versions of Windows probably use a DuplicateHandle'd one. */ CloseHandle (pi.hThread); #endif do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0); return current_process_id; }
static int psapi_get_dll_name (LPVOID BaseAddress, char *dll_name_ret) { DWORD len; MODULEINFO mi; size_t i; HMODULE dh_buf[1]; HMODULE *DllHandle = dh_buf; DWORD cbNeeded; BOOL ok; if (!load_psapi ()) goto failed; cbNeeded = 0; ok = (*win32_EnumProcessModules) (current_process_handle, DllHandle, sizeof (HMODULE), &cbNeeded); if (!ok || !cbNeeded) goto failed; DllHandle = (HMODULE *) alloca (cbNeeded); if (!DllHandle) goto failed; ok = (*win32_EnumProcessModules) (current_process_handle, DllHandle, cbNeeded, &cbNeeded); if (!ok) goto failed; for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++) { if (!(*win32_GetModuleInformation) (current_process_handle, DllHandle[i], &mi, sizeof (mi))) { DWORD err = GetLastError (); error ("Can't get module info: (error %d): %s\n", (int) err, strwinerror (err)); } if (mi.lpBaseOfDll == BaseAddress) { len = (*win32_GetModuleFileNameExA) (current_process_handle, DllHandle[i], dll_name_ret, MAX_PATH); if (len == 0) { DWORD err = GetLastError (); error ("Error getting dll name: (error %d): %s\n", (int) err, strwinerror (err)); } return 1; } } failed: dll_name_ret[0] = '\0'; return 0; }