X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fexec.c;h=4358aca52a1718d564a513bfa9b4e160fa3e89d9;hb=4ee62156d969867d3d3ffedf656a74643f77279e;hp=e8e5f3be0094fd0b776a1d6b80303eda6f4e3ebf;hpb=5bf193a2eedab2cf1437c762fee2cfc8249753a0;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/exec.c b/gdb/exec.c
index e8e5f3be00..4358aca52a 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -1,14 +1,14 @@
/* Work with executable files, for GDB.
- Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
- Inc.
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see . */
#include "defs.h"
#include "frame.h"
@@ -32,6 +30,10 @@
#include "completer.h"
#include "value.h"
#include "exec.h"
+#include "observer.h"
+#include "arch-utils.h"
+#include "gdbthread.h"
+#include "progspace.h"
#include
#include "readline/readline.h"
@@ -41,9 +43,6 @@
#include
#include "gdb_stat.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
#include "xcoffsolib.h"
@@ -53,16 +52,12 @@ void (*deprecated_file_changed_hook) (char *);
/* Prototypes for local functions */
-static void exec_close (int);
-
static void file_command (char *, int);
static void set_section_command (char *, int);
static void exec_files_info (struct target_ops *);
-static int ignore (CORE_ADDR, char *);
-
static void init_exec_ops (void);
void _initialize_exec (void);
@@ -71,29 +66,66 @@ void _initialize_exec (void);
struct target_ops exec_ops;
-/* The Binary File Descriptor handle for the executable file. */
-
-bfd *exec_bfd = NULL;
+/* 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. */
int write_files = 0;
+static void
+show_write_files (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Writing into executable and core files is %s.\n"),
+ value);
+}
+
struct vmap *vmap;
-void
+static void
exec_open (char *args, int from_tty)
{
target_preopen (from_tty);
exec_file_attach (args, from_tty);
}
+/* Close and clear exec_bfd. If we end up with no target sections to
+ read memory from, this unpushes the exec_ops target. */
+
+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 ()));
+ xfree (name);
+
+ /* 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);
+ }
+}
+
+/* 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;
@@ -124,36 +156,38 @@ exec_close (int quitting)
vmap = NULL;
- if (exec_bfd)
+ {
+ struct program_space *ss;
+ struct cleanup *old_chain;
+
+ old_chain = save_current_program_space ();
+ ALL_PSPACES (ss)
{
- char *name = bfd_get_filename (exec_bfd);
+ set_current_program_space (ss);
- if (!bfd_close (exec_bfd))
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
- xfree (name);
- exec_bfd = NULL;
- }
+ /* Delete all target sections. */
+ resize_section_table
+ (current_target_sections,
+ -resize_section_table (current_target_sections, 0));
- if (exec_ops.to_sections)
- {
- xfree (exec_ops.to_sections);
- exec_ops.to_sections = NULL;
- exec_ops.to_sections_end = NULL;
+ exec_close ();
}
+
+ do_cleanups (old_chain);
+ }
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
- unpush_target (&exec_ops);
+ exec_close ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
}
-/* Process the first arg in ARGS as the new exec file.
+/* Set FILENAME as the new exec file.
This function is intended to be behave essentially the same
as exec_file_command, except that the latter will detect when
@@ -168,15 +202,13 @@ exec_file_clear (int from_tty)
given a pid but not a exec pathname, and the attach command could
figure out the pathname from the pid. (In this case, we shouldn't
ask the user whether the current target should be shut down --
- we're supplying the exec pathname late for good reason.)
-
- ARGS is assumed to be the filename. */
+ we're supplying the exec pathname late for good reason.) */
void
exec_file_attach (char *filename, int from_tty)
{
/* Remove any previous exec file. */
- unpush_target (&exec_ops);
+ exec_close ();
/* Now open and digest the file the user requested, if any. */
@@ -184,14 +216,18 @@ exec_file_attach (char *filename, int from_tty)
{
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
+
+ set_gdbarch_from_file (NULL);
}
else
{
+ struct cleanup *cleanups;
char *scratch_pathname;
int scratch_chan;
+ struct target_section *sections = NULL, *sections_end = NULL;
scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
- write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
+ write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
&scratch_pathname);
#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
if (scratch_chan < 0)
@@ -199,30 +235,35 @@ exec_file_attach (char *filename, int from_tty)
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, 0,
+ write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
&scratch_pathname);
}
#endif
if (scratch_chan < 0)
perror_with_name (filename);
- exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+ exec_bfd = bfd_fopen (scratch_pathname, gnutarget,
+ write_files ? FOPEN_RUB : FOPEN_RB,
+ scratch_chan);
if (!exec_bfd)
- error (_("\"%s\": could not open as an executable file: %s"),
- scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ {
+ close (scratch_chan);
+ error (_("\"%s\": could not open as an executable file: %s"),
+ 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);
- make_cleanup (xfree, scratch_pathname);
+ cleanups = make_cleanup (xfree, scratch_pathname);
if (!bfd_check_format (exec_bfd, bfd_object))
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close ();
error (_("\"%s\": not in executable format: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
@@ -237,37 +278,41 @@ exec_file_attach (char *filename, int from_tty)
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ 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, &exec_ops.to_sections,
- &exec_ops.to_sections_end))
+ if (build_section_table (exec_bfd, §ions, §ions_end))
{
/* Make sure to close exec_bfd, or else "run" might try to use
it. */
- exec_close (0);
+ exec_close ();
error (_("\"%s\": can't find the file sections: %s"),
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
-#ifdef DEPRECATED_HPUX_TEXT_END
- DEPRECATED_HPUX_TEXT_END (&exec_ops);
-#endif
+ exec_bfd_mtime = bfd_get_mtime (exec_bfd);
validate_files ();
set_gdbarch_from_file (exec_bfd);
- push_target (&exec_ops);
+ /* 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);
+ xfree (sections);
/* Tell display code (if any) about the changed file name. */
if (deprecated_exec_file_display_hook)
(*deprecated_exec_file_display_hook) (filename);
+
+ do_cleanups (cleanups);
}
bfd_cache_close_all ();
+ observer_notify_executable_changed ();
}
/* Process the first arg in ARGS as the new exec file.
@@ -283,19 +328,21 @@ exec_file_command (char *args, int from_tty)
{
char **argv;
char *filename;
-
- target_preopen (from_tty);
+
+ if (from_tty && target_has_execution
+ && !query (_("A program is being debugged already.\n"
+ "Are you sure you want to change the file? ")))
+ error (_("File not changed."));
if (args)
{
+ struct cleanup *cleanups;
+
/* Scan through the args and pick up the first non option arg
as the filename. */
- argv = buildargv (args);
- if (argv == NULL)
- nomem (0);
-
- make_cleanup_freeargv (argv);
+ argv = gdb_buildargv (args);
+ cleanups = make_cleanup_freeargv (argv);
for (; (*argv != NULL) && (**argv == '-'); argv++)
{;
@@ -306,6 +353,8 @@ exec_file_command (char *args, int from_tty)
filename = tilde_expand (*argv);
make_cleanup (xfree, filename);
exec_file_attach (filename, from_tty);
+
+ do_cleanups (cleanups);
}
else
exec_file_attach (NULL, from_tty);
@@ -335,14 +384,18 @@ static void
add_to_section_table (bfd *abfd, struct bfd_section *asect,
void *table_pp_char)
{
- struct section_table **table_pp = (struct section_table **) table_pp_char;
+ struct target_section **table_pp = (struct target_section **) table_pp_char;
flagword aflag;
+ /* 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
+ 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);
if (!(aflag & SEC_ALLOC))
return;
- if (0 == bfd_section_size (abfd, asect))
- return;
+
(*table_pp)->bfd = abfd;
(*table_pp)->the_bfd_section = asect;
(*table_pp)->addr = bfd_section_vma (abfd, asect);
@@ -350,19 +403,46 @@ add_to_section_table (bfd *abfd, struct bfd_section *asect,
(*table_pp)++;
}
+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;
+
+ if (new_count)
+ {
+ table->sections = xrealloc (table->sections,
+ sizeof (struct target_section) * new_count);
+ table->sections_end = table->sections + new_count;
+ }
+ else
+ {
+ xfree (table->sections);
+ table->sections = table->sections_end = NULL;
+ }
+
+ return old_count;
+}
+
/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
Returns 0 if OK, 1 on error. */
int
-build_section_table (struct bfd *some_bfd, struct section_table **start,
- struct section_table **end)
+build_section_table (struct bfd *some_bfd, struct target_section **start,
+ struct target_section **end)
{
unsigned count;
count = bfd_count_sections (some_bfd);
if (*start)
xfree (* start);
- *start = (struct section_table *) xmalloc (count * sizeof (**start));
+ *start = (struct target_section *) xmalloc (count * sizeof (**start));
*end = *start;
bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end);
if (*end > *start + count)
@@ -370,6 +450,77 @@ build_section_table (struct bfd *some_bfd, struct section_table **start,
/* We could realloc the table, but it probably loses for most files. */
return 0;
}
+
+/* Add the sections array defined by [SECTIONS..SECTIONS_END[ to the
+ current set of target sections. */
+
+void
+add_target_sections (struct target_section *sections,
+ struct target_section *sections_end)
+{
+ int count;
+ struct target_section_table *table = current_target_sections;
+
+ count = sections_end - 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 (!using_exec_ops)
+ {
+ using_exec_ops = 1;
+ push_target (&exec_ops);
+ }
+ }
+}
+
+/* Remove all target sections taken from ABFD. */
+
+void
+remove_target_sections (bfd *abfd)
+{
+ struct target_section *src, *dest;
+
+ struct target_section_table *table = current_target_sections;
+
+ dest = table->sections;
+ for (src = table->sections; src < table->sections_end; src++)
+ if (src->bfd != abfd)
+ {
+ /* Keep this section. */
+ if (dest < src)
+ *dest = *src;
+ dest++;
+ }
+
+ /* If we've dropped any sections, resize the section table. */
+ if (dest < src)
+ {
+ int old_count;
+
+ 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. */
+ if (old_count + (dest - src) == 0)
+ {
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ if (pspace->target_sections.sections
+ != pspace->target_sections.sections_end)
+ return;
+
+ unpush_target (&exec_ops);
+ }
+ }
+}
+
static void
bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
@@ -382,14 +533,14 @@ bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
return;
- if (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".text"))
+ 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 (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".data"))
+ 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);
@@ -426,64 +577,38 @@ map_vmap (bfd *abfd, bfd *arch)
return vp;
}
-/* Read or write the exec file.
-
- Args are address within a BFD file, address within gdb address-space,
- length, and a flag indicating whether to read or write.
-
- 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.
-
- The same routine is used to handle both core and exec files;
- we just tail-call it with more arguments to select between them. */
int
-xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
- struct mem_attrib *attrib,
- struct target_ops *target)
+section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len,
+ struct target_section *sections,
+ struct target_section *sections_end,
+ const char *section_name)
{
int res;
- struct section_table *p;
- CORE_ADDR nextsectaddr, memend;
- asection *section = NULL;
+ struct target_section *p;
+ ULONGEST memaddr = offset;
+ ULONGEST memend = memaddr + len;
if (len <= 0)
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
- if (overlay_debugging)
+ for (p = sections; p < sections_end; p++)
{
- section = find_pc_overlay (memaddr);
- if (pc_in_unmapped_range (memaddr, section))
- memaddr = overlay_mapped_address (memaddr, section);
- }
-
- memend = memaddr + len;
- nextsectaddr = memend;
-
- for (p = target->to_sections; p < target->to_sections_end; p++)
- {
- if (overlay_debugging && section && p->the_bfd_section &&
- strcmp (section->name, p->the_bfd_section->name) != 0)
+ if (section_name && strcmp (section_name, p->the_bfd_section->name) != 0)
continue; /* not the section we need */
if (memaddr >= p->addr)
{
if (memend <= p->endaddr)
{
/* Entire transfer is within this section. */
- if (write)
+ if (writebuf)
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ writebuf, memaddr - p->addr,
len);
else
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ readbuf, memaddr - p->addr,
len);
return (res != 0) ? len : 0;
}
@@ -496,45 +621,62 @@ xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
{
/* This section overlaps the transfer. Just do half. */
len = p->endaddr - memaddr;
- if (write)
+ if (writebuf)
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ writebuf, memaddr - p->addr,
len);
else
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ readbuf, memaddr - p->addr,
len);
return (res != 0) ? len : 0;
}
}
- else
- nextsectaddr = min (nextsectaddr, p->addr);
}
- if (nextsectaddr >= memend)
- return 0; /* We can't help */
+ return 0; /* We can't help */
+}
+
+struct target_section_table *
+exec_get_section_table (struct target_ops *ops)
+{
+ return current_target_sections;
+}
+
+static LONGEST
+exec_xfer_partial (struct target_ops *ops, enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ struct target_section_table *table = target_get_section_table (ops);
+
+ if (object == TARGET_OBJECT_MEMORY)
+ return section_table_xfer_memory_partial (readbuf, writebuf,
+ offset, len,
+ table->sections,
+ table->sections_end,
+ NULL);
else
- return -(nextsectaddr - memaddr); /* Next boundary where we can help */
+ return -1;
}
void
-print_section_info (struct target_ops *t, bfd *abfd)
+print_section_info (struct target_section_table *t, bfd *abfd)
{
- struct section_table *p;
- /* FIXME: 16 is not wide enough when TARGET_ADDR_BIT > 64. */
- int wid = TARGET_ADDR_BIT <= 32 ? 8 : 16;
+ 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) <= 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: "));
- deprecated_print_address_numeric (bfd_get_start_address (abfd), 1, gdb_stdout);
- printf_filtered ("\n");
- }
- for (p = t->to_sections; p < t->to_sections_end; p++)
+ printf_filtered (_("\tEntry point: %s\n"),
+ paddress (gdbarch, bfd_get_start_address (abfd)));
+ for (p = t->sections; p < t->sections_end; p++)
{
printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
@@ -558,78 +700,44 @@ print_section_info (struct target_ops *t, bfd *abfd)
static void
exec_files_info (struct target_ops *t)
{
- print_section_info (t, exec_bfd);
+ print_section_info (current_target_sections, exec_bfd);
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 ? ")" : "");
}
}
-/* msnyder 5/21/99:
- exec_set_section_offsets sets the offsets of all the sections
- in the exec objfile. */
-
-void
-exec_set_section_offsets (bfd_signed_vma text_off, bfd_signed_vma data_off,
- bfd_signed_vma bss_off)
-{
- struct section_table *sect;
-
- for (sect = exec_ops.to_sections;
- sect < exec_ops.to_sections_end;
- sect++)
- {
- flagword flags;
-
- flags = bfd_get_section_flags (exec_bfd, sect->the_bfd_section);
-
- if (flags & SEC_CODE)
- {
- sect->addr += text_off;
- sect->endaddr += text_off;
- }
- else if (flags & (SEC_DATA | SEC_LOAD))
- {
- sect->addr += data_off;
- sect->endaddr += data_off;
- }
- else if (flags & SEC_ALLOC)
- {
- sect->addr += bss_off;
- sect->endaddr += bss_off;
- }
- }
-}
-
static void
set_section_command (char *args, int from_tty)
{
- struct section_table *p;
+ struct target_section *p;
char *secname;
unsigned seclen;
unsigned long secaddr;
char secprint[100];
long offset;
+ struct target_section_table *table;
if (args == 0)
error (_("Must specify section name and its virtual address"));
@@ -641,7 +749,8 @@ set_section_command (char *args, int from_tty)
/* Parse out new virtual address */
secaddr = parse_and_eval_address (args);
- for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
+ table = current_target_sections;
+ for (p = table->sections; p < table->sections_end; p++)
{
if (!strncmp (secname, bfd_section_name (exec_bfd, p->the_bfd_section), seclen)
&& bfd_section_name (exec_bfd, p->the_bfd_section)[seclen] == '\0')
@@ -661,16 +770,46 @@ set_section_command (char *args, int from_tty)
error (_("Section %s not found"), secprint);
}
+/* If we can find a section in FILENAME with BFD index INDEX, adjust
+ it to ADDRESS. */
+
+void
+exec_set_section_address (const char *filename, int index, CORE_ADDR address)
+{
+ struct target_section *p;
+ struct target_section_table *table;
+
+ table = current_target_sections;
+ for (p = table->sections; p < table->sections_end; p++)
+ {
+ if (strcmp (filename, p->bfd->filename) == 0
+ && index == p->the_bfd_section->index)
+ {
+ p->endaddr += address - p->addr;
+ p->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 (CORE_ADDR addr, char *contents)
+ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
{
return 0;
}
+static int
+exec_has_memory (struct target_ops *ops)
+{
+ /* We can provide memory if we have any file/target sections to read
+ from. */
+ return (current_target_sections->sections
+ != current_target_sections->sections_end);
+}
+
/* Find mapped memory. */
extern void
@@ -696,15 +835,16 @@ init_exec_ops (void)
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.deprecated_xfer_memory = xfer_memory;
+ 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_create_inferior = find_default_create_inferior;
exec_ops.to_stratum = file_stratum;
- exec_ops.to_has_memory = 1;
+ exec_ops.to_has_memory = exec_has_memory;
exec_ops.to_make_corefile_notes = exec_make_note_section;
exec_ops.to_magic = OPS_MAGIC;
}
@@ -746,7 +886,7 @@ file itself are wrong. Each section must be changed separately. The\n\
Set writing into executable and core files."), _("\
Show writing into executable and core files."), NULL,
NULL,
- NULL, /* FIXME: i18n: */
+ show_write_files,
&setlist, &showlist);
add_target (&exec_ops);