PR 20569, segv in follow_exec
The following testcases make GDB crash whenever an invalid sysroot is provided, when GDB is unable to find a valid path to the symbol file: gdb.base/catch-syscall.exp gdb.base/execl-update-breakpoints.exp gdb.base/foll-exec-mode.exp gdb.base/foll-exec.exp gdb.base/foll-vfork.exp gdb.base/pie-execl.exp gdb.multi/bkpt-multi-exec.exp gdb.python/py-finish-breakpoint.exp gdb.threads/execl.exp gdb.threads/non-ldr-exc-1.exp gdb.threads/non-ldr-exc-2.exp gdb.threads/non-ldr-exc-3.exp gdb.threads/non-ldr-exc-4.exp gdb.threads/thread-execl.exp The immediate cause of the segv is that follow_exec is passing a NULL argument (the result of exec_file_find) to strlen. However, the problem is deeper than that: follow_exec simply isn't prepared for the case where sysroot translation fails to locate the new executable. Actually all callers of exec_file_find have bugs due to confusion between host and target pathnames. This commit attempts to fix all that. In terms of the testcases that were formerly segv'ing, GDB now prints a warning but continues execution of the new program, so that the tests now mostly FAIL instead. You could argue the FAILs are due to a legitimate problem with the test environment setting up the sysroot translation incorrectly. A new representative test is added which exercises the ne wwarning code path even with native testing. Tested on x86_64 Fedora 23, native and gdbserver. gdb/ChangeLog: 2016-10-25 Sandra Loosemore <sandra@codesourcery.com> Luis Machado <lgustavo@codesourcery.com> Pedro Alves <palves@redhat.com> PR gdb/20569 * exceptions.c (exception_print_same): Moved here from exec.c. * exceptions.h (exception_print_same): Declare. * exec.h: Include "symfile-add-flags.h". (try_open_exec_file): New declaration. * exec.c (exception_print_same): Moved to exceptions.c. (try_open_exec_file): New function. (exec_file_locate_attach): Rename exec_file and full_exec_path variables to avoid confusion between target and host pathnames. Move pathname processing logic to exec_file_find. Do not return early if pathname lookup fails; Call try_open_exec_file. * infrun.c (follow_exec): Split and rename execd_pathname variable to avoid confusion between target and host pathnames. Warn if pathname lookup fails. Pass target pathname to target_follow_exec, not hostpathname. Call try_open_exec_file. * main.c (symbol_file_add_main_adapter): New function. (captured_main_1): Use it. * solib-svr4.c (open_symbol_file_object): Adjust to pass symfile_add_flags to symbol_file_add_main. * solib.c (exec_file_find): Incorporate fallback logic for relative pathnames formerly in exec_file_locate_attach. * symfile.c (symbol_file_add_main, symbol_file_add_main_1): Replace 'from_tty' parameter with a symfile_add_file. (symbol_file_command): Adjust to pass symfile_add_flags to symbol_file_add_main. * symfile.h (symbol_file_add_main): Replace 'from_tty' parameter with a symfile_add_file. gdb/testsuite/ChangeLog: 2016-10-25 Luis Machado <lgustavo@codesourcery.com> * gdb.base/exec-invalid-sysroot.exp: New file.
This commit is contained in:
parent
b15cc25cbe
commit
ecf45d2cc7
14 changed files with 277 additions and 121 deletions
|
@ -1,3 +1,35 @@
|
||||||
|
2016-10-25 Sandra Loosemore <sandra@codesourcery.com>
|
||||||
|
Luis Machado <lgustavo@codesourcery.com>
|
||||||
|
Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
PR gdb/20569
|
||||||
|
* exceptions.c (exception_print_same): Moved here from exec.c.
|
||||||
|
* exceptions.h (exception_print_same): Declare.
|
||||||
|
* exec.h: Include "symfile-add-flags.h".
|
||||||
|
(try_open_exec_file): New declaration.
|
||||||
|
* exec.c (exception_print_same): Moved to exceptions.c.
|
||||||
|
(try_open_exec_file): New function.
|
||||||
|
(exec_file_locate_attach): Rename exec_file and full_exec_path
|
||||||
|
variables to avoid confusion between target and host pathnames.
|
||||||
|
Move pathname processing logic to exec_file_find. Do not return
|
||||||
|
early if pathname lookup fails; Call try_open_exec_file.
|
||||||
|
* infrun.c (follow_exec): Split and rename execd_pathname variable
|
||||||
|
to avoid confusion between target and host pathnames. Warn if
|
||||||
|
pathname lookup fails. Pass target pathname to
|
||||||
|
target_follow_exec, not hostpathname. Call try_open_exec_file.
|
||||||
|
* main.c (symbol_file_add_main_adapter): New function.
|
||||||
|
(captured_main_1): Use it.
|
||||||
|
* solib-svr4.c (open_symbol_file_object): Adjust to pass
|
||||||
|
symfile_add_flags to symbol_file_add_main.
|
||||||
|
* solib.c (exec_file_find): Incorporate fallback logic for relative
|
||||||
|
pathnames formerly in exec_file_locate_attach.
|
||||||
|
* symfile.c (symbol_file_add_main, symbol_file_add_main_1):
|
||||||
|
Replace 'from_tty' parameter with a symfile_add_file.
|
||||||
|
(symbol_file_command): Adjust to pass symfile_add_flags to
|
||||||
|
symbol_file_add_main.
|
||||||
|
* symfile.h (symbol_file_add_main): Replace 'from_tty' parameter
|
||||||
|
with a symfile_add_file.
|
||||||
|
|
||||||
2016-10-26 Pedro Alves <palves@redhat.com>
|
2016-10-26 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* coffread.c (coff_symfile_read): Use symfile_add_flags.
|
* coffread.c (coff_symfile_read): Use symfile_add_flags.
|
||||||
|
|
|
@ -256,3 +256,21 @@ catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
|
||||||
return 0;
|
return 0;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See exceptions.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
exception_print_same (struct gdb_exception e1, struct gdb_exception e2)
|
||||||
|
{
|
||||||
|
const char *msg1 = e1.message;
|
||||||
|
const char *msg2 = e2.message;
|
||||||
|
|
||||||
|
if (msg1 == NULL)
|
||||||
|
msg1 = "";
|
||||||
|
if (msg2 == NULL)
|
||||||
|
msg2 = "";
|
||||||
|
|
||||||
|
return (e1.reason == e2.reason
|
||||||
|
&& e1.error == e2.error
|
||||||
|
&& strcmp (msg1, msg2) == 0);
|
||||||
|
}
|
||||||
|
|
|
@ -88,4 +88,7 @@ extern int catch_exceptions_with_msg (struct ui_out *uiout,
|
||||||
typedef int (catch_errors_ftype) (void *);
|
typedef int (catch_errors_ftype) (void *);
|
||||||
extern int catch_errors (catch_errors_ftype *, void *, char *, return_mask);
|
extern int catch_errors (catch_errors_ftype *, void *, char *, return_mask);
|
||||||
|
|
||||||
|
/* Compare two exception objects for print equality. */
|
||||||
|
extern int exception_print_same (struct gdb_exception e1,
|
||||||
|
struct gdb_exception e2);
|
||||||
#endif
|
#endif
|
||||||
|
|
129
gdb/exec.c
129
gdb/exec.c
|
@ -136,73 +136,16 @@ exec_file_clear (int from_tty)
|
||||||
printf_unfiltered (_("No executable file now.\n"));
|
printf_unfiltered (_("No executable file now.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns non-zero if exceptions E1 and E2 are equal. Returns zero
|
/* See exec.h. */
|
||||||
otherwise. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
exception_print_same (struct gdb_exception e1, struct gdb_exception e2)
|
|
||||||
{
|
|
||||||
const char *msg1 = e1.message;
|
|
||||||
const char *msg2 = e2.message;
|
|
||||||
|
|
||||||
if (msg1 == NULL)
|
|
||||||
msg1 = "";
|
|
||||||
if (msg2 == NULL)
|
|
||||||
msg2 = "";
|
|
||||||
|
|
||||||
return (e1.reason == e2.reason
|
|
||||||
&& e1.error == e2.error
|
|
||||||
&& strcmp (msg1, msg2) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See gdbcore.h. */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
|
try_open_exec_file (const char *exec_file_host, struct inferior *inf,
|
||||||
|
symfile_add_flags add_flags)
|
||||||
{
|
{
|
||||||
char *exec_file, *full_exec_path = NULL;
|
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
struct gdb_exception prev_err = exception_none;
|
struct gdb_exception prev_err = exception_none;
|
||||||
|
|
||||||
/* Do nothing if we already have an executable filename. */
|
old_chain = make_cleanup (free_current_contents, &prev_err.message);
|
||||||
exec_file = (char *) get_exec_file (0);
|
|
||||||
if (exec_file != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Try to determine a filename from the process itself. */
|
|
||||||
exec_file = target_pid_to_exec_file (pid);
|
|
||||||
if (exec_file == NULL)
|
|
||||||
{
|
|
||||||
warning (_("No executable has been specified and target does not "
|
|
||||||
"support\n"
|
|
||||||
"determining executable automatically. "
|
|
||||||
"Try using the \"file\" command."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If gdb_sysroot is not empty and the discovered filename
|
|
||||||
is absolute then prefix the filename with gdb_sysroot. */
|
|
||||||
if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file))
|
|
||||||
{
|
|
||||||
full_exec_path = exec_file_find (exec_file, NULL);
|
|
||||||
if (full_exec_path == NULL)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* It's possible we don't have a full path, but rather just a
|
|
||||||
filename. Some targets, such as HP-UX, don't provide the
|
|
||||||
full path, sigh.
|
|
||||||
|
|
||||||
Attempt to qualify the filename against the source path.
|
|
||||||
(If that fails, we'll just fall back on the original
|
|
||||||
filename. Not much more we can do...) */
|
|
||||||
if (!source_full_path_of (exec_file, &full_exec_path))
|
|
||||||
full_exec_path = xstrdup (exec_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_chain = make_cleanup (xfree, full_exec_path);
|
|
||||||
make_cleanup (free_current_contents, &prev_err.message);
|
|
||||||
|
|
||||||
/* exec_file_attach and symbol_file_add_main may throw an error if the file
|
/* exec_file_attach and symbol_file_add_main may throw an error if the file
|
||||||
cannot be opened either locally or remotely.
|
cannot be opened either locally or remotely.
|
||||||
|
@ -217,7 +160,9 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
|
||||||
errors/exceptions in the following code. */
|
errors/exceptions in the following code. */
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
exec_file_attach (full_exec_path, from_tty);
|
/* We must do this step even if exec_file_host is NULL, so that
|
||||||
|
exec_file_attach will clear state. */
|
||||||
|
exec_file_attach (exec_file_host, add_flags & SYMFILE_VERBOSE);
|
||||||
}
|
}
|
||||||
CATCH (err, RETURN_MASK_ERROR)
|
CATCH (err, RETURN_MASK_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -232,23 +177,61 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
|
||||||
}
|
}
|
||||||
END_CATCH
|
END_CATCH
|
||||||
|
|
||||||
TRY
|
if (exec_file_host != NULL)
|
||||||
{
|
{
|
||||||
if (defer_bp_reset)
|
TRY
|
||||||
current_inferior ()->symfile_flags |= SYMFILE_DEFER_BP_RESET;
|
{
|
||||||
symbol_file_add_main (full_exec_path, from_tty);
|
symbol_file_add_main (exec_file_host, add_flags);
|
||||||
|
}
|
||||||
|
CATCH (err, RETURN_MASK_ERROR)
|
||||||
|
{
|
||||||
|
if (!exception_print_same (prev_err, err))
|
||||||
|
warning ("%s", err.message);
|
||||||
|
}
|
||||||
|
END_CATCH
|
||||||
}
|
}
|
||||||
CATCH (err, RETURN_MASK_ERROR)
|
|
||||||
{
|
|
||||||
if (!exception_print_same (prev_err, err))
|
|
||||||
warning ("%s", err.message);
|
|
||||||
}
|
|
||||||
END_CATCH
|
|
||||||
current_inferior ()->symfile_flags &= ~SYMFILE_DEFER_BP_RESET;
|
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See gdbcore.h. */
|
||||||
|
|
||||||
|
void
|
||||||
|
exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
|
||||||
|
{
|
||||||
|
char *exec_file_target, *exec_file_host;
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
symfile_add_flags add_flags = 0;
|
||||||
|
|
||||||
|
/* Do nothing if we already have an executable filename. */
|
||||||
|
if (get_exec_file (0) != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Try to determine a filename from the process itself. */
|
||||||
|
exec_file_target = target_pid_to_exec_file (pid);
|
||||||
|
if (exec_file_target == NULL)
|
||||||
|
{
|
||||||
|
warning (_("No executable has been specified and target does not "
|
||||||
|
"support\n"
|
||||||
|
"determining executable automatically. "
|
||||||
|
"Try using the \"file\" command."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_file_host = exec_file_find (exec_file_target, NULL);
|
||||||
|
old_chain = make_cleanup (xfree, exec_file_host);
|
||||||
|
|
||||||
|
if (defer_bp_reset)
|
||||||
|
add_flags |= SYMFILE_DEFER_BP_RESET;
|
||||||
|
|
||||||
|
if (from_tty)
|
||||||
|
add_flags |= SYMFILE_VERBOSE;
|
||||||
|
|
||||||
|
/* Attempt to open the exec file. */
|
||||||
|
try_open_exec_file (exec_file_host, current_inferior (), add_flags);
|
||||||
|
do_cleanups (old_chain);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set FILENAME as the new exec file.
|
/* Set FILENAME as the new exec file.
|
||||||
|
|
||||||
This function is intended to be behave essentially the same
|
This function is intended to be behave essentially the same
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "progspace.h"
|
#include "progspace.h"
|
||||||
#include "memrange.h"
|
#include "memrange.h"
|
||||||
|
#include "symfile-add-flags.h"
|
||||||
|
|
||||||
struct target_section;
|
struct target_section;
|
||||||
struct target_ops;
|
struct target_ops;
|
||||||
|
@ -113,4 +114,11 @@ extern void print_section_info (struct target_section_table *table,
|
||||||
|
|
||||||
extern void exec_close (void);
|
extern void exec_close (void);
|
||||||
|
|
||||||
|
/* Helper function that attempts to open the symbol file at EXEC_FILE_HOST.
|
||||||
|
If successful, it proceeds to add the symbol file as the main symbol file.
|
||||||
|
|
||||||
|
ADD_FLAGS is passed on to the function adding the symbol file. */
|
||||||
|
extern void try_open_exec_file (const char *exec_file_host,
|
||||||
|
struct inferior *inf,
|
||||||
|
symfile_add_flags add_flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -854,8 +854,12 @@ add_inferior_command (char *args, int from_tty)
|
||||||
int i, copies = 1;
|
int i, copies = 1;
|
||||||
char *exec = NULL;
|
char *exec = NULL;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
symfile_add_flags add_flags = 0;
|
||||||
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
||||||
|
|
||||||
|
if (from_tty)
|
||||||
|
add_flags |= SYMFILE_VERBOSE;
|
||||||
|
|
||||||
if (args)
|
if (args)
|
||||||
{
|
{
|
||||||
argv = gdb_buildargv (args);
|
argv = gdb_buildargv (args);
|
||||||
|
@ -903,7 +907,7 @@ add_inferior_command (char *args, int from_tty)
|
||||||
switch_to_thread (null_ptid);
|
switch_to_thread (null_ptid);
|
||||||
|
|
||||||
exec_file_attach (exec, from_tty);
|
exec_file_attach (exec, from_tty);
|
||||||
symbol_file_add_main (exec, from_tty);
|
symbol_file_add_main (exec, add_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
48
gdb/infrun.c
48
gdb/infrun.c
|
@ -1077,15 +1077,17 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
|
||||||
fprintf_filtered (file, _("Follow exec mode is \"%s\".\n"), value);
|
fprintf_filtered (file, _("Follow exec mode is \"%s\".\n"), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EXECD_PATHNAME is assumed to be non-NULL. */
|
/* EXEC_FILE_TARGET is assumed to be non-NULL. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
follow_exec (ptid_t ptid, char *execd_pathname)
|
follow_exec (ptid_t ptid, char *exec_file_target)
|
||||||
{
|
{
|
||||||
struct thread_info *th, *tmp;
|
struct thread_info *th, *tmp;
|
||||||
struct inferior *inf = current_inferior ();
|
struct inferior *inf = current_inferior ();
|
||||||
int pid = ptid_get_pid (ptid);
|
int pid = ptid_get_pid (ptid);
|
||||||
ptid_t process_ptid;
|
ptid_t process_ptid;
|
||||||
|
char *exec_file_host;
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
|
||||||
/* This is an exec event that we actually wish to pay attention to.
|
/* This is an exec event that we actually wish to pay attention to.
|
||||||
Refresh our symbol table to the newly exec'd program, remove any
|
Refresh our symbol table to the newly exec'd program, remove any
|
||||||
|
@ -1155,7 +1157,7 @@ follow_exec (ptid_t ptid, char *execd_pathname)
|
||||||
process_ptid = pid_to_ptid (pid);
|
process_ptid = pid_to_ptid (pid);
|
||||||
printf_unfiltered (_("%s is executing new program: %s\n"),
|
printf_unfiltered (_("%s is executing new program: %s\n"),
|
||||||
target_pid_to_str (process_ptid),
|
target_pid_to_str (process_ptid),
|
||||||
execd_pathname);
|
exec_file_target);
|
||||||
|
|
||||||
/* We've followed the inferior through an exec. Therefore, the
|
/* We've followed the inferior through an exec. Therefore, the
|
||||||
inferior has essentially been killed & reborn. */
|
inferior has essentially been killed & reborn. */
|
||||||
|
@ -1164,14 +1166,17 @@ follow_exec (ptid_t ptid, char *execd_pathname)
|
||||||
|
|
||||||
breakpoint_init_inferior (inf_execd);
|
breakpoint_init_inferior (inf_execd);
|
||||||
|
|
||||||
if (*gdb_sysroot != '\0')
|
exec_file_host = exec_file_find (exec_file_target, NULL);
|
||||||
{
|
old_chain = make_cleanup (xfree, exec_file_host);
|
||||||
char *name = exec_file_find (execd_pathname, NULL);
|
|
||||||
|
|
||||||
execd_pathname = (char *) alloca (strlen (name) + 1);
|
/* If we were unable to map the executable target pathname onto a host
|
||||||
strcpy (execd_pathname, name);
|
pathname, tell the user that. Otherwise GDB's subsequent behavior
|
||||||
xfree (name);
|
is confusing. Maybe it would even be better to stop at this point
|
||||||
}
|
so that the user can specify a file manually before continuing. */
|
||||||
|
if (exec_file_host == NULL)
|
||||||
|
warning (_("Could not load symbols for executable %s.\n"
|
||||||
|
"Do you need \"set sysroot\"?"),
|
||||||
|
exec_file_target);
|
||||||
|
|
||||||
/* Reset the shared library package. This ensures that we get a
|
/* Reset the shared library package. This ensures that we get a
|
||||||
shlib event when the child reaches "_start", at which point the
|
shlib event when the child reaches "_start", at which point the
|
||||||
|
@ -1193,7 +1198,7 @@ follow_exec (ptid_t ptid, char *execd_pathname)
|
||||||
|
|
||||||
inf = add_inferior_with_spaces ();
|
inf = add_inferior_with_spaces ();
|
||||||
inf->pid = pid;
|
inf->pid = pid;
|
||||||
target_follow_exec (inf, execd_pathname);
|
target_follow_exec (inf, exec_file_target);
|
||||||
|
|
||||||
set_current_inferior (inf);
|
set_current_inferior (inf);
|
||||||
set_current_program_space (inf->pspace);
|
set_current_program_space (inf->pspace);
|
||||||
|
@ -1212,21 +1217,14 @@ follow_exec (ptid_t ptid, char *execd_pathname)
|
||||||
|
|
||||||
gdb_assert (current_program_space == inf->pspace);
|
gdb_assert (current_program_space == inf->pspace);
|
||||||
|
|
||||||
/* That a.out is now the one to use. */
|
/* Attempt to open the exec file. SYMFILE_DEFER_BP_RESET is used
|
||||||
exec_file_attach (execd_pathname, 0);
|
because the proper displacement for a PIE (Position Independent
|
||||||
|
Executable) main symbol file will only be computed by
|
||||||
|
solib_create_inferior_hook below. breakpoint_re_set would fail
|
||||||
|
to insert the breakpoints with the zero displacement. */
|
||||||
|
try_open_exec_file (exec_file_host, inf, SYMFILE_DEFER_BP_RESET);
|
||||||
|
|
||||||
/* SYMFILE_DEFER_BP_RESET is used as the proper displacement for PIE
|
do_cleanups (old_chain);
|
||||||
(Position Independent Executable) main symbol file will get applied by
|
|
||||||
solib_create_inferior_hook below. breakpoint_re_set would fail to insert
|
|
||||||
the breakpoints with the zero displacement. */
|
|
||||||
|
|
||||||
symbol_file_add (execd_pathname,
|
|
||||||
(inf->symfile_flags
|
|
||||||
| SYMFILE_MAINLINE | SYMFILE_DEFER_BP_RESET),
|
|
||||||
NULL, 0);
|
|
||||||
|
|
||||||
if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
|
|
||||||
set_initial_language ();
|
|
||||||
|
|
||||||
/* If the target can specify a description, read it. Must do this
|
/* If the target can specify a description, read it. Must do this
|
||||||
after flipping to the new executable (because the target supplied
|
after flipping to the new executable (because the target supplied
|
||||||
|
|
18
gdb/main.c
18
gdb/main.c
|
@ -413,6 +413,20 @@ catch_command_errors_const (catch_command_errors_const_ftype *command,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adapter for symbol_file_add_main that translates 'from_tty' to a
|
||||||
|
symfile_add_flags. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
symbol_file_add_main_adapter (const char *arg, int from_tty)
|
||||||
|
{
|
||||||
|
symfile_add_flags add_flags = 0;
|
||||||
|
|
||||||
|
if (from_tty)
|
||||||
|
add_flags |= SYMFILE_VERBOSE;
|
||||||
|
|
||||||
|
symbol_file_add_main (arg, add_flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* Type of this option. */
|
/* Type of this option. */
|
||||||
enum cmdarg_kind
|
enum cmdarg_kind
|
||||||
{
|
{
|
||||||
|
@ -1029,7 +1043,7 @@ captured_main_1 (struct captured_main_args *context)
|
||||||
catch_command_errors returns non-zero on success! */
|
catch_command_errors returns non-zero on success! */
|
||||||
if (catch_command_errors_const (exec_file_attach, execarg,
|
if (catch_command_errors_const (exec_file_attach, execarg,
|
||||||
!batch_flag))
|
!batch_flag))
|
||||||
catch_command_errors_const (symbol_file_add_main, symarg,
|
catch_command_errors_const (symbol_file_add_main_adapter, symarg,
|
||||||
!batch_flag);
|
!batch_flag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1038,7 +1052,7 @@ captured_main_1 (struct captured_main_args *context)
|
||||||
catch_command_errors_const (exec_file_attach, execarg,
|
catch_command_errors_const (exec_file_attach, execarg,
|
||||||
!batch_flag);
|
!batch_flag);
|
||||||
if (symarg != NULL)
|
if (symarg != NULL)
|
||||||
catch_command_errors_const (symbol_file_add_main, symarg,
|
catch_command_errors_const (symbol_file_add_main_adapter, symarg,
|
||||||
!batch_flag);
|
!batch_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1022,6 +1022,10 @@ open_symbol_file_object (void *from_ttyp)
|
||||||
gdb_byte *l_name_buf = (gdb_byte *) xmalloc (l_name_size);
|
gdb_byte *l_name_buf = (gdb_byte *) xmalloc (l_name_size);
|
||||||
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
|
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
|
||||||
struct svr4_info *info = get_svr4_info ();
|
struct svr4_info *info = get_svr4_info ();
|
||||||
|
symfile_add_flags add_flags = 0;
|
||||||
|
|
||||||
|
if (from_tty)
|
||||||
|
add_flags |= SYMFILE_VERBOSE;
|
||||||
|
|
||||||
if (symfile_objfile)
|
if (symfile_objfile)
|
||||||
if (!query (_("Attempt to reload symbols from process? ")))
|
if (!query (_("Attempt to reload symbols from process? ")))
|
||||||
|
@ -1071,7 +1075,7 @@ open_symbol_file_object (void *from_ttyp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Have a pathname: read the symbol file. */
|
/* Have a pathname: read the symbol file. */
|
||||||
symbol_file_add_main (filename, from_tty);
|
symbol_file_add_main (filename, add_flags);
|
||||||
|
|
||||||
do_cleanups (cleanups);
|
do_cleanups (cleanups);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
32
gdb/solib.c
32
gdb/solib.c
|
@ -380,21 +380,22 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
|
||||||
/* Return the full pathname of the main executable, or NULL if not
|
/* Return the full pathname of the main executable, or NULL if not
|
||||||
found. The returned pathname is malloc'ed and must be freed by
|
found. The returned pathname is malloc'ed and must be freed by
|
||||||
the caller. If FD is non-NULL, *FD is set to either -1 or an open
|
the caller. If FD is non-NULL, *FD is set to either -1 or an open
|
||||||
file handle for the main executable.
|
file handle for the main executable. */
|
||||||
|
|
||||||
The search algorithm used is described in solib_find_1's comment
|
|
||||||
above. */
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
exec_file_find (char *in_pathname, int *fd)
|
exec_file_find (char *in_pathname, int *fd)
|
||||||
{
|
{
|
||||||
char *result = solib_find_1 (in_pathname, fd, 0);
|
char *result;
|
||||||
|
const char *fskind = effective_target_file_system_kind ();
|
||||||
|
|
||||||
if (result == NULL)
|
if (in_pathname == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*gdb_sysroot != '\0' && IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
|
||||||
{
|
{
|
||||||
const char *fskind = effective_target_file_system_kind ();
|
result = solib_find_1 (in_pathname, fd, 0);
|
||||||
|
|
||||||
if (fskind == file_system_kind_dos_based)
|
if (result == NULL && fskind == file_system_kind_dos_based)
|
||||||
{
|
{
|
||||||
char *new_pathname;
|
char *new_pathname;
|
||||||
|
|
||||||
|
@ -405,6 +406,21 @@ exec_file_find (char *in_pathname, int *fd)
|
||||||
result = solib_find_1 (new_pathname, fd, 0);
|
result = solib_find_1 (new_pathname, fd, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It's possible we don't have a full path, but rather just a
|
||||||
|
filename. Some targets, such as HP-UX, don't provide the
|
||||||
|
full path, sigh.
|
||||||
|
|
||||||
|
Attempt to qualify the filename against the source path.
|
||||||
|
(If that fails, we'll just fall back on the original
|
||||||
|
filename. Not much more we can do...) */
|
||||||
|
|
||||||
|
if (!source_full_path_of (in_pathname, &result))
|
||||||
|
result = xstrdup (in_pathname);
|
||||||
|
if (fd != NULL)
|
||||||
|
*fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ int readnow_symbol_files; /* Read full symbols immediately. */
|
||||||
|
|
||||||
static void load_command (char *, int);
|
static void load_command (char *, int);
|
||||||
|
|
||||||
static void symbol_file_add_main_1 (const char *args, int from_tty,
|
static void symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags,
|
||||||
objfile_flags flags);
|
objfile_flags flags);
|
||||||
|
|
||||||
static void add_symbol_file_command (char *, int);
|
static void add_symbol_file_command (char *, int);
|
||||||
|
@ -1306,19 +1306,16 @@ symbol_file_add (const char *name, symfile_add_flags add_flags,
|
||||||
command itself. */
|
command itself. */
|
||||||
|
|
||||||
void
|
void
|
||||||
symbol_file_add_main (const char *args, int from_tty)
|
symbol_file_add_main (const char *args, symfile_add_flags add_flags)
|
||||||
{
|
{
|
||||||
symbol_file_add_main_1 (args, from_tty, 0);
|
symbol_file_add_main_1 (args, add_flags, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symbol_file_add_main_1 (const char *args, int from_tty, objfile_flags flags)
|
symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags,
|
||||||
|
objfile_flags flags)
|
||||||
{
|
{
|
||||||
symfile_add_flags add_flags = (current_inferior ()->symfile_flags
|
add_flags |= current_inferior ()->symfile_flags | SYMFILE_MAINLINE;
|
||||||
| SYMFILE_MAINLINE);
|
|
||||||
|
|
||||||
if (from_tty)
|
|
||||||
add_flags |= SYMFILE_VERBOSE;
|
|
||||||
|
|
||||||
symbol_file_add (args, add_flags, NULL, flags);
|
symbol_file_add (args, add_flags, NULL, flags);
|
||||||
|
|
||||||
|
@ -1655,9 +1652,13 @@ symbol_file_command (char *args, int from_tty)
|
||||||
{
|
{
|
||||||
char **argv = gdb_buildargv (args);
|
char **argv = gdb_buildargv (args);
|
||||||
objfile_flags flags = OBJF_USERLOADED;
|
objfile_flags flags = OBJF_USERLOADED;
|
||||||
|
symfile_add_flags add_flags = 0;
|
||||||
struct cleanup *cleanups;
|
struct cleanup *cleanups;
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
|
|
||||||
|
if (from_tty)
|
||||||
|
add_flags |= SYMFILE_VERBOSE;
|
||||||
|
|
||||||
cleanups = make_cleanup_freeargv (argv);
|
cleanups = make_cleanup_freeargv (argv);
|
||||||
while (*argv != NULL)
|
while (*argv != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1667,7 +1668,7 @@ symbol_file_command (char *args, int from_tty)
|
||||||
error (_("unknown option `%s'"), *argv);
|
error (_("unknown option `%s'"), *argv);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
symbol_file_add_main_1 (*argv, from_tty, flags);
|
symbol_file_add_main_1 (*argv, add_flags, flags);
|
||||||
name = *argv;
|
name = *argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -543,7 +543,8 @@ extern CORE_ADDR overlay_unmapped_address (CORE_ADDR, struct obj_section *);
|
||||||
extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *);
|
extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *);
|
||||||
|
|
||||||
/* Load symbols from a file. */
|
/* Load symbols from a file. */
|
||||||
extern void symbol_file_add_main (const char *args, int from_tty);
|
extern void symbol_file_add_main (const char *args,
|
||||||
|
symfile_add_flags add_flags);
|
||||||
|
|
||||||
/* Clear GDB symbol tables. */
|
/* Clear GDB symbol tables. */
|
||||||
extern void symbol_file_clear (int from_tty);
|
extern void symbol_file_clear (int from_tty);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2016-10-25 Luis Machado <lgustavo@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.base/exec-invalid-sysroot.exp: New file.
|
||||||
|
|
||||||
2016-10-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
2016-10-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
* gdb.base/morestack.exp: Try to build it using -fuse-ld=gold first.
|
* gdb.base/morestack.exp: Try to build it using -fuse-ld=gold first.
|
||||||
|
|
70
gdb/testsuite/gdb.base/exec-invalid-sysroot.exp
Normal file
70
gdb/testsuite/gdb.base/exec-invalid-sysroot.exp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# Copyright 1997-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# This test exercises PR20569. GDB would crash when attempting to follow
|
||||||
|
# an exec call when it could not resolve the path to the symbol file.
|
||||||
|
# This was the case when an invalid sysroot is provided.
|
||||||
|
|
||||||
|
standard_testfile foll-exec.c
|
||||||
|
|
||||||
|
global binfile
|
||||||
|
set binfile [standard_output_file "foll-exec"]
|
||||||
|
set testfile2 "execd-prog"
|
||||||
|
set srcfile2 ${testfile2}.c
|
||||||
|
set binfile2 [standard_output_file ${testfile2}]
|
||||||
|
|
||||||
|
set compile_options debug
|
||||||
|
|
||||||
|
# build the first test case
|
||||||
|
if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable $compile_options] != "" } {
|
||||||
|
untested "could not compile test program ${binfile2}"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $compile_options] != "" } {
|
||||||
|
untested "could not compile test program ${binfile}"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
proc do_exec_sysroot_test {} {
|
||||||
|
global binfile srcfile srcfile2 testfile testfile2
|
||||||
|
global gdb_prompt
|
||||||
|
|
||||||
|
gdb_test_no_output "set sysroot /a/path/that/does/not/exist"
|
||||||
|
|
||||||
|
# Start the program running, and stop at main.
|
||||||
|
#
|
||||||
|
if ![runto_main] then {
|
||||||
|
fail "Couldn't run ${testfile}"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify that the system supports "catch exec".
|
||||||
|
gdb_test "catch exec" "Catchpoint \[0-9\]* \\(exec\\)" "insert exec catchpoint"
|
||||||
|
set test "continue to exec catchpoint"
|
||||||
|
gdb_test_multiple "continue" $test {
|
||||||
|
-re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
|
||||||
|
unsupported $test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
-re ".*Could not load symbols for executable.*$gdb_prompt $" {
|
||||||
|
pass $test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start with a fresh gdb
|
||||||
|
clean_restart $binfile
|
||||||
|
do_exec_sysroot_test
|
Loading…
Add table
Add a link
Reference in a new issue