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 (e1.message, e2.message) == 0);
+}
+
/* See gdbcore.h. */
void
exec_file_locate_attach (int pid, int from_tty)
{
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);
/* Try to determine a filename from the process itself. */
exec_file = target_pid_to_exec_file (pid);
if (exec_file == NULL)
- return;
+ {
+ 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)
+ {
+ 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_exec_path = xstrdup (exec_file);
}
- exec_file_attach (full_exec_path, from_tty);
- symbol_file_add_main (full_exec_path, from_tty);
+ 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
+ cannot be opened either locally or remotely.
+
+ This happens for example, when the file is first found in the local
+ sysroot (above), and then disappears (a TOCTOU race), or when it doesn't
+ exist in the target filesystem, or when the file does exist, but
+ is not readable.
+
+ Even without a symbol file, the remote-based debugging session should
+ continue normally instead of ending abruptly. Hence we catch thrown
+ errors/exceptions in the following code. */
+ TRY
+ {
+ exec_file_attach (full_exec_path, from_tty);
+ }
+ CATCH (err, RETURN_MASK_ERROR)
+ {
+ if (err.message != NULL)
+ warning ("%s", err.message);
+
+ prev_err = err;
+
+ /* Save message so it doesn't get trashed by the catch below. */
+ prev_err.message = xstrdup (err.message);
+ }
+ END_CATCH
+
+ TRY
+ {
+ symbol_file_add_main (full_exec_path, from_tty);
+ }
+ CATCH (err, RETURN_MASK_ERROR)
+ {
+ if (!exception_print_same (prev_err, err))
+ warning ("%s", err.message);
+ }
+ END_CATCH
+
+ do_cleanups (old_chain);
}
/* Set FILENAME as the new exec file.
return 0;
}
+/* Implement the to_remove_breakpoint method. */
+
+static int
+exec_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt,
+ enum remove_bp_reason reason)
+{
+ return 0;
+}
+
static int
exec_has_memory (struct target_ops *ops)
{
exec_ops.to_get_section_table = exec_get_section_table;
exec_ops.to_files_info = exec_files_info;
exec_ops.to_insert_breakpoint = ignore;
- exec_ops.to_remove_breakpoint = ignore;
+ exec_ops.to_remove_breakpoint = exec_remove_breakpoint;
exec_ops.to_stratum = file_stratum;
exec_ops.to_has_memory = exec_has_memory;
exec_ops.to_make_corefile_notes = exec_make_note_section;