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:
Sandra Loosemore 2016-10-26 12:12:01 -05:00 committed by Pedro Alves
parent b15cc25cbe
commit ecf45d2cc7
14 changed files with 277 additions and 121 deletions

View file

@ -85,7 +85,7 @@ int readnow_symbol_files; /* Read full symbols immediately. */
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);
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. */
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
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
| SYMFILE_MAINLINE);
if (from_tty)
add_flags |= SYMFILE_VERBOSE;
add_flags |= current_inferior ()->symfile_flags | SYMFILE_MAINLINE;
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);
objfile_flags flags = OBJF_USERLOADED;
symfile_add_flags add_flags = 0;
struct cleanup *cleanups;
char *name = NULL;
if (from_tty)
add_flags |= SYMFILE_VERBOSE;
cleanups = make_cleanup_freeargv (argv);
while (*argv != NULL)
{
@ -1667,7 +1668,7 @@ symbol_file_command (char *args, int from_tty)
error (_("unknown option `%s'"), *argv);
else
{
symbol_file_add_main_1 (*argv, from_tty, flags);
symbol_file_add_main_1 (*argv, add_flags, flags);
name = *argv;
}