diff options
Diffstat (limited to 'gdb/gdbserver/server.c')
-rw-r--r-- | gdb/gdbserver/server.c | 240 |
1 files changed, 121 insertions, 119 deletions
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 69fcab1..3ab042d 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -36,6 +36,19 @@ #include "dll.h" #include "hostio.h" #include <vector> +#include "common-inferior.h" +#include "job-control.h" +#include "environ.h" + +/* The environment to pass to the inferior when creating it. */ + +struct gdb_environ *our_environ = NULL; + +/* Start the inferior using a shell. */ + +/* We always try to start the inferior using a shell. */ + +int startup_with_shell = 1; /* The thread set with an `Hc' packet. `Hc' is deprecated in favor of `vCont'. Note the multi-process extensions made `vCont' a @@ -79,8 +92,9 @@ static int vCont_supported; space randomization feature before starting an inferior. */ int disable_randomization = 1; -static std::vector<char *> program_argv; -static std::vector<char *> wrapper_argv; +static char *program_name = NULL; +static std::vector<char *> program_args; +static std::string wrapper_argv; int pass_signals[GDB_SIGNAL_LAST]; int program_signals[GDB_SIGNAL_LAST]; @@ -93,22 +107,6 @@ int program_signals_p; unsigned long signal_pid; -#ifdef SIGTTOU -/* A file descriptor for the controlling terminal. */ -int terminal_fd; - -/* TERMINAL_FD's original foreground group. */ -pid_t old_foreground_pgrp; - -/* Hand back terminal ownership to the original foreground group. */ - -static void -restore_old_foreground_pgrp (void) -{ - tcsetpgrp (terminal_fd, old_foreground_pgrp); -} -#endif - /* Set if you want to disable optional thread related packets support in gdbserver, for the sake of testing GDB against stubs that don't support them. */ @@ -118,8 +116,8 @@ int disable_packet_qC; int disable_packet_qfThreadInfo; /* Last status reported to GDB. */ -static struct target_waitstatus last_status; -static ptid_t last_ptid; +struct target_waitstatus last_status; +ptid_t last_ptid; char *own_buf; static unsigned char *mem_buf; @@ -238,94 +236,31 @@ target_running (void) return get_first_thread () != NULL; } -static int -start_inferior (char **argv) -{ - std::vector<char *> new_argv; - - if (!wrapper_argv.empty ()) - new_argv.insert (new_argv.begin (), - wrapper_argv.begin (), - wrapper_argv.end ()); - - for (int i = 0; argv[i] != NULL; ++i) - new_argv.push_back (argv[i]); - - new_argv.push_back (NULL); +/* See common/common-inferior.h. */ - if (debug_threads) - { - for (int i = 0; i < new_argv.size (); ++i) - debug_printf ("new_argv[%d] = \"%s\"\n", i, new_argv[i]); - debug_flush (); - } - -#ifdef SIGTTOU - signal (SIGTTOU, SIG_DFL); - signal (SIGTTIN, SIG_DFL); -#endif - - signal_pid = create_inferior (new_argv[0], &new_argv[0]); - - /* FIXME: we don't actually know at this point that the create - actually succeeded. We won't know that until we wait. */ - fprintf (stderr, "Process %s created; pid = %ld\n", argv[0], - signal_pid); - fflush (stderr); - -#ifdef SIGTTOU - signal (SIGTTOU, SIG_IGN); - signal (SIGTTIN, SIG_IGN); - terminal_fd = fileno (stderr); - old_foreground_pgrp = tcgetpgrp (terminal_fd); - tcsetpgrp (terminal_fd, signal_pid); - atexit (restore_old_foreground_pgrp); -#endif - - if (!wrapper_argv.empty ()) - { - ptid_t ptid = pid_to_ptid (signal_pid); - - last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); - - if (last_status.kind == TARGET_WAITKIND_STOPPED) - { - do - { - target_continue_no_signal (ptid); +const char * +get_exec_wrapper () +{ + return !wrapper_argv.empty () ? wrapper_argv.c_str () : NULL; +} - last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); - if (last_status.kind != TARGET_WAITKIND_STOPPED) - break; +/* See common/common-inferior.h. */ - current_thread->last_resume_kind = resume_stop; - current_thread->last_status = last_status; - } - while (last_status.value.sig != GDB_SIGNAL_TRAP); - } - target_post_create_inferior (); - return signal_pid; - } +char * +get_exec_file (int err) +{ + if (err && program_name == NULL) + error (_("No executable file specified.")); - /* Wait till we are at 1st instruction in program, return new pid - (assuming success). */ - last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); + return program_name; +} - /* At this point, the target process, if it exits, is stopped. Do not call - the function target_post_create_inferior if the process has already - exited, as the target implementation of the routine may rely on the - process being live. */ - if (last_status.kind != TARGET_WAITKIND_EXITED - && last_status.kind != TARGET_WAITKIND_SIGNALLED) - { - target_post_create_inferior (); - current_thread->last_resume_kind = resume_stop; - current_thread->last_status = last_status; - } - else - target_mourn_inferior (last_ptid); +/* See server.h. */ - return signal_pid; +struct gdb_environ * +get_environ () +{ + return our_environ; } static int @@ -2848,6 +2783,7 @@ handle_v_run (char *own_buf) { char *p, *next_p; std::vector<char *> new_argv; + char *new_program_name = NULL; int i, new_argc; new_argc = 0; @@ -2866,42 +2802,94 @@ handle_v_run (char *own_buf) if (i == 0 && p == next_p) { /* No program specified. */ - new_argv.push_back (NULL); + new_program_name = NULL; + } + else if (p == next_p) + { + /* Empty argument. */ + new_argv.push_back (xstrdup ("''")); } else { size_t len = (next_p - p) / 2; + /* ARG is the unquoted argument received via the RSP. */ char *arg = (char *) xmalloc (len + 1); + /* FULL_ARGS will contain the quoted version of ARG. */ + char *full_arg = (char *) xmalloc ((len + 1) * 2); + /* These are pointers used to navigate the strings above. */ + char *tmp_arg = arg; + char *tmp_full_arg = full_arg; + int need_quote = 0; hex2bin (p, (gdb_byte *) arg, len); arg[len] = '\0'; - new_argv.push_back (arg); - } + while (*tmp_arg != '\0') + { + switch (*tmp_arg) + { + case '\n': + /* Quote \n. */ + *tmp_full_arg = '\''; + ++tmp_full_arg; + need_quote = 1; + break; + + case '\'': + /* Quote single quote. */ + *tmp_full_arg = '\\'; + ++tmp_full_arg; + break; + + default: + break; + } + + *tmp_full_arg = *tmp_arg; + ++tmp_full_arg; + ++tmp_arg; + } + + if (need_quote) + *tmp_full_arg++ = '\''; + + /* Finish FULL_ARG and push it into the vector containing + the argv. */ + *tmp_full_arg = '\0'; + if (i == 0) + new_program_name = full_arg; + else + new_argv.push_back (full_arg); + xfree (arg); + } if (*next_p) next_p++; } new_argv.push_back (NULL); - if (new_argv[0] == NULL) + if (new_program_name == NULL) { /* GDB didn't specify a program to run. Use the program from the last run with the new argument list. */ - if (program_argv.empty ()) + if (program_name == NULL) { write_enn (own_buf); free_vector_argv (new_argv); return 0; } - - new_argv.push_back (xstrdup (program_argv[0])); + } + else + { + xfree (program_name); + program_name = new_program_name; } /* Free the old argv and install the new one. */ - free_vector_argv (program_argv); - program_argv = new_argv; + free_vector_argv (program_args); + program_args = new_argv; + + create_inferior (program_name, program_args); - start_inferior (&program_argv[0]); if (last_status.kind == TARGET_WAITKIND_STOPPED) { prepare_resume_reply (own_buf, last_ptid, &last_status); @@ -3527,10 +3515,17 @@ captured_main (int argc, char *argv[]) tmp = next_arg; while (*next_arg != NULL && strcmp (*next_arg, "--") != 0) { - wrapper_argv.push_back (*next_arg); + wrapper_argv += *next_arg; + wrapper_argv += ' '; next_arg++; } + if (!wrapper_argv.empty ()) + { + /* Erase the last whitespace. */ + wrapper_argv.erase (wrapper_argv.end () - 1); + } + if (next_arg == tmp || *next_arg == NULL) { gdbserver_usage (stderr); @@ -3666,8 +3661,13 @@ captured_main (int argc, char *argv[]) exit (1); } + /* Gather information about the environment. */ + our_environ = make_environ (); + init_environ (our_environ); + initialize_async_io (); initialize_low (); + have_job_control (); initialize_event_loop (); if (target_supports_tracepoints ()) initialize_tracepoint (); @@ -3681,12 +3681,13 @@ captured_main (int argc, char *argv[]) int i, n; n = argc - (next_arg - argv); - for (i = 0; i < n; i++) - program_argv.push_back (xstrdup (next_arg[i])); - program_argv.push_back (NULL); + program_name = xstrdup (next_arg[0]); + for (i = 1; i < n; i++) + program_args.push_back (xstrdup (next_arg[i])); + program_args.push_back (NULL); /* Wait till we are at first instruction in program. */ - start_inferior (&program_argv[0]); + create_inferior (program_name, program_args); /* We are now (hopefully) stopped at the first instruction of the target process. This assumes that the target process was @@ -4301,9 +4302,10 @@ process_serial_event (void) fprintf (stderr, "GDBserver restarting\n"); /* Wait till we are at 1st instruction in prog. */ - if (!program_argv.empty ()) + if (program_name != NULL) { - start_inferior (&program_argv[0]); + create_inferior (program_name, program_args); + if (last_status.kind == TARGET_WAITKIND_STOPPED) { /* Stopped at the first instruction of the target |