X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fwindows-nat.c;h=35ad8655342f579b3c2fb8373e9fc97f4200cd46;hb=9a325b7b3ff056647de536941eaba911d1d794ad;hp=76313db98914973135247bddc6314ef8464202bc;hpb=3de88e9afbf0d8d10a8c4ce1415c219120e0a0c1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 76313db989..35ad865534 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1,6 +1,6 @@ /* Target-vector operations for controlling windows child processes, for GDB. - Copyright (C) 1995-2017 Free Software Foundation, Inc. + Copyright (C) 1995-2018 Free Software Foundation, Inc. Contributed by Cygnus Solutions, A Red Hat Company. @@ -42,6 +42,7 @@ #include #include #endif +#include #include "buildsym.h" #include "filenames.h" @@ -66,6 +67,7 @@ #include "x86-nat.h" #include "complaints.h" #include "inf-child.h" +#include "gdb_tilde_expand.h" #define AdjustTokenPrivileges dyn_AdjustTokenPrivileges #define DebugActiveProcessStop dyn_DebugActiveProcessStop @@ -199,10 +201,6 @@ typedef enum #define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x #define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x -static void windows_interrupt (struct target_ops *self, ptid_t); -static int windows_thread_alive (struct target_ops *, ptid_t); -static void windows_kill_inferior (struct target_ops *); - static void cygwin_set_dr (int i, CORE_ADDR addr); static void cygwin_set_dr7 (unsigned long val); static CORE_ADDR cygwin_get_dr (int i); @@ -300,6 +298,58 @@ static const struct xlate_exception {STATUS_FLOAT_DIVIDE_BY_ZERO, GDB_SIGNAL_FPE}, {-1, GDB_SIGNAL_UNKNOWN}}; + +struct windows_nat_target final : public x86_nat_target +{ + void close () override; + + void attach (const char *, int) override; + + bool attach_no_wait () override + { return true; } + + void detach (inferior *, int) override; + + void resume (ptid_t, int , enum gdb_signal) override; + + ptid_t wait (ptid_t, struct target_waitstatus *, int) override; + + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; + + enum target_xfer_status xfer_partial (enum target_object object, + const char *annex, + gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) override; + + void files_info () override; + + void kill () override; + + void create_inferior (const char *, const std::string &, + char **, int) override; + + void mourn_inferior () override; + + bool thread_alive (ptid_t ptid) override; + + const char *pid_to_str (ptid_t) override; + + void interrupt () override; + + char *pid_to_exec_file (int pid) override; + + ptid_t get_ada_task_ptid (long lwp, long thread) override; + + bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override; + + const char *thread_name (struct thread_info *) override; +}; + +static windows_nat_target the_windows_nat_target; + /* Set the MAPPINGS static global to OFFSETS. See the description of MAPPINGS for more details. */ @@ -443,7 +493,7 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code) else if (print_thread_events && id != main_thread_id) printf_unfiltered (_("[%s exited with code %u]\n"), target_pid_to_str (ptid), (unsigned) exit_code); - delete_thread (ptid); + delete_thread (find_thread_ptid (ptid)); for (th = &thread_head; th->next != NULL && th->next->id != id; @@ -459,14 +509,59 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code) } } +/* Fetches register number R from the given windows_thread_info, + and supplies its value to the given regcache. + + This function assumes that R is non-negative. A failed assertion + is raised if that is not true. + + This function assumes that TH->RELOAD_CONTEXT is not set, meaning + that the windows_thread_info has an up-to-date context. A failed + assertion is raised if that assumption is violated. */ + static void -do_windows_fetch_inferior_registers (struct regcache *regcache, - windows_thread_info *th, int r) +windows_fetch_one_register (struct regcache *regcache, + windows_thread_info *th, int r) { + gdb_assert (r >= 0); + gdb_assert (!th->reload_context); + char *context_offset = ((char *) &th->context) + mappings[r]; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - long l; + + if (r == I387_FISEG_REGNUM (tdep)) + { + long l = *((long *) context_offset) & 0xffff; + regcache->raw_supply (r, (char *) &l); + } + else if (r == I387_FOP_REGNUM (tdep)) + { + long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); + regcache->raw_supply (r, (char *) &l); + } + else if (segment_register_p (r)) + { + /* GDB treats segment registers as 32bit registers, but they are + in fact only 16 bits long. Make sure we do not read extra + bits from our source buffer. */ + long l = *((long *) context_offset) & 0xffff; + regcache->raw_supply (r, (char *) &l); + } + else + regcache->raw_supply (r, context_offset); +} + +void +windows_nat_target::fetch_registers (struct regcache *regcache, int r) +{ + DWORD pid = ptid_get_tid (regcache->ptid ()); + windows_thread_info *th = thread_rec (pid, TRUE); + + /* Check if TH exists. Windows sometimes uses a non-existent + thread id in its events. */ + if (th == NULL) + return; if (th->reload_context) { @@ -502,73 +597,47 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, th->reload_context = 0; } - if (r == I387_FISEG_REGNUM (tdep)) - { - l = *((long *) context_offset) & 0xffff; - regcache_raw_supply (regcache, r, (char *) &l); - } - else if (r == I387_FOP_REGNUM (tdep)) - { - l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); - regcache_raw_supply (regcache, r, (char *) &l); - } - else if (segment_register_p (r)) - { - /* GDB treats segment registers as 32bit registers, but they are - in fact only 16 bits long. Make sure we do not read extra - bits from our source buffer. */ - l = *((long *) context_offset) & 0xffff; - regcache_raw_supply (regcache, r, (char *) &l); - } - else if (r >= 0) - regcache_raw_supply (regcache, r, context_offset); + if (r < 0) + for (r = 0; r < gdbarch_num_regs (regcache->arch()); r++) + windows_fetch_one_register (regcache, th, r); else - { - for (r = 0; r < gdbarch_num_regs (gdbarch); r++) - do_windows_fetch_inferior_registers (regcache, th, r); - } + windows_fetch_one_register (regcache, th, r); } -static void -windows_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int r) -{ - DWORD pid = ptid_get_tid (regcache_get_ptid (regcache)); - windows_thread_info *th = thread_rec (pid, TRUE); +/* Collect the register number R from the given regcache, and store + its value into the corresponding area of the given thread's context. - /* Check if TH exists. Windows sometimes uses a non-existent - thread id in its events. */ - if (th != NULL) - do_windows_fetch_inferior_registers (regcache, th, r); -} + This function assumes that R is non-negative. A failed assertion + assertion is raised if that is not true. */ static void -do_windows_store_inferior_registers (const struct regcache *regcache, - windows_thread_info *th, int r) +windows_store_one_register (const struct regcache *regcache, + windows_thread_info *th, int r) { - if (r >= 0) - regcache_raw_collect (regcache, r, - ((char *) &th->context) + mappings[r]); - else - { - for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++) - do_windows_store_inferior_registers (regcache, th, r); - } + gdb_assert (r >= 0); + + regcache->raw_collect (r, ((char *) &th->context) + mappings[r]); } /* Store a new register value into the context of the thread tied to REGCACHE. */ -static void -windows_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int r) + +void +windows_nat_target::store_registers (struct regcache *regcache, int r) { - DWORD pid = ptid_get_tid (regcache_get_ptid (regcache)); + DWORD pid = ptid_get_tid (regcache->ptid ()); windows_thread_info *th = thread_rec (pid, TRUE); /* Check if TH exists. Windows sometimes uses a non-existent thread id in its events. */ - if (th != NULL) - do_windows_store_inferior_registers (regcache, th, r); + if (th == NULL) + return; + + if (r < 0) + for (r = 0; r < gdbarch_num_regs (regcache->arch ()); r++) + windows_store_one_register (regcache, th, r); + else + windows_store_one_register (regcache, th, r); } /* Encapsulate the information required in a call to @@ -577,7 +646,7 @@ struct safe_symbol_file_add_args { char *name; int from_tty; - struct section_addr_info *addrs; + section_addr_info *addrs; int mainline; int flags; struct ui_file *err, *out; @@ -585,9 +654,9 @@ struct safe_symbol_file_add_args }; /* Maintain a linked list of "so" information. */ -struct lm_info +struct lm_info_windows : public lm_info_base { - LPVOID load_addr; + LPVOID load_addr = 0; }; static struct so_list solib_start, *solib_end; @@ -645,8 +714,9 @@ windows_make_so (const char *name, LPVOID load_addr) } #endif so = XCNEW (struct so_list); - so->lm_info = XNEW (struct lm_info); - so->lm_info->load_addr = load_addr; + lm_info_windows *li = new lm_info_windows; + so->lm_info = li; + li->load_addr = load_addr; strcpy (so->so_original_name, name); #ifndef __CYGWIN__ strcpy (so->so_name, buf); @@ -753,8 +823,8 @@ get_image_name (HANDLE h, void *address, int unicode) do_initial_windows_stuff and windows_add_all_dlls for more info on how we handle DLL loading during that phase). */ -static int -handle_load_dll (void *dummy) +static void +handle_load_dll () { LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; char *dll_name; @@ -767,22 +837,23 @@ handle_load_dll (void *dummy) dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode); if (!dll_name) - return 1; + return; solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll); solib_end = solib_end->next; - DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name, - host_address_to_string (solib_end->lm_info->load_addr))); + lm_info_windows *li = (lm_info_windows *) solib_end->lm_info; - return 1; + DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name, + host_address_to_string (li->load_addr))); } static void windows_free_so (struct so_list *so) { - if (so->lm_info) - xfree (so->lm_info); + lm_info_windows *li = (lm_info_windows *) so->lm_info; + + delete li; xfree (so); } @@ -794,25 +865,29 @@ windows_free_so (struct so_list *so) do_initial_windows_stuff and windows_add_all_dlls for more info on how we handle DLL loading during that phase). */ -static int -handle_unload_dll (void *dummy) +static void +handle_unload_dll () { LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; struct so_list *so; for (so = &solib_start; so->next != NULL; so = so->next) - if (so->next->lm_info->load_addr == lpBaseOfDll) - { - struct so_list *sodel = so->next; + { + lm_info_windows *li_next = (lm_info_windows *) so->next->lm_info; - so->next = sodel->next; - if (!so->next) - solib_end = so; - DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name)); + if (li_next->load_addr == lpBaseOfDll) + { + struct so_list *sodel = so->next; - windows_free_so (sodel); - return 1; - } + so->next = sodel->next; + if (!so->next) + solib_end = so; + DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name)); + + windows_free_so (sodel); + return; + } + } /* We did not find any DLL that was previously loaded at this address, so register a complaint. We do not report an error, because we have @@ -821,10 +896,25 @@ handle_unload_dll (void *dummy) 4 mysterious UNLOAD_DLL_DEBUG_EVENTs during the startup phase (these events are apparently caused by the WOW layer, the interface between 32bit and 64bit worlds). */ - complaint (&symfile_complaints, _("dll starting at %s not found."), + complaint (_("dll starting at %s not found."), host_address_to_string (lpBaseOfDll)); +} - return 0; +/* Call FUNC wrapped in a TRY/CATCH that swallows all GDB + exceptions. */ + +static void +catch_errors (void (*func) ()) +{ + TRY + { + func (); + } + CATCH (ex, RETURN_MASK_ALL) + { + exception_print (gdb_stderr, ex); + } + END_CATCH } /* Clear list of loaded DLLs. */ @@ -836,7 +926,7 @@ windows_clear_solib (void) } static void -signal_event_command (char *args, int from_tty) +signal_event_command (const char *args, int from_tty) { uintptr_t event_id = 0; char *endargs = NULL; @@ -860,25 +950,25 @@ signal_event_command (char *args, int from_tty) static int handle_output_debug_string (struct target_waitstatus *ourstatus) { - char *s = NULL; + gdb::unique_xmalloc_ptr s; int retval = 0; if (!target_read_string ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData, - &s, 1024, 0) - || !s || !*s) + &s, 1024, 0) + || !s || !*(s.get ())) /* nothing to do */; - else if (!startswith (s, _CYGWIN_SIGNAL_STRING)) + else if (!startswith (s.get (), _CYGWIN_SIGNAL_STRING)) { #ifdef __CYGWIN__ - if (!startswith (s, "cYg")) + if (!startswith (s.get (), "cYg")) #endif { - char *p = strchr (s, '\0'); + char *p = strchr (s.get (), '\0'); - if (p > s && *--p == '\n') + if (p > s.get () && *--p == '\n') *p = '\0'; - warning (("%s"), s); + warning (("%s"), s.get ()); } } #ifdef __CYGWIN__ @@ -892,7 +982,7 @@ handle_output_debug_string (struct target_waitstatus *ourstatus) to be stored at the given address in the inferior. Tell gdb to treat this like a real signal. */ char *p; - int sig = strtol (s + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0); + int sig = strtol (s.get () + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0); gdb_signal gotasig = gdb_signal_from_host (sig); ourstatus->value.sig = gotasig; @@ -915,8 +1005,6 @@ handle_output_debug_string (struct target_waitstatus *ourstatus) } #endif - if (s) - xfree (s); return retval; } @@ -997,7 +1085,7 @@ display_selector (HANDLE thread, DWORD sel) } static void -display_selectors (char * args, int from_tty) +display_selectors (const char * args, int from_tty) { if (!current_thread) { @@ -1170,24 +1258,23 @@ handle_exception (struct target_waitstatus *ourstatus) if (named_thread != NULL) { int thread_name_len; - char *thread_name; + gdb::unique_xmalloc_ptr thread_name; thread_name_len = target_read_string (thread_name_target, &thread_name, 1025, NULL); if (thread_name_len > 0) { - thread_name[thread_name_len - 1] = '\0'; + thread_name.get ()[thread_name_len - 1] = '\0'; xfree (named_thread->name); - named_thread->name = thread_name; + named_thread->name = thread_name.release (); } - else - xfree (thread_name); } ourstatus->value.sig = GDB_SIGNAL_TRAP; result = HANDLE_EXCEPTION_IGNORED; break; } - /* treat improperly formed exception as unknown, fallthrough */ + /* treat improperly formed exception as unknown */ + /* FALLTHROUGH */ default: /* Treat unhandled first chance exceptions specially. */ if (current_event.u.Exception.dwFirstChance) @@ -1291,9 +1378,8 @@ fake_create_process (void) return main_thread_id; } -static void -windows_resume (struct target_ops *ops, - ptid_t ptid, int step, enum gdb_signal sig) +void +windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig) { windows_thread_info *th; DWORD continue_status = DBG_CONTINUE; @@ -1353,9 +1439,8 @@ windows_resume (struct target_ops *ops, { /* Single step by setting t bit. */ struct regcache *regcache = get_current_regcache (); - struct gdbarch *gdbarch = get_regcache_arch (regcache); - windows_fetch_inferior_registers (ops, regcache, - gdbarch_ps_regnum (gdbarch)); + struct gdbarch *gdbarch = regcache->arch (); + fetch_registers (regcache, gdbarch_ps_regnum (gdbarch)); th->context.EFlags |= FLAG_TRACE_BIT; } @@ -1511,7 +1596,7 @@ get_windows_debug_event (struct target_ops *ops, "EXIT_PROCESS_DEBUG_EVENT")); if (!windows_initialization_done) { - target_terminal_ours (); + target_terminal::ours (); target_mourn_inferior (inferior_ptid); error (_("During startup program exited with code 0x%x."), (unsigned int) current_event.u.ExitProcess.dwExitCode); @@ -1532,7 +1617,7 @@ get_windows_debug_event (struct target_ops *ops, CloseHandle (current_event.u.LoadDll.hFile); if (saw_create != 1 || ! windows_initialization_done) break; - catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL); + catch_errors (handle_load_dll); ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->value.integer = 0; thread_id = main_thread_id; @@ -1545,7 +1630,7 @@ get_windows_debug_event (struct target_ops *ops, "UNLOAD_DLL_DEBUG_EVENT")); if (saw_create != 1 || ! windows_initialization_done) break; - catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL); + catch_errors (handle_unload_dll); ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->value.integer = 0; thread_id = main_thread_id; @@ -1612,13 +1697,13 @@ out: } /* Wait for interesting events to occur in the target process. */ -static ptid_t -windows_wait (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *ourstatus, int options) +ptid_t +windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, + int options) { int pid = -1; - target_terminal_ours (); + target_terminal::ours (); /* We loop when we get a non-standard exception rather than return with a SPURIOUS because resume can try and step or modify things, @@ -1657,7 +1742,7 @@ windows_wait (struct target_ops *ops, the user tries to resume the execution in the inferior. This is a classic race that we should try to fix one day. */ SetConsoleCtrlHandler (&ctrl_c_handler, TRUE); - retval = get_windows_debug_event (ops, pid, ourstatus); + retval = get_windows_debug_event (this, pid, ourstatus); SetConsoleCtrlHandler (&ctrl_c_handler, FALSE); if (retval) @@ -1670,7 +1755,7 @@ windows_wait (struct target_ops *ops, detach = deprecated_ui_loop_hook (0); if (detach) - windows_kill_inferior (ops); + kill (); } } } @@ -1763,8 +1848,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching) current thread until we report an event out of windows_wait. */ inferior_ptid = pid_to_ptid (pid); - target_terminal_init (); - target_terminal_inferior (); + target_terminal::init (); + target_terminal::inferior (); windows_initialization_done = 0; @@ -1772,7 +1857,7 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching) { struct target_waitstatus status; - windows_wait (ops, minus_one_ptid, &status, 0); + ops->wait (minus_one_ptid, &status, 0); /* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread events. */ @@ -1780,7 +1865,7 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching) && status.kind != TARGET_WAITKIND_SPURIOUS) break; - windows_resume (ops, minus_one_ptid, 0, GDB_SIGNAL_0); + ops->resume (minus_one_ptid, 0, GDB_SIGNAL_0); } /* Now that the inferior has been started and all DLLs have been mapped, @@ -1854,8 +1939,9 @@ out: } /* Attach to process PID, then initialize for debugging it. */ -static void -windows_attach (struct target_ops *ops, const char *args, int from_tty) + +void +windows_nat_target::attach (const char *args, int from_tty) { BOOL ok; DWORD pid; @@ -1903,17 +1989,17 @@ windows_attach (struct target_ops *ops, const char *args, int from_tty) gdb_flush (gdb_stdout); } - do_initial_windows_stuff (ops, pid, 1); - target_terminal_ours (); + do_initial_windows_stuff (this, pid, 1); + target_terminal::ours (); } -static void -windows_detach (struct target_ops *ops, const char *args, int from_tty) +void +windows_nat_target::detach (inferior *inf, int from_tty) { int detached = 1; - ptid_t ptid = {-1}; - windows_resume (ops, ptid, 0, GDB_SIGNAL_0); + ptid_t ptid = minus_one_ptid; + resume (ptid, 0, GDB_SIGNAL_0); if (!DebugActiveProcessStop (current_event.dwProcessId)) { @@ -1925,7 +2011,7 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty) if (detached && from_tty) { - char *exec_file = get_exec_file (0); + const char *exec_file = get_exec_file (0); if (exec_file == 0) exec_file = ""; printf_unfiltered ("Detaching from program: %s, Pid %u\n", exec_file, @@ -1935,9 +2021,9 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty) x86_cleanup_dregs (); inferior_ptid = null_ptid; - detach_inferior (current_event.dwProcessId); + detach_inferior (inf); - inf_child_maybe_unpush_target (ops); + maybe_unpush_target (); } /* Try to determine the executable filename. @@ -1994,8 +2080,8 @@ windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len) /* The pid_to_exec_file target_ops method for this platform. */ -static char * -windows_pid_to_exec_file (struct target_ops *self, int pid) +char * +windows_nat_target::pid_to_exec_file (int pid) { static char path[__PMAX]; #ifdef __CYGWIN__ @@ -2022,8 +2108,8 @@ windows_pid_to_exec_file (struct target_ops *self, int pid) /* Print status information about what we're accessing. */ -static void -windows_files_info (struct target_ops *ignore) +void +windows_nat_target::files_info () { struct inferior *inf = current_inferior (); @@ -2411,14 +2497,16 @@ redirect_inferior_handles (const char *cmd_orig, char *cmd, ALLARGS is a string containing the arguments to the program. ENV is the environment vector to pass. Errors reported with error(). */ -static void -windows_create_inferior (struct target_ops *ops, char *exec_file, - char *allargs, char **in_env, int from_tty) +void +windows_nat_target::create_inferior (const char *exec_file, + const std::string &origallargs, + char **in_env, int from_tty) { STARTUPINFO si; #ifdef __CYGWIN__ cygwin_buf_t real_path[__PMAX]; cygwin_buf_t shell[__PMAX]; /* Path to shell */ + cygwin_buf_t infcwd[__PMAX]; const char *sh; cygwin_buf_t *toexec; cygwin_buf_t *cygallargs; @@ -2431,7 +2519,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, #else /* !__CYGWIN__ */ char real_path[__PMAX]; char shell[__PMAX]; /* Path to shell */ - char *toexec; + const char *toexec; char *args, *allargs_copy; size_t args_len, allargs_len; int fd_inp = -1, fd_out = -1, fd_err = -1; @@ -2447,6 +2535,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, size_t envsize; char **env; #endif /* !__CYGWIN__ */ + const char *allargs = origallargs.c_str (); PROCESS_INFORMATION pi; BOOL ret; DWORD flags = 0; @@ -2455,6 +2544,17 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, if (!exec_file) error (_("No executable specified, use `target exec'.")); + const char *inferior_cwd = get_inferior_cwd (); + std::string expanded_infcwd; + if (inferior_cwd != NULL) + { + expanded_infcwd = gdb_tilde_expand (inferior_cwd); + /* Mirror slashes on inferior's cwd. */ + std::replace (expanded_infcwd.begin (), expanded_infcwd.end (), + '/', '\\'); + inferior_cwd = expanded_infcwd.c_str (); + } + memset (&si, 0, sizeof (si)); si.cb = sizeof (si); @@ -2504,6 +2604,11 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, flags |= DEBUG_PROCESS; } + if (inferior_cwd != NULL + && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd, + infcwd, strlen (inferior_cwd)) < 0) + error (_("Error converting inferior cwd: %d"), errno); + #ifdef __USEWIDE args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2) * sizeof (wchar_t)); @@ -2564,7 +2669,8 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, TRUE, /* inherit handles */ flags, /* start flags */ w32_env, /* environment */ - NULL, /* current directory */ + inferior_cwd != NULL ? infcwd : NULL, /* current + directory */ &si, &pi); if (w32_env) @@ -2687,7 +2793,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, TRUE, /* inherit handles */ flags, /* start flags */ w32env, /* environment */ - NULL, /* current directory */ + inferior_cwd, /* current directory */ &si, &pi); if (tty != INVALID_HANDLE_VALUE) @@ -2712,13 +2818,13 @@ windows_create_inferior (struct target_ops *ops, char *exec_file, else saw_create = 0; - do_initial_windows_stuff (ops, pi.dwProcessId, 0); + do_initial_windows_stuff (this, pi.dwProcessId, 0); /* windows_continue (DBG_CONTINUE, -1, 0); */ } -static void -windows_mourn_inferior (struct target_ops *ops) +void +windows_nat_target::mourn_inferior () { (void) windows_continue (DBG_CONTINUE, -1, 0); x86_cleanup_dregs(); @@ -2727,14 +2833,14 @@ windows_mourn_inferior (struct target_ops *ops) CHECK (CloseHandle (current_process_handle)); open_process_used = 0; } - inf_child_mourn_inferior (ops); + inf_child_target::mourn_inferior (); } /* Send a SIGINT to the process group. This acts just like the user typed a ^C on the controlling terminal. */ -static void -windows_interrupt (struct target_ops *self, ptid_t ptid) +void +windows_nat_target::interrupt () { DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n")); CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId)); @@ -2781,8 +2887,8 @@ windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf, return success ? TARGET_XFER_OK : TARGET_XFER_E_IO; } -static void -windows_kill_inferior (struct target_ops *ops) +void +windows_nat_target::kill () { CHECK (TerminateProcess (current_process_handle, 0)); @@ -2799,16 +2905,16 @@ windows_kill_inferior (struct target_ops *ops) target_mourn_inferior (inferior_ptid); /* Or just windows_mourn_inferior? */ } -static void -windows_close (struct target_ops *self) +void +windows_nat_target::close () { DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n", ptid_get_pid (inferior_ptid))); } /* Convert pid to printable format. */ -static char * -windows_pid_to_str (struct target_ops *ops, ptid_t ptid) +const char * +windows_nat_target::pid_to_str (ptid_t ptid) { static char buf[80]; @@ -2840,9 +2946,13 @@ windows_xfer_shared_libraries (struct target_ops *ops, obstack_init (&obstack); obstack_grow_str (&obstack, "\n"); for (so = solib_start.next; so; so = so->next) - windows_xfer_shared_library (so->so_name, (CORE_ADDR) - (uintptr_t) so->lm_info->load_addr, - target_gdbarch (), &obstack); + { + lm_info_windows *li = (lm_info_windows *) so->lm_info; + + windows_xfer_shared_library (so->so_name, (CORE_ADDR) + (uintptr_t) li->load_addr, + target_gdbarch (), &obstack); + } obstack_grow_str0 (&obstack, "\n"); buf = (const char *) obstack_finish (&obstack); @@ -2861,11 +2971,11 @@ windows_xfer_shared_libraries (struct target_ops *ops, return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF; } -static enum target_xfer_status -windows_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) +enum target_xfer_status +windows_nat_target::xfer_partial (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, + ULONGEST len, ULONGEST *xfered_len) { switch (object) { @@ -2873,90 +2983,59 @@ windows_xfer_partial (struct target_ops *ops, enum target_object object, return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len); case TARGET_OBJECT_LIBRARIES: - return windows_xfer_shared_libraries (ops, object, annex, readbuf, + return windows_xfer_shared_libraries (this, object, annex, readbuf, writebuf, offset, len, xfered_len); default: - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len, - xfered_len); + if (beneath () == NULL) + { + /* This can happen when requesting the transfer of unsupported + objects before a program has been started (and therefore + with the current_target having no target beneath). */ + return TARGET_XFER_E_IO; + } + return beneath ()->xfer_partial (object, annex, + readbuf, writebuf, offset, len, + xfered_len); } } /* Provide thread local base, i.e. Thread Information Block address. Returns 1 if ptid is found and sets *ADDR to thread_local_base. */ -static int -windows_get_tib_address (struct target_ops *self, - ptid_t ptid, CORE_ADDR *addr) +bool +windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr) { windows_thread_info *th; th = thread_rec (ptid_get_tid (ptid), 0); if (th == NULL) - return 0; + return false; if (addr != NULL) *addr = th->thread_local_base; - return 1; + return true; } -static ptid_t -windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) +ptid_t +windows_nat_target::get_ada_task_ptid (long lwp, long thread) { return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp); } /* Implementation of the to_thread_name method. */ -static const char * -windows_thread_name (struct target_ops *self, struct thread_info *thr) +const char * +windows_nat_target::thread_name (struct thread_info *thr) { return thread_rec (ptid_get_tid (thr->ptid), 0)->name; } -static struct target_ops * -windows_target (void) -{ - struct target_ops *t = inf_child_target (); - - t->to_close = windows_close; - t->to_attach = windows_attach; - t->to_attach_no_wait = 1; - t->to_detach = windows_detach; - t->to_resume = windows_resume; - t->to_wait = windows_wait; - t->to_fetch_registers = windows_fetch_inferior_registers; - t->to_store_registers = windows_store_inferior_registers; - t->to_xfer_partial = windows_xfer_partial; - t->to_files_info = windows_files_info; - t->to_kill = windows_kill_inferior; - t->to_create_inferior = windows_create_inferior; - t->to_mourn_inferior = windows_mourn_inferior; - t->to_thread_alive = windows_thread_alive; - t->to_pid_to_str = windows_pid_to_str; - t->to_interrupt = windows_interrupt; - t->to_pid_to_exec_file = windows_pid_to_exec_file; - t->to_get_ada_task_ptid = windows_get_ada_task_ptid; - t->to_get_tib_address = windows_get_tib_address; - t->to_thread_name = windows_thread_name; - - return t; -} - -/* -Wmissing-prototypes */ -extern initialize_file_ftype _initialize_windows_nat; void _initialize_windows_nat (void) { - struct target_ops *t; - - t = windows_target (); - - x86_use_watchpoints (t); - x86_dr_low.set_control = cygwin_set_dr7; x86_dr_low.set_addr = cygwin_set_dr; x86_dr_low.get_addr = cygwin_get_dr; @@ -2967,7 +3046,7 @@ _initialize_windows_nat (void) calling x86_set_debug_register_length function in processor windows specific native file. */ - add_target (t); + add_inf_child_target (&the_windows_nat_target); #ifdef __CYGWIN__ cygwin_internal (CW_SET_DOS_FILE_WARNING, 0); @@ -3104,21 +3183,18 @@ cygwin_get_dr7 (void) /* Determine if the thread referenced by "ptid" is alive by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0 it means that the thread has died. Otherwise it is assumed to be alive. */ -static int -windows_thread_alive (struct target_ops *ops, ptid_t ptid) + +bool +windows_nat_target::thread_alive (ptid_t ptid) { int tid; gdb_assert (ptid_get_tid (ptid) != 0); tid = ptid_get_tid (ptid); - return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 - ? FALSE : TRUE; + return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0; } -/* -Wmissing-prototypes */ -extern initialize_file_ftype _initialize_check_for_gdb_ini; - void _initialize_check_for_gdb_ini (void) { @@ -3213,9 +3289,6 @@ bad_GetConsoleFontSize (HANDLE w, DWORD nFont) return size; } -/* -Wmissing-prototypes */ -extern initialize_file_ftype _initialize_loadable; - /* Load any functions which may not be available in ancient versions of Windows. */