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
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);
|
||||
}
|
||||
|
||||
/* EXECD_PATHNAME is assumed to be non-NULL. */
|
||||
/* EXEC_FILE_TARGET is assumed to be non-NULL. */
|
||||
|
||||
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 inferior *inf = current_inferior ();
|
||||
int pid = ptid_get_pid (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.
|
||||
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);
|
||||
printf_unfiltered (_("%s is executing new program: %s\n"),
|
||||
target_pid_to_str (process_ptid),
|
||||
execd_pathname);
|
||||
exec_file_target);
|
||||
|
||||
/* We've followed the inferior through an exec. Therefore, the
|
||||
inferior has essentially been killed & reborn. */
|
||||
|
@ -1164,14 +1166,17 @@ follow_exec (ptid_t ptid, char *execd_pathname)
|
|||
|
||||
breakpoint_init_inferior (inf_execd);
|
||||
|
||||
if (*gdb_sysroot != '\0')
|
||||
{
|
||||
char *name = exec_file_find (execd_pathname, NULL);
|
||||
exec_file_host = exec_file_find (exec_file_target, NULL);
|
||||
old_chain = make_cleanup (xfree, exec_file_host);
|
||||
|
||||
execd_pathname = (char *) alloca (strlen (name) + 1);
|
||||
strcpy (execd_pathname, name);
|
||||
xfree (name);
|
||||
}
|
||||
/* If we were unable to map the executable target pathname onto a host
|
||||
pathname, tell the user that. Otherwise GDB's subsequent behavior
|
||||
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
|
||||
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->pid = pid;
|
||||
target_follow_exec (inf, execd_pathname);
|
||||
target_follow_exec (inf, exec_file_target);
|
||||
|
||||
set_current_inferior (inf);
|
||||
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);
|
||||
|
||||
/* That a.out is now the one to use. */
|
||||
exec_file_attach (execd_pathname, 0);
|
||||
/* Attempt to open the exec file. SYMFILE_DEFER_BP_RESET is used
|
||||
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
|
||||
(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 ();
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* If the target can specify a description, read it. Must do this
|
||||
after flipping to the new executable (because the target supplied
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue