X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fexec.c;h=f94c15f1f53dd9cb127a8b1a05a662343868b9c5;hb=c819b2c0b216c69a4ae5bfba0eac71ffdf1b3596;hp=9d4ad90c3f90f6b0e3e035c7528dd1324f7bbb52;hpb=a10de6046fbd50e99742af428a815dcd94e2fba8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/exec.c b/gdb/exec.c index 9d4ad90c3f..f94c15f1f5 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -1,6 +1,6 @@ /* Work with executable files, for GDB. - Copyright (C) 1988-2015 Free Software Foundation, Inc. + Copyright (C) 1988-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -29,12 +29,13 @@ #include "completer.h" #include "value.h" #include "exec.h" -#include "observer.h" +#include "observable.h" #include "arch-utils.h" #include "gdbthread.h" #include "progspace.h" #include "gdb_bfd.h" #include "gcore.h" +#include "source.h" #include #include "readline/readline.h" @@ -42,21 +43,18 @@ #include #include +#include "solist.h" +#include +#include "common/pathstuff.h" -void (*deprecated_file_changed_hook) (char *); +void (*deprecated_file_changed_hook) (const char *); /* Prototypes for local functions */ -static void file_command (char *, int); - -static void set_section_command (char *, int); - static void exec_files_info (struct target_ops *); static void init_exec_ops (void); -void _initialize_exec (void); - /* The target vector for executable files. */ static struct target_ops exec_ops; @@ -111,17 +109,14 @@ static void exec_close_1 (struct target_ops *self) { struct program_space *ss; - struct cleanup *old_chain; + scoped_restore_current_program_space restore_pspace; - old_chain = save_current_program_space (); ALL_PSPACES (ss) - { - set_current_program_space (ss); - clear_section_table (current_target_sections); - exec_close (); - } - - do_cleanups (old_chain); + { + set_current_program_space (ss); + clear_section_table (current_target_sections); + exec_close (); + } } void @@ -134,35 +129,98 @@ exec_file_clear (int from_tty) printf_unfiltered (_("No executable file now.\n")); } +/* See exec.h. */ + +void +try_open_exec_file (const char *exec_file_host, struct inferior *inf, + symfile_add_flags add_flags) +{ + struct cleanup *old_chain; + struct gdb_exception prev_err = exception_none; + + 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. + + 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 + { + /* 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) + { + if (err.message != NULL) + warning ("%s", err.message); + + prev_err = err; + + /* Save message so it doesn't get trashed by the catch below. */ + if (err.message != NULL) + prev_err.message = xstrdup (err.message); + } + END_CATCH + + if (exec_file_host != NULL) + { + 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 + } + + do_cleanups (old_chain); +} + /* See gdbcore.h. */ void -exec_file_locate_attach (int pid, int from_tty) +exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty) { - char *exec_file, *full_exec_path = NULL; + char *exec_file_target; + symfile_add_flags add_flags = 0; /* Do nothing if we already have an executable filename. */ - exec_file = (char *) get_exec_file (0); - if (exec_file != NULL) + if (get_exec_file (0) != NULL) return; /* Try to determine a filename from the process itself. */ - exec_file = target_pid_to_exec_file (pid); - if (exec_file == NULL) - return; + 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; + } - /* 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. + gdb::unique_xmalloc_ptr exec_file_host + = exec_file_find (exec_file_target, NULL); - 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); + if (defer_bp_reset) + add_flags |= SYMFILE_DEFER_BP_RESET; - exec_file_attach (full_exec_path, from_tty); - symbol_file_add_main (full_exec_path, from_tty); + if (from_tty) + add_flags |= SYMFILE_VERBOSE; + + /* Attempt to open the exec file. */ + try_open_exec_file (exec_file_host.get (), current_inferior (), add_flags); } /* Set FILENAME as the new exec file. @@ -185,13 +243,10 @@ exec_file_locate_attach (int pid, int from_tty) void exec_file_attach (const char *filename, int from_tty) { - struct cleanup *cleanups; - /* First, acquire a reference to the current exec_bfd. We release this at the end of the function; but acquiring it now lets the BFD cache return it if this call refers to the same file. */ - gdb_bfd_ref (exec_bfd); - cleanups = make_cleanup_bfd_unref (exec_bfd); + gdb_bfd_ref_ptr exec_bfd_holder = new_bfd_ref (exec_bfd); /* Remove any previous exec file. */ exec_close (); @@ -208,7 +263,7 @@ exec_file_attach (const char *filename, int from_tty) else { int load_via_target = 0; - char *scratch_pathname, *canonical_pathname; + const char *scratch_pathname, *canonical_pathname; int scratch_chan; struct target_section *sections = NULL, *sections_end = NULL; char **matching; @@ -221,6 +276,7 @@ exec_file_attach (const char *filename, int from_tty) load_via_target = 1; } + gdb::unique_xmalloc_ptr canonical_storage, scratch_storage; if (load_via_target) { /* gdb_bfd_fopen does not support "target:" filenames. */ @@ -229,11 +285,8 @@ exec_file_attach (const char *filename, int from_tty) "not supported for %s sysroots"), TARGET_SYSROOT_PREFIX); - scratch_pathname = xstrdup (filename); - make_cleanup (xfree, scratch_pathname); - + scratch_pathname = filename; scratch_chan = -1; - canonical_pathname = scratch_pathname; } else @@ -241,40 +294,42 @@ exec_file_attach (const char *filename, int from_tty) scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename, write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, - &scratch_pathname); + &scratch_storage); #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__) if (scratch_chan < 0) { - char *exename = alloca (strlen (filename) + 5); + char *exename = (char *) alloca (strlen (filename) + 5); strcat (strcpy (exename, filename), ".exe"); scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename, write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, - &scratch_pathname); + &scratch_storage); } #endif if (scratch_chan < 0) perror_with_name (filename); - make_cleanup (xfree, scratch_pathname); + scratch_pathname = scratch_storage.get (); /* gdb_bfd_open (and its variants) prefers canonicalized pathname for better BFD caching. */ - canonical_pathname = gdb_realpath (scratch_pathname); - make_cleanup (xfree, canonical_pathname); + canonical_storage = gdb_realpath (scratch_pathname); + canonical_pathname = canonical_storage.get (); } + gdb_bfd_ref_ptr temp; if (write_files && !load_via_target) - exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget, - FOPEN_RUB, scratch_chan); + temp = gdb_bfd_fopen (canonical_pathname, gnutarget, + FOPEN_RUB, scratch_chan); else - exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan); + temp = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan); + exec_bfd = temp.release (); if (!exec_bfd) { - error (_("\"%s\": could not open as an executable file: %s"), + error (_("\"%s\": could not open as an executable file: %s."), scratch_pathname, bfd_errmsg (bfd_get_error ())); } @@ -284,7 +339,7 @@ exec_file_attach (const char *filename, int from_tty) if (load_via_target) exec_filename = xstrdup (bfd_get_filename (exec_bfd)); else - exec_filename = gdb_realpath_keepfile (scratch_pathname); + exec_filename = gdb_realpath_keepfile (scratch_pathname).release (); if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching)) { @@ -322,10 +377,8 @@ exec_file_attach (const char *filename, int from_tty) (*deprecated_exec_file_display_hook) (filename); } - do_cleanups (cleanups); - bfd_cache_close_all (); - observer_notify_executable_changed (); + gdb::observers::executable_changed.notify (); } /* Process the first arg in ARGS as the new exec file. @@ -337,11 +390,8 @@ exec_file_attach (const char *filename, int from_tty) If ARGS is NULL, we just want to close the exec file. */ static void -exec_file_command (char *args, int from_tty) +exec_file_command (const char *args, int from_tty) { - char **argv; - char *filename; - if (from_tty && target_has_execution && !query (_("A program is being debugged already.\n" "Are you sure you want to change the file? "))) @@ -349,13 +399,11 @@ exec_file_command (char *args, int from_tty) if (args) { - struct cleanup *cleanups; - /* Scan through the args and pick up the first non option arg as the filename. */ - argv = gdb_buildargv (args); - cleanups = make_cleanup_freeargv (argv); + gdb_argv built_argv (args); + char **argv = built_argv.get (); for (; (*argv != NULL) && (**argv == '-'); argv++) {; @@ -363,11 +411,8 @@ exec_file_command (char *args, int from_tty) if (*argv == NULL) error (_("No executable file name was specified")); - filename = tilde_expand (*argv); - make_cleanup (xfree, filename); - exec_file_attach (filename, from_tty); - - do_cleanups (cleanups); + gdb::unique_xmalloc_ptr filename (tilde_expand (*argv)); + exec_file_attach (filename.get (), from_tty); } else exec_file_attach (NULL, from_tty); @@ -378,7 +423,7 @@ exec_file_command (char *args, int from_tty) command was added? */ static void -file_command (char *arg, int from_tty) +file_command (const char *arg, int from_tty) { /* FIXME, if we lose on reading the symbol file, we should revert the exec file, but that's rough. */ @@ -444,8 +489,8 @@ resize_section_table (struct target_section_table *table, int adjustment) if (new_count) { - table->sections = xrealloc (table->sections, - sizeof (struct target_section) * new_count); + table->sections = XRESIZEVEC (struct target_section, table->sections, + new_count); table->sections_end = table->sections + new_count; } else @@ -466,7 +511,7 @@ build_section_table (struct bfd *some_bfd, struct target_section **start, count = bfd_count_sections (some_bfd); if (*start) xfree (* start); - *start = (struct target_section *) xmalloc (count * sizeof (**start)); + *start = XNEWVEC (struct target_section, count); *end = *start; bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end); if (*end > *start + count) @@ -645,20 +690,18 @@ exec_read_partial_read_only (gdb_byte *readbuf, ULONGEST offset, return TARGET_XFER_E_IO; } -/* Appends all read-only memory ranges found in the target section +/* Return all read-only memory ranges found in the target section table defined by SECTIONS and SECTIONS_END, starting at (and - intersected with) MEMADDR for LEN bytes. Returns the augmented - VEC. */ + intersected with) MEMADDR for LEN bytes. */ -static VEC(mem_range_s) * -section_table_available_memory (VEC(mem_range_s) *memory, - CORE_ADDR memaddr, ULONGEST len, +static std::vector +section_table_available_memory (CORE_ADDR memaddr, ULONGEST len, struct target_section *sections, struct target_section *sections_end) { - struct target_section *p; + std::vector memory; - for (p = sections; p < sections_end; p++) + for (target_section *p = sections; p < sections_end; p++) { if ((bfd_get_section_flags (p->the_bfd_section->owner, p->the_bfd_section) @@ -669,7 +712,6 @@ section_table_available_memory (VEC(mem_range_s) *memory, if (mem_ranges_overlap (p->addr, p->endaddr - p->addr, memaddr, len)) { ULONGEST lo1, hi1, lo2, hi2; - struct mem_range *r; lo1 = memaddr; hi1 = memaddr + len; @@ -677,10 +719,10 @@ section_table_available_memory (VEC(mem_range_s) *memory, lo2 = p->addr; hi2 = p->endaddr; - r = VEC_safe_push (mem_range_s, memory, NULL); + CORE_ADDR start = std::max (lo1, lo2); + int length = std::min (hi1, hi2) - start; - r->start = max (lo1, lo2); - r->length = min (hi1, hi2) - r->start; + memory.emplace_back (start, length); } } @@ -691,51 +733,37 @@ enum target_xfer_status section_table_read_available_memory (gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - VEC(mem_range_s) *available_memory = NULL; - struct target_section_table *table; - struct cleanup *old_chain; - mem_range_s *r; - int i; - - table = target_get_section_table (&exec_ops); - available_memory = section_table_available_memory (available_memory, - offset, len, - table->sections, - table->sections_end); - - old_chain = make_cleanup (VEC_cleanup(mem_range_s), - &available_memory); + target_section_table *table = target_get_section_table (&exec_ops); + std::vector available_memory + = section_table_available_memory (offset, len, + table->sections, table->sections_end); - normalize_mem_ranges (available_memory); + normalize_mem_ranges (&available_memory); - for (i = 0; - VEC_iterate (mem_range_s, available_memory, i, r); - i++) + for (const mem_range &r : available_memory) { - if (mem_ranges_overlap (r->start, r->length, offset, len)) + if (mem_ranges_overlap (r.start, r.length, offset, len)) { CORE_ADDR end; enum target_xfer_status status; /* Get the intersection window. */ - end = min (offset + len, r->start + r->length); + end = std::min (offset + len, r.start + r.length); gdb_assert (end - offset <= len); - if (offset >= r->start) + if (offset >= r.start) status = exec_read_partial_read_only (readbuf, offset, end - offset, xfered_len); else { - *xfered_len = r->start - offset; + *xfered_len = r.start - offset; status = TARGET_XFER_UNAVAILABLE; } - do_cleanups (old_chain); return status; } } - do_cleanups (old_chain); *xfered_len = len; return TARGET_XFER_UNAVAILABLE; @@ -922,10 +950,10 @@ exec_files_info (struct target_ops *t) } static void -set_section_command (char *args, int from_tty) +set_section_command (const char *args, int from_tty) { struct target_section *p; - char *secname; + const char *secname; unsigned seclen; unsigned long secaddr; char secprint[100]; @@ -996,6 +1024,16 @@ ignore (struct target_ops *ops, struct gdbarch *gdbarch, 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) { @@ -1027,7 +1065,7 @@ Specify the filename of the executable file."; 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;