WaitForDebugEvent */
static HANDLE current_process_handle; /* Currently executing process */
static thread_info *current_thread; /* Info on currently selected thread */
-static DWORD main_thread_id; /* Thread ID of the main thread */
+static DWORD main_thread_id; /* Thread ID of the main thread */
+static pid_t cygwin_pid; /* pid of cygwin process */
/* Counts of things. */
static int exception_count = 0;
static int debug_exceptions = 0; /* show target exceptions */
static int useshell = 0; /* use shell for subprocesses */
-/* Path to shell */
-static char shell[MAX_PATH + 1];
-
/* This vector maps GDB's idea of a register's number into an address
in the win32 exception context vector.
do_child_store_inferior_registers (int r)
{
if (r >= 0)
- read_register_gen (r, ((char *) ¤t_thread->context) + mappings[r]);
+ deprecated_read_register_gen (r, ((char *) ¤t_thread->context) + mappings[r]);
else
{
for (r = 0; r < NUM_REGS; r++)
dll_name_ret,
MAX_PATH);
if (len == 0)
- error ("Error getting dll name: %u\n", GetLastError ());
+ error ("Error getting dll name: %u\n", (unsigned) GetLastError ());
if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
return 1;
{
struct so_stuff *next;
DWORD load_addr;
+ DWORD end_addr;
int loaded;
struct objfile *objfile;
char name[1];
char *p;
WIN32_FIND_DATA w32_fd;
HANDLE h = FindFirstFile(name, &w32_fd);
+ MEMORY_BASIC_INFORMATION m;
size_t len;
if (h == INVALID_HANDLE_VALUE)
so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
so->loaded = 0;
so->load_addr = load_addr;
+ if (!VirtualQueryEx (current_process_handle, (void *) load_addr, &m,
+ sizeof (m)))
+ so->end_addr = (DWORD) m.AllocationBase + m.RegionSize;
+ else
+ so->end_addr = load_addr + 0x2000; /* completely arbitrary */
+
so->next = NULL;
so->objfile = NULL;
strcpy (so->name, ppath);
return 0;
}
+char *
+solib_address (CORE_ADDR address)
+{
+ struct so_stuff *so;
+ for (so = &solib_start; so->next != NULL; so = so->next)
+ if (address >= so->load_addr && address <= so->end_addr)
+ return so->name;
+ return NULL;
+}
+
/* Return name of last loaded DLL. */
char *
child_solib_loaded_library_pathname (int pid)
memset (§ion_addrs, 0, sizeof (section_addrs));
section_addrs.other[0].name = ".text";
section_addrs.other[0].addr = load_addr;
- return safe_symbol_file_add (name, from_tty, NULL, 0, OBJF_SHARED);
+ return safe_symbol_file_add (name, from_tty, §ion_addrs, 0, OBJF_SHARED);
}
/* Load DLL symbol info. */
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
retval = main_thread_id;
+ re_enable_breakpoints_in_shlibs ();
break;
case UNLOAD_DLL_DEBUG_EVENT:
memset (¤t_event, 0, sizeof (current_event));
push_target (&child_ops);
child_init_thread_list ();
+ disable_breakpoints_in_shlibs (1);
child_clear_solibs ();
clear_proceed_status ();
init_wait_for_inferior ();
static BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
static int
-has_detach_ability ()
+has_detach_ability (void)
{
static HMODULE kernel32 = NULL;
return 0;
}
+/* Try to set or remove a user privilege to the current process. Return -1
+ if that fails, the previous setting of that privilege otherwise.
+
+ This code is copied from the Cygwin source code and rearranged to allow
+ dynamically loading of the needed symbols from advapi32 which is only
+ available on NT/2K/XP. */
+static int
+set_process_privilege (const char *privilege, BOOL enable)
+{
+ static HMODULE advapi32 = NULL;
+ static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
+ static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
+ static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
+ DWORD, PTOKEN_PRIVILEGES, PDWORD);
+
+ HANDLE token_hdl = NULL;
+ LUID restore_priv;
+ TOKEN_PRIVILEGES new_priv, orig_priv;
+ int ret = -1;
+ DWORD size;
+
+ if (GetVersion () >= 0x80000000) /* No security availbale on 9x/Me */
+ return 0;
+
+ if (!advapi32)
+ {
+ if (!(advapi32 = LoadLibrary ("advapi32.dll")))
+ goto out;
+ if (!OpenProcessToken)
+ OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken");
+ if (!LookupPrivilegeValue)
+ LookupPrivilegeValue = GetProcAddress (advapi32,
+ "LookupPrivilegeValueA");
+ if (!AdjustTokenPrivileges)
+ AdjustTokenPrivileges = GetProcAddress (advapi32,
+ "AdjustTokenPrivileges");
+ if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
+ {
+ advapi32 = NULL;
+ goto out;
+ }
+ }
+
+ if (!OpenProcessToken (GetCurrentProcess (),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+ &token_hdl))
+ goto out;
+
+ if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
+ goto out;
+
+ new_priv.PrivilegeCount = 1;
+ new_priv.Privileges[0].Luid = restore_priv;
+ new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
+
+ if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv,
+ sizeof orig_priv, &orig_priv, &size))
+ goto out;
+#if 0
+ /* Disabled, otherwise every `attach' in an unprivileged user session
+ would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
+ child_attach(). */
+ /* AdjustTokenPrivileges returns TRUE even if the privilege could not
+ be enabled. GetLastError () returns an correct error code, though. */
+ if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
+ goto out;
+#endif
+
+ ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
+
+out:
+ if (token_hdl)
+ CloseHandle (token_hdl);
+
+ return ret;
+}
+
/* Attach to process PID, then initialize for debugging it. */
static void
child_attach (char *args, int from_tty)
if (!args)
error_no_arg ("process-id to attach");
+ if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
+ {
+ printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n");
+ printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n");
+ }
+
pid = strtoul (args, 0, 0);
ok = DebugActiveProcess (pid);
+ saw_create = 0;
if (!ok)
error ("Can't attach to process.");
char *args;
char real_path[MAXPATHLEN];
char *toexec;
+ char shell[MAX_PATH + 1]; /* Path to shell */
+ const char *sh;
+ int tty;
+ int ostdin, ostdout, ostderr;
if (!exec_file)
error ("No executable specified, use `target exec'.\n");
memset (&si, 0, sizeof (si));
si.cb = sizeof (si);
- flags = 0;
-
- if (new_group)
- flags |= CREATE_NEW_PROCESS_GROUP;
-
- if (new_console)
- flags |= CREATE_NEW_CONSOLE;
-
- if (!useshell || !shell[0])
+ if (!useshell)
{
flags = DEBUG_ONLY_THIS_PROCESS;
cygwin_conv_to_win32_path (exec_file, real_path);
}
else
{
- char *newallargs = alloca (sizeof (" -c 'exec '") + strlen (exec_file) + strlen (allargs) + 2);
+ char *newallargs;
+ sh = getenv ("SHELL");
+ if (!sh)
+ sh = "/bin/sh";
+ cygwin_conv_to_win32_path (sh, shell);
+ newallargs = alloca (sizeof (" -c 'exec '") + strlen (exec_file)
+ + strlen (allargs) + 2);
sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
allargs = newallargs;
toexec = shell;
flags = DEBUG_PROCESS;
}
+ if (new_group)
+ flags |= CREATE_NEW_PROCESS_GROUP;
+
+ if (new_console)
+ flags |= CREATE_NEW_CONSOLE;
+
args = alloca (strlen (toexec) + strlen (allargs) + 2);
strcpy (args, toexec);
strcat (args, " ");
/* Prepare the environment vars for CreateProcess. */
{
- /* This code use to assume all env vars were file names and would
+ /* This code used to assume all env vars were file names and would
translate them all to win32 style. That obviously doesn't work in the
general case. The current rule is that we only translate PATH.
We need to handle PATH because we're about to call CreateProcess and
*temp = 0;
}
+ if (!inferior_io_terminal)
+ tty = ostdin = ostdout = ostderr = -1;
+ else
+ {
+ tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
+ if (tty < 0)
+ {
+ print_sys_errmsg (inferior_io_terminal, errno);
+ ostdin = ostdout = ostderr = -1;
+ }
+ else
+ {
+ ostdin = dup (0);
+ ostdout = dup (1);
+ ostderr = dup (2);
+ dup2 (tty, 0);
+ dup2 (tty, 1);
+ dup2 (tty, 2);
+ }
+ }
+
ret = CreateProcess (0,
args, /* command line */
NULL, /* Security */
NULL, /* current directory */
&si,
&pi);
+ if (tty >= 0)
+ {
+ close (tty);
+ dup2 (ostdin, 0);
+ dup2 (ostdout, 1);
+ dup2 (ostderr, 2);
+ close (ostdin);
+ close (ostdout);
+ close (ostderr);
+ }
+
if (!ret)
- error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
+ error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ());
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
child_ops.to_terminal_inferior = terminal_inferior;
child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
child_ops.to_terminal_ours = terminal_ours;
+ child_ops.to_terminal_save_ours = terminal_save_ours;
child_ops.to_terminal_info = child_terminal_info;
child_ops.to_kill = child_kill_inferior;
- child_ops.to_load = 0;
- child_ops.to_lookup_symbol = 0;
child_ops.to_create_inferior = child_create_inferior;
child_ops.to_mourn_inferior = child_mourn_inferior;
child_ops.to_can_run = child_can_run;
- child_ops.to_notice_signals = 0;
child_ops.to_thread_alive = win32_child_thread_alive;
child_ops.to_pid_to_str = cygwin_pid_to_str;
child_ops.to_stop = child_stop;
child_ops.to_stratum = process_stratum;
- child_ops.DONT_USE = 0;
child_ops.to_has_all_memory = 1;
child_ops.to_has_memory = 1;
child_ops.to_has_stack = 1;
child_ops.to_has_registers = 1;
child_ops.to_has_execution = 1;
- child_ops.to_sections = 0;
- child_ops.to_sections_end = 0;
child_ops.to_magic = OPS_MAGIC;
}
void
-_initialize_inftarg (void)
+_initialize_win32_nat (void)
{
struct cmd_list_element *c;
- const char *sh;
init_child_ops ();
c = add_com ("dll-symbols", class_files, dll_symbol_command,
"Load dll library symbols from FILE.");
- c->completer = filename_completer;
-
- sh = getenv ("SHELL");
- if (!sh)
- sh = "/bin/sh";
- if (access (sh, X_OK) != 0)
- {
- shell[0] = '\0';
- useshell = 0;
- }
- else
- {
- cygwin_conv_to_win32_path (sh, shell);
- useshell = 1;
- }
+ set_cmd_completer (c, filename_completer);
add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);