/* Work with executable files, for GDB.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009
+ 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GDB.
#include "exec.h"
#include "observer.h"
#include "arch-utils.h"
+#include "gdbthread.h"
+#include "progspace.h"
#include <fcntl.h>
#include "readline/readline.h"
/* Prototypes for local functions */
-static void exec_close (int);
-
static void file_command (char *, int);
static void set_section_command (char *, int);
struct target_ops exec_ops;
-/* The Binary File Descriptor handle for the executable file. */
-
-bfd *exec_bfd = NULL;
-long exec_bfd_mtime = 0;
-
-/* GDB currently only supports a single symbol/address space for the
- whole debug session. When that limitation is lifted, this global
- goes away. */
-static struct target_section_table current_target_sections_1;
-
-/* The set of target sections matching the sections mapped into the
- current inferior's address space. */
-static struct target_section_table *current_target_sections
- = ¤t_target_sections_1;
+/* True if the exec target is pushed on the stack. */
+static int using_exec_ops;
/* Whether to open exec and core files read-only or read-write. */
/* Close and clear exec_bfd. If we end up with no target sections to
read memory from, this unpushes the exec_ops target. */
-static void
-exec_close_1 (void)
+void
+exec_close (void)
{
if (exec_bfd)
{
bfd *abfd = exec_bfd;
char *name = bfd_get_filename (abfd);
- if (!bfd_close (abfd))
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
+ gdb_bfd_close_or_warn (abfd);
xfree (name);
/* Removing target sections may close the exec_ops target.
}
}
+/* This is the target_close implementation. Clears all target
+ sections and closes all executable bfds from all program spaces. */
+
static void
-exec_close (int quitting)
+exec_close_1 (int quitting)
{
int need_symtab_cleanup = 0;
struct vmap *vp, *nxt;
+ using_exec_ops = 0;
+
for (nxt = vmap; nxt != NULL;)
{
vp = nxt;
}
else if (vp->bfd != exec_bfd)
/* FIXME-leak: We should be freeing vp->name too, I think. */
- if (!bfd_close (vp->bfd))
- warning (_("cannot close \"%s\": %s"),
- vp->name, bfd_errmsg (bfd_get_error ()));
-
- /* FIXME: This routine is #if 0'd in symfile.c. What should we
- be doing here? Should we just free everything in
- vp->objfile->symtabs? Should free_objfile do that?
- FIXME-as-well: free_objfile already free'd vp->name, so it isn't
- valid here. */
- free_named_symtabs (vp->name);
+ gdb_bfd_close_or_warn (vp->bfd);
+
xfree (vp);
}
vmap = NULL;
- /* Delete all target sections. */
- resize_section_table
- (current_target_sections,
- -resize_section_table (current_target_sections, 0));
+ {
+ struct program_space *ss;
+ struct cleanup *old_chain;
- /* Remove exec file. */
- exec_close_1 ();
+ old_chain = save_current_program_space ();
+ ALL_PSPACES (ss)
+ {
+ set_current_program_space (ss);
+
+ /* Delete all target sections. */
+ resize_section_table
+ (current_target_sections,
+ -resize_section_table (current_target_sections, 0));
+
+ exec_close ();
+ }
+
+ do_cleanups (old_chain);
+ }
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
- exec_close_1 ();
+ exec_close ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
exec_file_attach (char *filename, int from_tty)
{
/* Remove any previous exec file. */
- exec_close_1 ();
+ exec_close ();
/* Now open and digest the file the user requested, if any. */
char *scratch_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,
if (scratch_chan < 0)
{
char *exename = 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 = xstrdup (scratch_pathname);
cleanups = make_cleanup (xfree, scratch_pathname);
- if (!bfd_check_format (exec_bfd, bfd_object))
+ 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_1 ();
+ exec_close ();
error (_("\"%s\": not in executable format: %s"),
- scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ scratch_pathname,
+ gdb_bfd_errmsg (bfd_get_error (), matching));
}
/* FIXME - This should only be run for RS6000, but the ifdef is a poor
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close_1 ();
+ exec_close ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close_1 ();
+ exec_close ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
set_gdbarch_from_file (exec_bfd);
/* Add the executable's sections to the current address spaces'
- list of sections. */
+ list of sections. This possibly pushes the exec_ops
+ target. */
add_target_sections (sections, sections_end);
xfree (sections);
if (count > 0)
{
int space = resize_section_table (table, count);
+
memcpy (table->sections + space,
sections, count * sizeof (sections[0]));
/* If these are the first file sections we can provide memory
from, push the file_stratum target. */
- if (space == 0)
- push_target (&exec_ops);
+ if (!using_exec_ops)
+ {
+ using_exec_ops = 1;
+ push_target (&exec_ops);
+ }
}
}
remove_target_sections (bfd *abfd)
{
struct target_section *src, *dest;
-
struct target_section_table *table = current_target_sections;
dest = table->sections;
/* If we don't have any more sections to read memory from,
remove the file_stratum target from the stack. */
if (old_count + (dest - src) == 0)
- unpush_target (&exec_ops);
+ {
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ if (pspace->target_sections.sections
+ != pspace->target_sections.sections_end)
+ return;
+
+ unpush_target (&exec_ops);
+ }
}
}
return vp;
}
\f
-/* Read or write from BFD executable files.
-
- MEMADDR is an address within the target address space, MYADDR is an
- address within GDB address-space where data is written to, LEN is
- length of buffer, and WRITE indicates whether to read or write.
- SECTIONS and SECTIONS_END defines a section table holding sections
- from possibly multiple BFDs.
-
- If SECTION_NAME is not NULL, only access sections with that same
- name.
-
- Result is a length:
-
- 0: We cannot handle this address and length.
- > 0: We have handled N bytes starting at this address.
- (If N == length, we did it all.) We might be able
- to handle more bytes beyond this length, but no
- promises.
- < 0: We cannot handle this address, but if somebody
- else handles (-N) bytes, we can start from there. */
int
section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
if (len <= 0)
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
-
for (p = sections; p < sections_end; p++)
{
if (section_name && strcmp (section_name, p->the_bfd_section->name) != 0)
void
print_section_info (struct target_section_table *t, bfd *abfd)
{
+ struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
struct target_section *p;
/* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64. */
- int wid = gdbarch_addr_bit (gdbarch_from_bfd (abfd)) <= 32 ? 8 : 16;
+ int wid = gdbarch_addr_bit (gdbarch) <= 32 ? 8 : 16;
printf_filtered ("\t`%s', ", bfd_get_filename (abfd));
wrap_here (" ");
printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
if (abfd == exec_bfd)
- printf_filtered (_("\tEntry point: %s\n"),
- paddress (bfd_get_start_address (abfd)));
+ {
+ /* gcc-3.4 does not like the initialization in <p == t->sections_end>. */
+ bfd_vma displacement = 0;
+ bfd_vma entry_point;
+
+ for (p = t->sections; p < t->sections_end; p++)
+ {
+ asection *asect = p->the_bfd_section;
+
+ if ((bfd_get_section_flags (abfd, asect) & (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)))
+ {
+ displacement = p->addr - bfd_get_section_vma (abfd, asect);
+ break;
+ }
+ }
+ if (p == t->sections_end)
+ warning (_("Cannot find section for the entry point of %s.\n"),
+ bfd_get_filename (abfd));
+
+ entry_point = gdbarch_addr_bits_remove (gdbarch,
+ bfd_get_start_address (abfd)
+ + displacement);
+ printf_filtered (_("\tEntry point: %s\n"),
+ paddress (gdbarch, entry_point));
+ }
for (p = t->sections; p < t->sections_end; p++)
{
printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
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",
- strlen_paddr (), "tstart",
- strlen_paddr (), "tend",
- strlen_paddr (), "dstart",
- strlen_paddr (), "dend",
+ 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",
- paddr (vp->tstart),
- paddr (vp->tend),
- paddr (vp->dstart),
- paddr (vp->dend),
+ 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 ? ")" : "");
breakpoint_init_inferior). */
static int
-ignore (struct bp_target_info *bp_tgt)
+ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
{
return 0;
}
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;
+ exec_ops.to_close = exec_close_1;
exec_ops.to_attach = find_default_attach;
exec_ops.to_xfer_partial = exec_xfer_partial;
exec_ops.to_get_section_table = exec_get_section_table;