X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fexec.c;h=ee13c5e027efc29eb07843b8c5474e60fd6a043d;hb=348fe36b1d64f12c60e08f6313520b3191663063;hp=124074ff50b50ced65342b25a01cf89d180e5a62;hpb=32d0add0a654c1204ab71dc8a55d9374538c4b33;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/exec.c b/gdb/exec.c index 124074ff50..ee13c5e027 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-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -29,41 +29,109 @@ #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 "progspace-and-thread.h" #include "gdb_bfd.h" #include "gcore.h" +#include "source.h" +#include "build-id.h" #include -#include "readline/readline.h" +#include "readline/tilde.h" #include "gdbcore.h" #include #include +#include "solist.h" +#include +#include "gdbsupport/pathstuff.h" +#include "cli/cli-style.h" -void (*deprecated_file_changed_hook) (char *); +void (*deprecated_file_changed_hook) (const char *); -/* Prototypes for local functions */ +static const target_info exec_target_info = { + "exec", + N_("Local exec file"), + N_("Use an executable file as a target.\n\ +Specify the filename of the executable file.") +}; -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); +/* The target vector for executable files. */ -void _initialize_exec (void); +struct exec_target final : public target_ops +{ + const target_info &info () const override + { return exec_target_info; } + + strata stratum () const override { return file_stratum; } + + void close () override; + enum target_xfer_status xfer_partial (enum target_object object, + const char *annex, + gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) override; + struct target_section_table *get_section_table () override; + void files_info () override; + + bool has_memory () override; + char *make_corefile_notes (bfd *, int *) override; + int find_memory_regions (find_memory_region_ftype func, void *data) override; +}; + +static exec_target exec_ops; + +/* How to handle a mismatch between the current exec file and the exec + file determined from target. */ + +static const char *const exec_file_mismatch_names[] + = {"ask", "warn", "off", NULL }; +enum exec_file_mismatch_mode + { + exec_file_mismatch_ask, exec_file_mismatch_warn, exec_file_mismatch_off + }; +static const char *exec_file_mismatch = exec_file_mismatch_names[0]; +static enum exec_file_mismatch_mode exec_file_mismatch_mode + = exec_file_mismatch_ask; -/* The target vector for executable files. */ +/* Show command. */ +static void +show_exec_file_mismatch_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (gdb_stdout, + _("exec-file-mismatch handling is currently \"%s\".\n"), + exec_file_mismatch_names[exec_file_mismatch_mode]); +} -static struct target_ops exec_ops; +/* Set command. Change the setting for range checking. */ +static void +set_exec_file_mismatch_command (const char *ignore, + int from_tty, struct cmd_list_element *c) +{ + for (enum exec_file_mismatch_mode mode = exec_file_mismatch_ask; + ; + mode = static_cast(1 + (int) mode)) + { + if (strcmp (exec_file_mismatch, exec_file_mismatch_names[mode]) == 0) + { + exec_file_mismatch_mode = mode; + return; + } + if (mode == exec_file_mismatch_off) + internal_error (__FILE__, __LINE__, + _("Unrecognized exec-file-mismatch setting: \"%s\""), + exec_file_mismatch); + } +} /* Whether to open exec and core files read-only or read-write. */ -int write_files = 0; +bool write_files = false; static void show_write_files (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -74,7 +142,7 @@ show_write_files (struct ui_file *file, int from_tty, static void -exec_open (const char *args, int from_tty) +exec_target_open (const char *args, int from_tty) { target_preopen (from_tty); exec_file_attach (args, from_tty); @@ -107,31 +175,189 @@ exec_close (void) /* This is the target_close implementation. Clears all target sections and closes all executable bfds from all program spaces. */ -static void -exec_close_1 (struct target_ops *self) +void +exec_target::close () { - 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 (); - } + for (struct program_space *ss : program_spaces) + { + set_current_program_space (ss); + clear_section_table (current_target_sections); + exec_close (); + } +} + +/* See gdbcore.h. */ + +void +try_open_exec_file (const char *exec_file_host, struct inferior *inf, + symfile_add_flags add_flags) +{ + struct gdb_exception prev_err; + + /* 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 (gdb_exception_error &err) + { + if (err.message != NULL) + warning ("%s", err.what ()); - do_cleanups (old_chain); + prev_err = std::move (err); + } + + if (exec_file_host != NULL) + { + try + { + symbol_file_add_main (exec_file_host, add_flags); + } + catch (const gdb_exception_error &err) + { + if (!exception_print_same (prev_err, err)) + warning ("%s", err.what ()); + } + } } +/* See gdbcore.h. */ + void -exec_file_clear (int from_tty) +validate_exec_file (int from_tty) { - /* Remove exec file. */ - exec_close (); + /* If user asked to ignore the mismatch, do nothing. */ + if (exec_file_mismatch_mode == exec_file_mismatch_off) + return; + + const char *current_exec_file = get_exec_file (0); + struct inferior *inf = current_inferior (); + /* Try to determine a filename from the process itself. */ + const char *pid_exec_file = target_pid_to_exec_file (inf->pid); + bool build_id_mismatch = false; + + /* If we cannot validate the exec file, return. */ + if (current_exec_file == NULL || pid_exec_file == NULL) + return; + + /* Try validating via build-id, if available. This is the most + reliable check. */ + const bfd_build_id *exec_file_build_id = build_id_bfd_get (exec_bfd); + if (exec_file_build_id != nullptr) + { + /* Prepend the target prefix, to force gdb_bfd_open to open the + file on the remote file system (if indeed remote). */ + std::string target_pid_exec_file + = std::string (TARGET_SYSROOT_PREFIX) + pid_exec_file; + + gdb_bfd_ref_ptr abfd (gdb_bfd_open (target_pid_exec_file.c_str (), + gnutarget, -1, false)); + if (abfd != nullptr) + { + const bfd_build_id *target_exec_file_build_id + = build_id_bfd_get (abfd.get ()); + + if (target_exec_file_build_id != nullptr) + { + if (exec_file_build_id->size == target_exec_file_build_id->size + && memcmp (exec_file_build_id->data, + target_exec_file_build_id->data, + exec_file_build_id->size) == 0) + { + /* Match. */ + return; + } + else + build_id_mismatch = true; + } + } + } + + if (build_id_mismatch) + { + std::string exec_file_target (pid_exec_file); + + /* In case the exec file is not local, exec_file_target has to point at + the target file system. */ + if (is_target_filename (current_exec_file) && !target_filesystem_is_local ()) + exec_file_target = TARGET_SYSROOT_PREFIX + exec_file_target; + + warning + (_("Mismatch between current exec-file %ps\n" + "and automatically determined exec-file %ps\n" + "exec-file-mismatch handling is currently \"%s\""), + styled_string (file_name_style.style (), current_exec_file), + styled_string (file_name_style.style (), exec_file_target.c_str ()), + exec_file_mismatch_names[exec_file_mismatch_mode]); + if (exec_file_mismatch_mode == exec_file_mismatch_ask) + { + symfile_add_flags add_flags = SYMFILE_MAINLINE; + if (from_tty) + add_flags |= SYMFILE_VERBOSE; + try + { + symbol_file_add_main (exec_file_target.c_str (), add_flags); + exec_file_attach (exec_file_target.c_str (), from_tty); + } + catch (gdb_exception_error &err) + { + warning (_("loading %ps %s"), + styled_string (file_name_style.style (), + exec_file_target.c_str ()), + err.message != NULL ? err.what () : "error"); + } + } + } +} + +/* See gdbcore.h. */ + +void +exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty) +{ + char *exec_file_target; + 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) + { + warning (_("No executable has been specified and target does not " + "support\n" + "determining executable automatically. " + "Try using the \"file\" command.")); + return; + } + + gdb::unique_xmalloc_ptr exec_file_host + = exec_file_find (exec_file_target, NULL); + + if (defer_bp_reset) + add_flags |= SYMFILE_DEFER_BP_RESET; if (from_tty) - printf_unfiltered (_("No executable file now.\n")); + 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. @@ -154,13 +380,10 @@ exec_file_clear (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 = gdb_bfd_ref_ptr::new_reference (exec_bfd); /* Remove any previous exec file. */ exec_close (); @@ -176,58 +399,97 @@ exec_file_attach (const char *filename, int from_tty) } else { - char *scratch_pathname, *canonical_pathname; + int load_via_target = 0; + const char *scratch_pathname, *canonical_pathname; int scratch_chan; struct target_section *sections = NULL, *sections_end = NULL; char **matching; - scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename, - write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, - &scratch_pathname); -#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__) - if (scratch_chan < 0) + if (is_target_filename (filename)) { - char *exename = alloca (strlen (filename) + 5); + if (target_filesystem_is_local ()) + filename += strlen (TARGET_SYSROOT_PREFIX); + else + load_via_target = 1; + } - 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); + gdb::unique_xmalloc_ptr canonical_storage, scratch_storage; + if (load_via_target) + { + /* gdb_bfd_fopen does not support "target:" filenames. */ + if (write_files) + warning (_("writing into executable files is " + "not supported for %s sysroots"), + TARGET_SYSROOT_PREFIX); + + scratch_pathname = filename; + scratch_chan = -1; + canonical_pathname = scratch_pathname; } + else + { + scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, + filename, write_files ? + O_RDWR | O_BINARY : O_RDONLY | O_BINARY, + &scratch_storage); +#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__) + if (scratch_chan < 0) + { + int first_errno = errno; + 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_storage); + if (scratch_chan < 0) + errno = first_errno; + } #endif - if (scratch_chan < 0) - perror_with_name (filename); + 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); + /* gdb_bfd_open (and its variants) prefers canonicalized + pathname for better BFD caching. */ + canonical_storage = gdb_realpath (scratch_pathname); + canonical_pathname = canonical_storage.get (); + } - if (write_files) - exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget, - FOPEN_RUB, scratch_chan); + gdb_bfd_ref_ptr temp; + if (write_files && !load_via_target) + 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"), - scratch_pathname, bfd_errmsg (bfd_get_error ())); + error (_("\"%ps\": could not open as an executable file: %s."), + styled_string (file_name_style.style (), scratch_pathname), + bfd_errmsg (bfd_get_error ())); } + /* gdb_realpath_keepfile resolves symlinks on the local + filesystem and so cannot be used for "target:" files. */ gdb_assert (exec_filename == NULL); - exec_filename = gdb_realpath_keepfile (scratch_pathname); + if (load_via_target) + exec_filename = xstrdup (bfd_get_filename (exec_bfd)); + else + exec_filename = gdb_realpath_keepfile (scratch_pathname).release (); if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching)) { /* Make sure to close exec_bfd, or else "run" might try to use it. */ exec_close (); - error (_("\"%s\": not in executable format: %s"), - scratch_pathname, - gdb_bfd_errmsg (bfd_get_error (), matching)); + error (_("\"%ps\": not in executable format: %s"), + styled_string (file_name_style.style (), scratch_pathname), + gdb_bfd_errmsg (bfd_get_error (), matching).c_str ()); } if (build_section_table (exec_bfd, §ions, §ions_end)) @@ -235,8 +497,9 @@ exec_file_attach (const char *filename, int from_tty) /* Make sure to close exec_bfd, or else "run" might try to use it. */ exec_close (); - error (_("\"%s\": can't find the file sections: %s"), - scratch_pathname, bfd_errmsg (bfd_get_error ())); + error (_("\"%ps\": can't find the file sections: %s"), + styled_string (file_name_style.style (), scratch_pathname), + bfd_errmsg (bfd_get_error ())); } exec_bfd_mtime = bfd_get_mtime (exec_bfd); @@ -256,10 +519,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. @@ -271,11 +532,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? "))) @@ -283,13 +541,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++) {; @@ -297,11 +553,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); @@ -312,7 +565,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. */ @@ -341,14 +594,14 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect, encountered on sparc-solaris 2.10 a shared library with an empty .bss section to which a symbol named "_end" was attached. The address of this symbol still needs to be relocated. */ - aflag = bfd_get_section_flags (abfd, asect); + aflag = bfd_section_flags (asect); if (!(aflag & SEC_ALLOC)) return; (*table_pp)->owner = NULL; (*table_pp)->the_bfd_section = asect; - (*table_pp)->addr = bfd_section_vma (abfd, asect); - (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect); + (*table_pp)->addr = bfd_section_vma (asect); + (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (asect); (*table_pp)++; } @@ -378,8 +631,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 @@ -398,14 +651,13 @@ build_section_table (struct bfd *some_bfd, struct target_section **start, unsigned count; count = bfd_count_sections (some_bfd); - if (*start) - xfree (* start); - *start = (struct target_section *) xmalloc (count * sizeof (**start)); + xfree (*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) - internal_error (__FILE__, __LINE__, - _("failed internal consistency check")); + + gdb_assert (*end <= *start + count); + /* We could realloc the table, but it probably loses for most files. */ return 0; } @@ -434,10 +686,23 @@ add_target_sections (void *owner, table->sections[space + i].owner = owner; } + scoped_restore_current_pspace_and_thread restore_pspace_thread; + program_space *curr_pspace = current_program_space; + /* If these are the first file sections we can provide memory - from, push the file_stratum target. */ - if (!target_is_pushed (&exec_ops)) - push_target (&exec_ops); + from, push the file_stratum target. Must do this in all + inferiors sharing the program space. */ + for (inferior *inf : all_inferiors ()) + { + if (inf->pspace != curr_pspace) + continue; + + if (inf->target_is_pushed (&exec_ops)) + continue; + + switch_to_inferior_no_thread (inf); + push_target (&exec_ops); + } } } @@ -458,7 +723,7 @@ add_target_sections_of_objfile (struct objfile *objfile) /* Compute the number of sections to add. */ ALL_OBJFILE_OSECTIONS (objfile, osect) { - if (bfd_get_section_size (osect->the_bfd_section) == 0) + if (bfd_section_size (osect->the_bfd_section) == 0) continue; count++; } @@ -472,7 +737,7 @@ add_target_sections_of_objfile (struct objfile *objfile) ALL_OBJFILE_OSECTIONS (objfile, osect) { - if (bfd_get_section_size (osect->the_bfd_section) == 0) + if (bfd_section_size (osect->the_bfd_section) == 0) continue; gdb_assert (ts < table->sections + space + count); @@ -515,21 +780,39 @@ remove_target_sections (void *owner) old_count = resize_section_table (table, dest - src); /* If we don't have any more sections to read memory from, - remove the file_stratum target from the stack. */ + remove the file_stratum target from the stack of each + inferior sharing the program space. */ if (old_count + (dest - src) == 0) { - struct program_space *pspace; + scoped_restore_current_pspace_and_thread restore_pspace_thread; + program_space *curr_pspace = current_program_space; - ALL_PSPACES (pspace) - if (pspace->target_sections.sections - != pspace->target_sections.sections_end) - return; + for (inferior *inf : all_inferiors ()) + { + if (inf->pspace != curr_pspace) + continue; + + if (inf->pspace->target_sections.sections + != inf->pspace->target_sections.sections_end) + continue; - unpush_target (&exec_ops); + switch_to_inferior_no_thread (inf); + unpush_target (&exec_ops); + } } } } +/* See exec.h. */ + +void +exec_on_vfork () +{ + if (current_program_space->target_sections.sections + != current_program_space->target_sections.sections_end) + push_target (&exec_ops); +} + enum target_xfer_status @@ -552,7 +835,7 @@ exec_read_partial_read_only (gdb_byte *readbuf, ULONGEST offset, continue; vma = s->vma; - size = bfd_get_section_size (s); + size = bfd_section_size (s); if (vma <= offset && offset < (vma + size)) { ULONGEST amt; @@ -579,31 +862,26 @@ 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) - & SEC_READONLY) == 0) + if ((bfd_section_flags (p->the_bfd_section) & SEC_READONLY) == 0) continue; /* Copy the meta-data, adjusted. */ 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; @@ -611,10 +889,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); } } @@ -625,51 +903,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; + 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); - table = target_get_section_table (&exec_ops); - available_memory = section_table_available_memory (available_memory, - offset, len, - table->sections, - table->sections_end); + normalize_mem_ranges (&available_memory); - old_chain = make_cleanup (VEC_cleanup(mem_range_s), - &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; @@ -688,9 +952,7 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST memaddr = offset; ULONGEST memend = memaddr + len; - if (len == 0) - internal_error (__FILE__, __LINE__, - _("failed internal consistency check")); + gdb_assert (len != 0); for (p = sections; p < sections_end; p++) { @@ -752,19 +1014,19 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, return TARGET_XFER_EOF; /* We can't help. */ } -static struct target_section_table * -exec_get_section_table (struct target_ops *ops) +struct target_section_table * +exec_target::get_section_table () { return current_target_sections; } -static enum target_xfer_status -exec_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) +enum target_xfer_status +exec_target::xfer_partial (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - struct target_section_table *table = target_get_section_table (ops); + struct target_section_table *table = get_section_table (); if (object == TARGET_OBJECT_MEMORY) return section_table_xfer_memory_partial (readbuf, writebuf, @@ -785,7 +1047,9 @@ print_section_info (struct target_section_table *t, bfd *abfd) /* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64. */ int wid = gdbarch_addr_bit (gdbarch) <= 32 ? 8 : 16; - printf_filtered ("\t`%s', ", bfd_get_filename (abfd)); + printf_filtered ("\t`%ps', ", + styled_string (file_name_style.style (), + bfd_get_filename (abfd))); wrap_here (" "); printf_filtered (_("file type %s.\n"), bfd_get_target (abfd)); if (abfd == exec_bfd) @@ -798,23 +1062,23 @@ print_section_info (struct target_section_table *t, bfd *abfd) for (p = t->sections; p < t->sections_end; p++) { struct bfd_section *psect = p->the_bfd_section; - bfd *pbfd = psect->owner; - if ((bfd_get_section_flags (pbfd, psect) & (SEC_ALLOC | SEC_LOAD)) + if ((bfd_section_flags (psect) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) continue; - if (bfd_get_section_vma (pbfd, psect) <= abfd->start_address - && abfd->start_address < (bfd_get_section_vma (pbfd, psect) - + bfd_get_section_size (psect))) + if (bfd_section_vma (psect) <= abfd->start_address + && abfd->start_address < (bfd_section_vma (psect) + + bfd_section_size (psect))) { - displacement = p->addr - bfd_get_section_vma (pbfd, psect); + displacement = p->addr - bfd_section_vma (psect); break; } } if (p == t->sections_end) - warning (_("Cannot find section for the entry point of %s."), - bfd_get_filename (abfd)); + warning (_("Cannot find section for the entry point of %ps."), + styled_string (file_name_style.style (), + bfd_get_filename (abfd))); entry_point = gdbarch_addr_bits_remove (gdbarch, bfd_get_start_address (abfd) @@ -839,15 +1103,17 @@ print_section_info (struct target_section_table *t, bfd *abfd) if (info_verbose) printf_filtered (" @ %s", hex_string_custom (psect->filepos, 8)); - printf_filtered (" is %s", bfd_section_name (pbfd, psect)); + printf_filtered (" is %s", bfd_section_name (psect)); if (pbfd != abfd) - printf_filtered (" in %s", bfd_get_filename (pbfd)); + printf_filtered (" in %ps", + styled_string (file_name_style.style (), + bfd_get_filename (pbfd))); printf_filtered ("\n"); } } -static void -exec_files_info (struct target_ops *t) +void +exec_target::files_info () { if (exec_bfd) print_section_info (current_target_sections, exec_bfd); @@ -856,10 +1122,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]; @@ -879,15 +1145,14 @@ set_section_command (char *args, int from_tty) table = current_target_sections; for (p = table->sections; p < table->sections_end; p++) { - if (!strncmp (secname, bfd_section_name (p->bfd, - p->the_bfd_section), seclen) - && bfd_section_name (p->bfd, p->the_bfd_section)[seclen] == '\0') + if (!strncmp (secname, bfd_section_name (p->the_bfd_section), seclen) + && bfd_section_name (p->the_bfd_section)[seclen] == '\0') { offset = secaddr - p->addr; p->addr += offset; p->endaddr += offset; if (from_tty) - exec_files_info (&exec_ops); + exec_ops.files_info (); return; } } @@ -910,7 +1175,8 @@ exec_set_section_address (const char *filename, int index, CORE_ADDR address) table = current_target_sections; for (p = table->sections; p < table->sections_end; p++) { - if (filename_cmp (filename, p->the_bfd_section->owner->filename) == 0 + if (filename_cmp (filename, + bfd_get_filename (p->the_bfd_section->owner)) == 0 && index == p->the_bfd_section->index) { p->endaddr += address - p->addr; @@ -919,19 +1185,8 @@ exec_set_section_address (const char *filename, int index, CORE_ADDR address) } } -/* If mourn is being called in all the right places, this could be say - `gdb internal error' (since generic_mourn calls - breakpoint_init_inferior). */ - -static int -ignore (struct target_ops *ops, struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - return 0; -} - -static int -exec_has_memory (struct target_ops *ops) +bool +exec_target::has_memory () { /* We can provide memory if we have any file/target sections to read from. */ @@ -939,43 +1194,24 @@ exec_has_memory (struct target_ops *ops) != current_target_sections->sections_end); } -static char * -exec_make_note_section (struct target_ops *self, bfd *obfd, int *note_size) +char * +exec_target::make_corefile_notes (bfd *obfd, int *note_size) { error (_("Can't create a corefile")); } -/* Fill in the exec file target vector. Very few entries need to be - defined. */ - -static void -init_exec_ops (void) -{ - exec_ops.to_shortname = "exec"; - exec_ops.to_longname = "Local exec file"; - exec_ops.to_doc = "Use an executable file as a target.\n\ -Specify the filename of the executable file."; - exec_ops.to_open = exec_open; - exec_ops.to_close = exec_close_1; - exec_ops.to_xfer_partial = exec_xfer_partial; - 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_stratum = file_stratum; - exec_ops.to_has_memory = exec_has_memory; - exec_ops.to_make_corefile_notes = exec_make_note_section; - exec_ops.to_find_memory_regions = objfile_find_memory_regions; - exec_ops.to_magic = OPS_MAGIC; +int +exec_target::find_memory_regions (find_memory_region_ftype func, void *data) +{ + return objfile_find_memory_regions (this, func, data); } +void _initialize_exec (); void -_initialize_exec (void) +_initialize_exec () { struct cmd_list_element *c; - init_exec_ops (); - if (!dbx_commands) { c = add_cmd ("file", class_files, file_command, _("\ @@ -1009,5 +1245,23 @@ Show writing into executable and core files."), NULL, show_write_files, &setlist, &showlist); - add_target_with_completer (&exec_ops, filename_completer); + add_setshow_enum_cmd ("exec-file-mismatch", class_support, + exec_file_mismatch_names, + &exec_file_mismatch, + _("\ +Set exec-file-mismatch handling (ask|warn|off)."), + _("\ +Show exec-file-mismatch handling (ask|warn|off)."), + _("\ +Specifies how to handle a mismatch between the current exec-file\n\ +loaded by GDB and the exec-file automatically determined when attaching\n\ +to a process:\n\n\ + ask - warn the user and ask whether to load the determined exec-file.\n\ + warn - warn the user, but do not change the exec-file.\n\ + off - do not check for mismatch."), + set_exec_file_mismatch_command, + show_exec_file_mismatch_command, + &setlist, &showlist); + + add_target (exec_target_info, exec_target_open, filename_completer); }