| Index: gdb/exec.c
|
| diff --git a/gdb/exec.c b/gdb/exec.c
|
| index 6ba198615f1322552128690f00effa7c72af6d0c..38d2edb01c06cc90b5fb2171e9a986ba62edc5e0 100644
|
| --- a/gdb/exec.c
|
| +++ b/gdb/exec.c
|
| @@ -1,6 +1,6 @@
|
| /* Work with executable files, for GDB.
|
|
|
| - Copyright (C) 1988-2003, 2007-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1988-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -33,19 +33,16 @@
|
| #include "arch-utils.h"
|
| #include "gdbthread.h"
|
| #include "progspace.h"
|
| +#include "gdb_bfd.h"
|
|
|
| #include <fcntl.h>
|
| #include "readline/readline.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
|
|
| #include "gdbcore.h"
|
|
|
| #include <ctype.h>
|
| -#include "gdb_stat.h"
|
| -
|
| -#include "xcoffsolib.h"
|
| -
|
| -struct vmap *map_vmap (bfd *, bfd *);
|
| +#include <sys/stat.h>
|
|
|
| void (*deprecated_file_changed_hook) (char *);
|
|
|
| @@ -80,8 +77,6 @@ show_write_files (struct ui_file *file, int from_tty,
|
| }
|
|
|
|
|
| -struct vmap *vmap;
|
| -
|
| static void
|
| exec_open (char *args, int from_tty)
|
| {
|
| @@ -98,17 +93,18 @@ exec_close (void)
|
| if (exec_bfd)
|
| {
|
| bfd *abfd = exec_bfd;
|
| - char *name = bfd_get_filename (abfd);
|
|
|
| - gdb_bfd_close_or_warn (abfd);
|
| - xfree (name);
|
| + gdb_bfd_unref (abfd);
|
|
|
| /* Removing target sections may close the exec_ops target.
|
| Clear exec_bfd before doing so to prevent recursion. */
|
| exec_bfd = NULL;
|
| exec_bfd_mtime = 0;
|
|
|
| - remove_target_sections (abfd);
|
| + remove_target_sections (&exec_bfd);
|
| +
|
| + xfree (exec_filename);
|
| + exec_filename = NULL;
|
| }
|
| }
|
|
|
| @@ -116,35 +112,10 @@ exec_close (void)
|
| sections and closes all executable bfds from all program spaces. */
|
|
|
| static void
|
| -exec_close_1 (int quitting)
|
| +exec_close_1 (void)
|
| {
|
| - int need_symtab_cleanup = 0;
|
| - struct vmap *vp, *nxt;
|
| -
|
| using_exec_ops = 0;
|
|
|
| - for (nxt = vmap; nxt != NULL;)
|
| - {
|
| - vp = nxt;
|
| - nxt = vp->nxt;
|
| -
|
| - /* if there is an objfile associated with this bfd,
|
| - free_objfile() will do proper cleanup of objfile *and* bfd. */
|
| -
|
| - if (vp->objfile)
|
| - {
|
| - free_objfile (vp->objfile);
|
| - need_symtab_cleanup = 1;
|
| - }
|
| - else if (vp->bfd != exec_bfd)
|
| - /* FIXME-leak: We should be freeing vp->name too, I think. */
|
| - gdb_bfd_close_or_warn (vp->bfd);
|
| -
|
| - xfree (vp);
|
| - }
|
| -
|
| - vmap = NULL;
|
| -
|
| {
|
| struct program_space *ss;
|
| struct cleanup *old_chain;
|
| @@ -211,7 +182,7 @@ exec_file_attach (char *filename, int from_tty)
|
| else
|
| {
|
| struct cleanup *cleanups;
|
| - char *scratch_pathname;
|
| + char *scratch_pathname, *canonical_pathname;
|
| int scratch_chan;
|
| struct target_section *sections = NULL, *sections_end = NULL;
|
| char **matching;
|
| @@ -232,9 +203,19 @@ exec_file_attach (char *filename, int from_tty)
|
| #endif
|
| if (scratch_chan < 0)
|
| perror_with_name (filename);
|
| - exec_bfd = bfd_fopen (scratch_pathname, gnutarget,
|
| - write_files ? FOPEN_RUB : FOPEN_RB,
|
| - scratch_chan);
|
| +
|
| + cleanups = make_cleanup (xfree, scratch_pathname);
|
| +
|
| + /* gdb_bfd_open (and its variants) prefers canonicalized pathname for
|
| + better BFD caching. */
|
| + canonical_pathname = gdb_realpath (scratch_pathname);
|
| + make_cleanup (xfree, canonical_pathname);
|
| +
|
| + if (write_files)
|
| + exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget,
|
| + FOPEN_RUB, scratch_chan);
|
| + else
|
| + exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
|
|
|
| if (!exec_bfd)
|
| {
|
| @@ -242,12 +223,8 @@ exec_file_attach (char *filename, int from_tty)
|
| scratch_pathname, bfd_errmsg (bfd_get_error ()));
|
| }
|
|
|
| - /* At this point, scratch_pathname and exec_bfd->name both point to the
|
| - same malloc'd string. However exec_close() will attempt to free it
|
| - via the exec_bfd->name pointer, so we need to make another copy and
|
| - leave exec_bfd as the new owner of the original copy. */
|
| - scratch_pathname = xstrdup (scratch_pathname);
|
| - cleanups = make_cleanup (xfree, scratch_pathname);
|
| + gdb_assert (exec_filename == NULL);
|
| + exec_filename = gdb_realpath_keepfile (scratch_pathname);
|
|
|
| if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching))
|
| {
|
| @@ -259,22 +236,6 @@ exec_file_attach (char *filename, int from_tty)
|
| gdb_bfd_errmsg (bfd_get_error (), matching));
|
| }
|
|
|
| - /* FIXME - This should only be run for RS6000, but the ifdef is a poor
|
| - way to accomplish. */
|
| -#ifdef DEPRECATED_IBM6000_TARGET
|
| - /* Setup initial vmap. */
|
| -
|
| - map_vmap (exec_bfd, 0);
|
| - if (vmap == NULL)
|
| - {
|
| - /* 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 ()));
|
| - }
|
| -#endif /* DEPRECATED_IBM6000_TARGET */
|
| -
|
| if (build_section_table (exec_bfd, §ions, §ions_end))
|
| {
|
| /* Make sure to close exec_bfd, or else "run" might try to use
|
| @@ -293,7 +254,7 @@ exec_file_attach (char *filename, int from_tty)
|
| /* Add the executable's sections to the current address spaces'
|
| list of sections. This possibly pushes the exec_ops
|
| target. */
|
| - add_target_sections (sections, sections_end);
|
| + add_target_sections (&exec_bfd, sections, sections_end);
|
| xfree (sections);
|
|
|
| /* Tell display code (if any) about the changed file name. */
|
| @@ -378,6 +339,8 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
|
| struct target_section **table_pp = (struct target_section **) table_pp_char;
|
| flagword aflag;
|
|
|
| + gdb_assert (abfd == asect->owner);
|
| +
|
| /* Check the section flags, but do not discard zero-length sections, since
|
| some symbols may still be attached to this section. For instance, we
|
| encountered on sparc-solaris 2.10 a shared library with an empty .bss
|
| @@ -387,7 +350,7 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
|
| if (!(aflag & SEC_ALLOC))
|
| return;
|
|
|
| - (*table_pp)->bfd = abfd;
|
| + (*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);
|
| @@ -397,11 +360,9 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
|
| int
|
| resize_section_table (struct target_section_table *table, int num_added)
|
| {
|
| - struct target_section *old_value;
|
| int old_count;
|
| int new_count;
|
|
|
| - old_value = table->sections;
|
| old_count = table->sections_end - table->sections;
|
|
|
| new_count = num_added + old_count;
|
| @@ -447,7 +408,8 @@ build_section_table (struct bfd *some_bfd, struct target_section **start,
|
| current set of target sections. */
|
|
|
| void
|
| -add_target_sections (struct target_section *sections,
|
| +add_target_sections (void *owner,
|
| + struct target_section *sections,
|
| struct target_section *sections_end)
|
| {
|
| int count;
|
| @@ -458,9 +420,13 @@ add_target_sections (struct target_section *sections,
|
| if (count > 0)
|
| {
|
| int space = resize_section_table (table, count);
|
| + int i;
|
|
|
| - memcpy (table->sections + space,
|
| - sections, count * sizeof (sections[0]));
|
| + for (i = 0; i < count; ++i)
|
| + {
|
| + table->sections[space + i] = sections[i];
|
| + table->sections[space + i].owner = owner;
|
| + }
|
|
|
| /* If these are the first file sections we can provide memory
|
| from, push the file_stratum target. */
|
| @@ -472,17 +438,65 @@ add_target_sections (struct target_section *sections,
|
| }
|
| }
|
|
|
| -/* Remove all target sections taken from ABFD. */
|
| +/* Add the sections of OBJFILE to the current set of target sections. */
|
| +
|
| +void
|
| +add_target_sections_of_objfile (struct objfile *objfile)
|
| +{
|
| + struct target_section_table *table = current_target_sections;
|
| + struct obj_section *osect;
|
| + int space;
|
| + unsigned count = 0;
|
| + struct target_section *ts;
|
| +
|
| + if (objfile == NULL)
|
| + return;
|
| +
|
| + /* Compute the number of sections to add. */
|
| + ALL_OBJFILE_OSECTIONS (objfile, osect)
|
| + {
|
| + if (bfd_get_section_size (osect->the_bfd_section) == 0)
|
| + continue;
|
| + count++;
|
| + }
|
| +
|
| + if (count == 0)
|
| + return;
|
| +
|
| + space = resize_section_table (table, count);
|
| +
|
| + ts = table->sections + space;
|
| +
|
| + ALL_OBJFILE_OSECTIONS (objfile, osect)
|
| + {
|
| + if (bfd_get_section_size (osect->the_bfd_section) == 0)
|
| + continue;
|
| +
|
| + gdb_assert (ts < table->sections + space + count);
|
| +
|
| + ts->addr = obj_section_addr (osect);
|
| + ts->endaddr = obj_section_endaddr (osect);
|
| + ts->the_bfd_section = osect->the_bfd_section;
|
| + ts->owner = (void *) objfile;
|
| +
|
| + ts++;
|
| + }
|
| +}
|
| +
|
| +/* Remove all target sections owned by OWNER.
|
| + OWNER must be the same value passed to add_target_sections. */
|
|
|
| void
|
| -remove_target_sections (bfd *abfd)
|
| +remove_target_sections (void *owner)
|
| {
|
| struct target_section *src, *dest;
|
| struct target_section_table *table = current_target_sections;
|
|
|
| + gdb_assert (owner != NULL);
|
| +
|
| dest = table->sections;
|
| for (src = table->sections; src < table->sections_end; src++)
|
| - if (src->bfd != abfd)
|
| + if (src->owner != owner)
|
| {
|
| /* Keep this section. */
|
| if (dest < src)
|
| @@ -514,61 +528,6 @@ remove_target_sections (bfd *abfd)
|
| }
|
|
|
|
|
| -static void
|
| -bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
|
| -{
|
| - struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3;
|
| - struct vmap *vp;
|
| -
|
| - vp = vmap_bfd->pvmap;
|
| -
|
| - if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
|
| - return;
|
| -
|
| - if (strcmp (bfd_section_name (abfd, sect), ".text") == 0)
|
| - {
|
| - vp->tstart = bfd_section_vma (abfd, sect);
|
| - vp->tend = vp->tstart + bfd_section_size (abfd, sect);
|
| - vp->tvma = bfd_section_vma (abfd, sect);
|
| - vp->toffs = sect->filepos;
|
| - }
|
| - else if (strcmp (bfd_section_name (abfd, sect), ".data") == 0)
|
| - {
|
| - vp->dstart = bfd_section_vma (abfd, sect);
|
| - vp->dend = vp->dstart + bfd_section_size (abfd, sect);
|
| - vp->dvma = bfd_section_vma (abfd, sect);
|
| - }
|
| - /* Silently ignore other types of sections. (FIXME?) */
|
| -}
|
| -
|
| -/* Make a vmap for ABFD which might be a member of the archive ARCH.
|
| - Return the new vmap. */
|
| -
|
| -struct vmap *
|
| -map_vmap (bfd *abfd, bfd *arch)
|
| -{
|
| - struct vmap_and_bfd vmap_bfd;
|
| - struct vmap *vp, **vpp;
|
| -
|
| - vp = (struct vmap *) xmalloc (sizeof (*vp));
|
| - memset ((char *) vp, '\0', sizeof (*vp));
|
| - vp->nxt = 0;
|
| - vp->bfd = abfd;
|
| - vp->name = bfd_get_filename (arch ? arch : abfd);
|
| - vp->member = arch ? bfd_get_filename (abfd) : "";
|
| -
|
| - vmap_bfd.pbfd = arch;
|
| - vmap_bfd.pvmap = vp;
|
| - bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd);
|
| -
|
| - /* Find the end of the list and append. */
|
| - for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt)
|
| - ;
|
| - *vpp = vp;
|
| -
|
| - return vp;
|
| -}
|
| -
|
|
|
| VEC(mem_range_s) *
|
| section_table_available_memory (VEC(mem_range_s) *memory,
|
| @@ -580,7 +539,8 @@ section_table_available_memory (VEC(mem_range_s) *memory,
|
|
|
| for (p = sections; p < sections_end; p++)
|
| {
|
| - if ((bfd_get_section_flags (p->bfd, p->the_bfd_section)
|
| + if ((bfd_get_section_flags (p->the_bfd_section->owner,
|
| + p->the_bfd_section)
|
| & SEC_READONLY) == 0)
|
| continue;
|
|
|
| @@ -624,7 +584,10 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
|
|
|
| for (p = sections; p < sections_end; p++)
|
| {
|
| - if (section_name && strcmp (section_name, p->the_bfd_section->name) != 0)
|
| + struct bfd_section *asect = p->the_bfd_section;
|
| + bfd *abfd = asect->owner;
|
| +
|
| + if (section_name && strcmp (section_name, asect->name) != 0)
|
| continue; /* not the section we need. */
|
| if (memaddr >= p->addr)
|
| {
|
| @@ -632,11 +595,11 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
|
| {
|
| /* Entire transfer is within this section. */
|
| if (writebuf)
|
| - res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
| + res = bfd_set_section_contents (abfd, asect,
|
| writebuf, memaddr - p->addr,
|
| len);
|
| else
|
| - res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
| + res = bfd_get_section_contents (abfd, asect,
|
| readbuf, memaddr - p->addr,
|
| len);
|
| return (res != 0) ? len : 0;
|
| @@ -651,11 +614,11 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
|
| /* This section overlaps the transfer. Just do half. */
|
| len = p->endaddr - memaddr;
|
| if (writebuf)
|
| - res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
|
| + res = bfd_set_section_contents (abfd, asect,
|
| writebuf, memaddr - p->addr,
|
| len);
|
| else
|
| - res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
|
| + res = bfd_get_section_contents (abfd, asect,
|
| readbuf, memaddr - p->addr,
|
| len);
|
| return (res != 0) ? len : 0;
|
| @@ -711,17 +674,18 @@ print_section_info (struct target_section_table *t, bfd *abfd)
|
|
|
| for (p = t->sections; p < t->sections_end; p++)
|
| {
|
| - asection *asect = p->the_bfd_section;
|
| + struct bfd_section *psect = p->the_bfd_section;
|
| + bfd *pbfd = psect->owner;
|
|
|
| - if ((bfd_get_section_flags (abfd, asect) & (SEC_ALLOC | SEC_LOAD))
|
| + if ((bfd_get_section_flags (pbfd, psect) & (SEC_ALLOC | SEC_LOAD))
|
| != (SEC_ALLOC | SEC_LOAD))
|
| continue;
|
|
|
| - if (bfd_get_section_vma (abfd, asect) <= abfd->start_address
|
| - && abfd->start_address < (bfd_get_section_vma (abfd, asect)
|
| - + bfd_get_section_size (asect)))
|
| + if (bfd_get_section_vma (pbfd, psect) <= abfd->start_address
|
| + && abfd->start_address < (bfd_get_section_vma (pbfd, psect)
|
| + + bfd_get_section_size (psect)))
|
| {
|
| - displacement = p->addr - bfd_get_section_vma (abfd, asect);
|
| + displacement = p->addr - bfd_get_section_vma (pbfd, psect);
|
| break;
|
| }
|
| }
|
| @@ -737,6 +701,9 @@ 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;
|
| +
|
| printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
|
| printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
|
|
|
| @@ -748,11 +715,10 @@ print_section_info (struct target_section_table *t, bfd *abfd)
|
| /* FIXME: i18n: Need to rewrite this sentence. */
|
| if (info_verbose)
|
| printf_filtered (" @ %s",
|
| - hex_string_custom (p->the_bfd_section->filepos, 8));
|
| - printf_filtered (" is %s", bfd_section_name (p->bfd,
|
| - p->the_bfd_section));
|
| - if (p->bfd != abfd)
|
| - printf_filtered (" in %s", bfd_get_filename (p->bfd));
|
| + hex_string_custom (psect->filepos, 8));
|
| + printf_filtered (" is %s", bfd_section_name (pbfd, psect));
|
| + if (pbfd != abfd)
|
| + printf_filtered (" in %s", bfd_get_filename (pbfd));
|
| printf_filtered ("\n");
|
| }
|
| }
|
| @@ -764,31 +730,6 @@ exec_files_info (struct target_ops *t)
|
| print_section_info (current_target_sections, exec_bfd);
|
| else
|
| puts_filtered (_("\t<no file loaded>\n"));
|
| -
|
| - if (vmap)
|
| - {
|
| - int addr_size = gdbarch_addr_bit (target_gdbarch) / 8;
|
| - struct vmap *vp;
|
| -
|
| - printf_unfiltered (_("\tMapping info for file `%s'.\n"), vmap->name);
|
| - printf_unfiltered ("\t %*s %*s %*s %*s %8.8s %s\n",
|
| - addr_size * 2, "tstart",
|
| - addr_size * 2, "tend",
|
| - addr_size * 2, "dstart",
|
| - addr_size * 2, "dend",
|
| - "section",
|
| - "file(member)");
|
| -
|
| - for (vp = vmap; vp; vp = vp->nxt)
|
| - printf_unfiltered ("\t0x%s 0x%s 0x%s 0x%s %s%s%s%s\n",
|
| - phex (vp->tstart, addr_size),
|
| - phex (vp->tend, addr_size),
|
| - phex (vp->dstart, addr_size),
|
| - phex (vp->dend, addr_size),
|
| - vp->name,
|
| - *vp->member ? "(" : "", vp->member,
|
| - *vp->member ? ")" : "");
|
| - }
|
| }
|
|
|
| static void
|
| @@ -846,7 +787,7 @@ 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->bfd->filename) == 0
|
| + if (filename_cmp (filename, p->the_bfd_section->owner->filename) == 0
|
| && index == p->the_bfd_section->index)
|
| {
|
| p->endaddr += address - p->addr;
|
| @@ -949,7 +890,7 @@ Show writing into executable and core files."), NULL,
|
| show_write_files,
|
| &setlist, &showlist);
|
|
|
| - add_target (&exec_ops);
|
| + add_target_with_completer (&exec_ops, filename_completer);
|
| }
|
|
|
| static char *
|
|
|