#include "common-inferior.h"
#include "job-control.h"
#include "environ.h"
+#include "filenames.h"
+#include "pathstuff.h"
#include "common/selftest.h"
break; \
}
+/* String containing the current directory (what getwd would return). */
+
+char *current_directory;
+
/* The environment to pass to the inferior when creating it. */
static gdb_environ our_environ;
space randomization feature before starting an inferior. */
int disable_randomization = 1;
-static char *program_name = NULL;
+static struct {
+ /* Set the PROGRAM_PATH. Here we adjust the path of the provided
+ binary if needed. */
+ void set (gdb::unique_xmalloc_ptr<char> &&path)
+ {
+ m_path = std::move (path);
+
+ /* Make sure we're using the absolute path of the inferior when
+ creating it. */
+ if (!contains_dir_separator (m_path.get ()))
+ {
+ int reg_file_errno;
+
+ /* Check if the file is in our CWD. If it is, then we prefix
+ its name with CURRENT_DIRECTORY. Otherwise, we leave the
+ name as-is because we'll try searching for it in $PATH. */
+ if (is_regular_file (m_path.get (), ®_file_errno))
+ m_path = gdb_abspath (m_path.get ());
+ }
+ }
+
+ /* Return the PROGRAM_PATH. */
+ char *get ()
+ { return m_path.get (); }
+
+private:
+ /* The program name, adjusted if needed. */
+ gdb::unique_xmalloc_ptr<char> m_path;
+} program_path;
static std::vector<char *> program_args;
static std::string wrapper_argv;
char *
get_exec_file (int err)
{
- if (err && program_name == NULL)
+ if (err && program_path.get () == NULL)
error (_("No executable file specified."));
- return program_name;
+ return program_path.get ();
}
/* See server.h. */
req = TRIBOOL_TRUE;
else
{
- char *mode_copy = xstrdup (mode);
-
/* We don't know what this mode is, so complain to GDB. */
sprintf (own_buf, "E.Unknown thread-events mode requested: %s\n",
- mode_copy);
- xfree (mode_copy);
+ mode);
return;
}
if (strcmp (annex, "target.xml") == 0)
{
- const char *ret = tdesc_get_features_xml ((target_desc*) desc);
+ const char *ret = tdesc_get_features_xml (desc);
if (*ret == '@')
return ret + 1;
ARG is the text after "--debug-format=" or "monitor set debug-format".
IS_MONITOR is non-zero if we're invoked via "monitor set debug-format".
This triggers calls to monitor_output.
- The result is NULL if all options were parsed ok, otherwise an error
- message which the caller must free.
+ The result is an empty string if all options were parsed ok, otherwise an
+ error message which the caller must free.
N.B. These commands affect all debug format settings, they are not
cumulative. If a format is not specified, it is turned off.
static std::string
parse_debug_format_options (const char *arg, int is_monitor)
{
- VEC (char_ptr) *options;
- int ix;
- char *option;
-
/* First turn all debug format options off. */
debug_timestamp = 0;
while (isspace (*arg))
++arg;
- options = delim_string_to_char_ptr_vec (arg, ',');
+ std::vector<gdb::unique_xmalloc_ptr<char>> options
+ = delim_string_to_char_ptr_vec (arg, ',');
- for (ix = 0; VEC_iterate (char_ptr, options, ix, option); ++ix)
+ for (const gdb::unique_xmalloc_ptr<char> &option : options)
{
- if (strcmp (option, "all") == 0)
+ if (strcmp (option.get (), "all") == 0)
{
debug_timestamp = 1;
if (is_monitor)
monitor_output ("All extra debug format options enabled.\n");
}
- else if (strcmp (option, "none") == 0)
+ else if (strcmp (option.get (), "none") == 0)
{
debug_timestamp = 0;
if (is_monitor)
monitor_output ("All extra debug format options disabled.\n");
}
- else if (strcmp (option, "timestamp") == 0)
+ else if (strcmp (option.get (), "timestamp") == 0)
{
debug_timestamp = 1;
if (is_monitor)
continue;
}
else
- {
- std::string msg
- = string_printf ("Unknown debug-format argument: \"%s\"\n", option);
-
- free_char_ptr_vec (options);
- return msg;
- }
+ return string_printf ("Unknown debug-format argument: \"%s\"\n",
+ option.get ());
}
- free_char_ptr_vec (options);
return std::string ();
}
enum btrace_read_type type;
int result;
- if (the_target->read_btrace == NULL || writebuf != NULL)
+ if (writebuf != NULL)
return -2;
if (ptid_equal (general_thread, null_ptid)
{
buffer_free (&cache);
- result = target_read_btrace (thread->btrace, &cache, type);
- if (result != 0)
+ TRY
+ {
+ result = target_read_btrace (thread->btrace, &cache, type);
+ if (result != 0)
+ memcpy (own_buf, cache.buffer, cache.used_size);
+ }
+ CATCH (exception, RETURN_MASK_ERROR)
{
- memcpy (own_buf, cache.buffer, cache.used_size);
- return -3;
+ sprintf (own_buf, "E.%s", exception.message);
+ result = -1;
}
+ END_CATCH
+
+ if (result != 0)
+ return -3;
}
else if (offset > cache.used_size)
{
struct thread_info *thread;
int result;
- if (the_target->read_btrace_conf == NULL || writebuf != NULL)
+ if (writebuf != NULL)
return -2;
if (annex[0] != '\0')
{
buffer_free (&cache);
- result = target_read_btrace_conf (thread->btrace, &cache);
- if (result != 0)
+ TRY
+ {
+ result = target_read_btrace_conf (thread->btrace, &cache);
+ if (result != 0)
+ memcpy (own_buf, cache.buffer, cache.used_size);
+ }
+ CATCH (exception, RETURN_MASK_ERROR)
{
- memcpy (own_buf, cache.buffer, cache.used_size);
- return -3;
+ sprintf (own_buf, "E.%s", exception.message);
+ result = -1;
}
+ END_CATCH
+
+ if (result != 0)
+ return -3;
}
else if (offset > cache.used_size)
{
static void
supported_btrace_packets (char *buf)
{
- int btrace_supported = 0;
-
- if (target_supports_btrace (BTRACE_FORMAT_BTS))
- {
- strcat (buf, ";Qbtrace:bts+");
- strcat (buf, ";Qbtrace-conf:bts:size+");
-
- btrace_supported = 1;
- }
-
- if (target_supports_btrace (BTRACE_FORMAT_PT))
- {
- strcat (buf, ";Qbtrace:pt+");
- strcat (buf, ";Qbtrace-conf:pt:size+");
-
- btrace_supported = 1;
- }
-
- if (!btrace_supported)
- return;
-
+ strcat (buf, ";Qbtrace:bts+");
+ strcat (buf, ";Qbtrace-conf:bts:size+");
+ strcat (buf, ";Qbtrace:pt+");
+ strcat (buf, ";Qbtrace-conf:pt:size+");
strcat (buf, ";Qbtrace:off+");
strcat (buf, ";qXfer:btrace:read+");
strcat (buf, ";qXfer:btrace-conf:read+");
{
/* GDB didn't specify a program to run. Use the program from the
last run with the new argument list. */
- if (program_name == NULL)
+ if (program_path.get () == NULL)
{
write_enn (own_buf);
free_vector_argv (new_argv);
}
}
else
- {
- xfree (program_name);
- program_name = new_program_name;
- }
+ program_path.set (gdb::unique_xmalloc_ptr<char> (new_program_name));
/* Free the old argv and install the new one. */
free_vector_argv (program_args);
program_args = new_argv;
- create_inferior (program_name, program_args);
+ create_inferior (program_path.get (), program_args);
if (last_status.kind == TARGET_WAITKIND_STOPPED)
{
const char *selftest_filter = NULL;
#endif
+ current_directory = getcwd (NULL, 0);
+ if (current_directory == NULL)
+ {
+ error (_("Could not find current working directory: %s"),
+ safe_strerror (errno));
+ }
+
while (*next_arg != NULL && **next_arg == '-')
{
if (strcmp (*next_arg, "--version") == 0)
int i, n;
n = argc - (next_arg - argv);
- program_name = xstrdup (next_arg[0]);
+ program_path.set (gdb::unique_xmalloc_ptr<char> (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. */
- create_inferior (program_name, program_args);
+ create_inferior (program_path.get (), program_args);
/* We are now (hopefully) stopped at the first instruction of
the target process. This assumes that the target process was
fprintf (stderr, "GDBserver restarting\n");
/* Wait till we are at 1st instruction in prog. */
- if (program_name != NULL)
+ if (program_path.get () != NULL)
{
- create_inferior (program_name, program_args);
+ create_inferior (program_path.get (), program_args);
if (last_status.kind == TARGET_WAITKIND_STOPPED)
{