X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fexec.c;h=468f9f57f76cceee2156f77887d58dcd0cb595fe;hb=5b6d1e4fa4fc6827c7b3f0e99ff120dfa14d65d2;hp=92c87e4e02f096c2ec04bf305465649c876153f8;hpb=14278e1fdbe045df184d6dd546ff6a1e9e3c3797;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/exec.c b/gdb/exec.c index 92c87e4e02..468f9f57f7 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -1,6 +1,6 @@ /* Work with executable files, for GDB. - Copyright (C) 1988-2017 Free Software Foundation, Inc. + Copyright (C) 1988-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -29,43 +29,62 @@ #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" +#include "readline/tilde.h" #include "gdbcore.h" #include #include #include "solist.h" #include +#include "gdbsupport/pathstuff.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); +/* The target vector for executable files. */ -static void exec_files_info (struct target_ops *); +struct exec_target final : public target_ops +{ + const target_info &info () const override + { return exec_target_info; } -static void init_exec_ops (void); + strata stratum () const override { return file_stratum; } -void _initialize_exec (void); + 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; -/* The target vector for executable files. */ + bool has_memory () override; + char *make_corefile_notes (bfd *, int *) override; + int find_memory_regions (find_memory_region_ftype func, void *data) override; +}; -static struct target_ops exec_ops; +static exec_target exec_ops; /* 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) @@ -76,7 +95,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); @@ -109,8 +128,8 @@ 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; scoped_restore_current_program_space restore_pspace; @@ -123,26 +142,13 @@ exec_close_1 (struct target_ops *self) } } -void -exec_file_clear (int from_tty) -{ - /* Remove exec file. */ - exec_close (); - - if (from_tty) - printf_unfiltered (_("No executable file now.\n")); -} - -/* See exec.h. */ +/* See gdbcore.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); + 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. @@ -155,40 +161,32 @@ try_open_exec_file (const char *exec_file_host, struct inferior *inf, 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 + 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) + catch (gdb_exception_error &err) { if (err.message != NULL) - warning ("%s", err.message); + warning ("%s", err.what ()); - 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); + prev_err = std::move (err); } - END_CATCH if (exec_file_host != NULL) { - TRY + try { symbol_file_add_main (exec_file_host, add_flags); } - CATCH (err, RETURN_MASK_ERROR) + catch (const gdb_exception_error &err) { if (!exception_print_same (prev_err, err)) - warning ("%s", err.message); + warning ("%s", err.what ()); } - END_CATCH } - - do_cleanups (old_chain); } /* See gdbcore.h. */ @@ -196,8 +194,7 @@ try_open_exec_file (const char *exec_file_host, struct inferior *inf, 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; + char *exec_file_target; symfile_add_flags add_flags = 0; /* Do nothing if we already have an executable filename. */ @@ -215,8 +212,8 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty) return; } - exec_file_host = exec_file_find (exec_file_target, NULL); - old_chain = make_cleanup (xfree, exec_file_host); + gdb::unique_xmalloc_ptr exec_file_host + = exec_file_find (exec_file_target, NULL); if (defer_bp_reset) add_flags |= SYMFILE_DEFER_BP_RESET; @@ -225,8 +222,7 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int 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); + try_open_exec_file (exec_file_host.get (), current_inferior (), add_flags); } /* Set FILENAME as the new exec file. @@ -252,8 +248,7 @@ exec_file_attach (const char *filename, int from_tty) /* 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); - gdb_bfd_ref_ptr exec_bfd_holder (exec_bfd); + gdb_bfd_ref_ptr exec_bfd_holder = gdb_bfd_ref_ptr::new_reference (exec_bfd); /* Remove any previous exec file. */ exec_close (); @@ -298,12 +293,10 @@ exec_file_attach (const char *filename, int from_tty) } else { - char *temp_pathname; - scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename, write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, - &temp_pathname); + &scratch_storage); #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__) if (scratch_chan < 0) { @@ -314,14 +307,13 @@ exec_file_attach (const char *filename, int from_tty) exename, write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, - &temp_pathname); + &scratch_storage); } #endif if (scratch_chan < 0) perror_with_name (filename); - scratch_storage.reset (temp_pathname); - scratch_pathname = temp_pathname; + scratch_pathname = scratch_storage.get (); /* gdb_bfd_open (and its variants) prefers canonicalized pathname for better BFD caching. */ @@ -358,7 +350,7 @@ exec_file_attach (const char *filename, int from_tty) exec_close (); error (_("\"%s\": not in executable format: %s"), scratch_pathname, - gdb_bfd_errmsg (bfd_get_error (), matching)); + gdb_bfd_errmsg (bfd_get_error (), matching).c_str ()); } if (build_section_table (exec_bfd, §ions, §ions_end)) @@ -388,7 +380,7 @@ exec_file_attach (const char *filename, int from_tty) } bfd_cache_close_all (); - observer_notify_executable_changed (); + gdb::observers::executable_changed.notify (); } /* Process the first arg in ARGS as the new exec file. @@ -400,10 +392,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 *filename; - if (from_tty && target_has_execution && !query (_("A program is being debugged already.\n" "Are you sure you want to change the file? "))) @@ -435,7 +425,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. */ @@ -464,14 +454,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)++; } @@ -557,10 +547,23 @@ add_target_sections (void *owner, table->sections[space + i].owner = owner; } + scoped_restore_current_thread restore_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); + } } } @@ -581,7 +584,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++; } @@ -595,7 +598,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); @@ -638,21 +641,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_thread restore_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 @@ -675,7 +696,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; @@ -702,31 +723,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; @@ -734,10 +750,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 = std::max (lo1, lo2); - r->length = std::min (hi1, hi2) - r->start; + memory.emplace_back (start, length); } } @@ -748,51 +764,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); + 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); - old_chain = make_cleanup (VEC_cleanup(mem_range_s), - &available_memory); + 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 = std::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; @@ -875,19 +877,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, @@ -921,17 +923,16 @@ 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; } } @@ -962,15 +963,15 @@ 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 ("\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); @@ -979,10 +980,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]; @@ -1002,15 +1003,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; } } @@ -1042,29 +1042,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; -} - -/* 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) +bool +exec_target::has_memory () { /* We can provide memory if we have any file/target sections to read from. */ @@ -1072,34 +1051,16 @@ 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) +int +exec_target::find_memory_regions (find_memory_region_ftype func, void *data) { - 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 = 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; - exec_ops.to_find_memory_regions = objfile_find_memory_regions; - exec_ops.to_magic = OPS_MAGIC; + return objfile_find_memory_regions (this, func, data); } void @@ -1107,8 +1068,6 @@ _initialize_exec (void) { struct cmd_list_element *c; - init_exec_ops (); - if (!dbx_commands) { c = add_cmd ("file", class_files, file_command, _("\ @@ -1142,5 +1101,5 @@ Show writing into executable and core files."), NULL, show_write_files, &setlist, &showlist); - add_target_with_completer (&exec_ops, filename_completer); + add_target (exec_target_info, exec_target_open, filename_completer); }