From ecf45d2cc7667ed4692d07e52fc77a2c9a8adf1c Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Wed, 26 Oct 2016 12:12:01 -0500 Subject: [PATCH] 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 Luis Machado Pedro Alves 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 * gdb.base/exec-invalid-sysroot.exp: New file. --- gdb/ChangeLog | 32 +++++ gdb/exceptions.c | 18 +++ gdb/exceptions.h | 3 + gdb/exec.c | 125 ++++++++---------- gdb/exec.h | 8 ++ gdb/inferior.c | 6 +- gdb/infrun.c | 48 ++++--- gdb/main.c | 18 ++- gdb/solib-svr4.c | 6 +- gdb/solib.c | 32 +++-- gdb/symfile.c | 21 +-- gdb/symfile.h | 3 +- gdb/testsuite/ChangeLog | 4 + .../gdb.base/exec-invalid-sysroot.exp | 70 ++++++++++ 14 files changed, 275 insertions(+), 119 deletions(-) create mode 100644 gdb/testsuite/gdb.base/exec-invalid-sysroot.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 45e29cc301..768d166cd5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,35 @@ +2016-10-25 Sandra Loosemore + Luis Machado + Pedro Alves + + 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 * coffread.c (coff_symfile_read): Use symfile_add_flags. diff --git a/gdb/exceptions.c b/gdb/exceptions.c index 9a10f66528..99199382bb 100644 --- a/gdb/exceptions.c +++ b/gdb/exceptions.c @@ -256,3 +256,21 @@ catch_errors (catch_errors_ftype *func, void *func_args, char *errstring, return 0; 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); +} diff --git a/gdb/exceptions.h b/gdb/exceptions.h index 5711c1a35e..a2d39d7d4a 100644 --- a/gdb/exceptions.h +++ b/gdb/exceptions.h @@ -88,4 +88,7 @@ extern int catch_exceptions_with_msg (struct ui_out *uiout, typedef int (catch_errors_ftype) (void *); 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 diff --git a/gdb/exec.c b/gdb/exec.c index 6e2a296d2e..eeca005b39 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -136,73 +136,16 @@ exec_file_clear (int from_tty) printf_unfiltered (_("No executable file now.\n")); } -/* Returns non-zero if exceptions E1 and E2 are equal. Returns zero - 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. */ +/* See exec.h. */ 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 gdb_exception prev_err = exception_none; - /* Do nothing if we already have an executable filename. */ - 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); + old_chain = make_cleanup (free_current_contents, &prev_err.message); /* exec_file_attach and symbol_file_add_main may throw an error if the file 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. */ 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) { @@ -232,20 +177,58 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty) } END_CATCH - TRY + if (exec_file_host != NULL) { - if (defer_bp_reset) - current_inferior ()->symfile_flags |= SYMFILE_DEFER_BP_RESET; - symbol_file_add_main (full_exec_path, from_tty); + TRY + { + 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) + + 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) { - if (!exception_print_same (prev_err, err)) - warning ("%s", err.message); + warning (_("No executable has been specified and target does not " + "support\n" + "determining executable automatically. " + "Try using the \"file\" command.")); + return; } - END_CATCH - current_inferior ()->symfile_flags &= ~SYMFILE_DEFER_BP_RESET; + 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); } diff --git a/gdb/exec.h b/gdb/exec.h index 4044cb71b8..f50e9eadb3 100644 --- a/gdb/exec.h +++ b/gdb/exec.h @@ -23,6 +23,7 @@ #include "target.h" #include "progspace.h" #include "memrange.h" +#include "symfile-add-flags.h" struct target_section; struct target_ops; @@ -113,4 +114,11 @@ extern void print_section_info (struct target_section_table *table, 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 diff --git a/gdb/inferior.c b/gdb/inferior.c index 250603c85c..92a18d6627 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -854,8 +854,12 @@ add_inferior_command (char *args, int from_tty) int i, copies = 1; char *exec = NULL; char **argv; + symfile_add_flags add_flags = 0; struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + if (from_tty) + add_flags |= SYMFILE_VERBOSE; + if (args) { argv = gdb_buildargv (args); @@ -903,7 +907,7 @@ add_inferior_command (char *args, int from_tty) switch_to_thread (null_ptid); exec_file_attach (exec, from_tty); - symbol_file_add_main (exec, from_tty); + symbol_file_add_main (exec, add_flags); } } diff --git a/gdb/infrun.c b/gdb/infrun.c index 5e624729d3..b10aa03b66 100644 --- a/gdb/infrun.c +++ b/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 diff --git a/gdb/main.c b/gdb/main.c index 23852e2d47..ca6a81e804 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -413,6 +413,20 @@ catch_command_errors_const (catch_command_errors_const_ftype *command, 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. */ enum cmdarg_kind { @@ -1029,7 +1043,7 @@ captured_main_1 (struct captured_main_args *context) catch_command_errors returns non-zero on success! */ if (catch_command_errors_const (exec_file_attach, execarg, !batch_flag)) - catch_command_errors_const (symbol_file_add_main, symarg, + catch_command_errors_const (symbol_file_add_main_adapter, symarg, !batch_flag); } else @@ -1038,7 +1052,7 @@ captured_main_1 (struct captured_main_args *context) catch_command_errors_const (exec_file_attach, execarg, !batch_flag); if (symarg != NULL) - catch_command_errors_const (symbol_file_add_main, symarg, + catch_command_errors_const (symbol_file_add_main_adapter, symarg, !batch_flag); } diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 258d7dc49e..0e18292561 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -1022,6 +1022,10 @@ open_symbol_file_object (void *from_ttyp) gdb_byte *l_name_buf = (gdb_byte *) xmalloc (l_name_size); struct cleanup *cleanups = make_cleanup (xfree, l_name_buf); struct svr4_info *info = get_svr4_info (); + symfile_add_flags add_flags = 0; + + if (from_tty) + add_flags |= SYMFILE_VERBOSE; if (symfile_objfile) 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. */ - symbol_file_add_main (filename, from_tty); + symbol_file_add_main (filename, add_flags); do_cleanups (cleanups); return 1; diff --git a/gdb/solib.c b/gdb/solib.c index 5067191c57..29b25d56c7 100644 --- a/gdb/solib.c +++ b/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 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 - file handle for the main executable. - - The search algorithm used is described in solib_find_1's comment - above. */ + file handle for the main executable. */ char * 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 (in_pathname == NULL) + return NULL; - if (result == 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; @@ -405,6 +406,21 @@ exec_file_find (char *in_pathname, int *fd) 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; } diff --git a/gdb/symfile.c b/gdb/symfile.c index 616fef0f8c..f524f56b36 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -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; } diff --git a/gdb/symfile.h b/gdb/symfile.h index cd94d85585..59952cbba2 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -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 *); /* 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. */ extern void symbol_file_clear (int from_tty); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 460e6b9abc..d0a2bc986a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-10-25 Luis Machado + + * gdb.base/exec-invalid-sysroot.exp: New file. + 2016-10-24 Jan Kratochvil * gdb.base/morestack.exp: Try to build it using -fuse-ld=gold first. diff --git a/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp b/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp new file mode 100644 index 0000000000..9665b5fc33 --- /dev/null +++ b/gdb/testsuite/gdb.base/exec-invalid-sysroot.exp @@ -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 . + +# 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 -- 2.34.1