/* Work with executable files, for GDB.
- Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997, 1998
- Free Software Foundation, Inc.
+
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
+ Inc.
This file is part of GDB.
#include "language.h"
#include "symfile.h"
#include "objfiles.h"
+#include "completer.h"
+#include "value.h"
+#include "exec.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <fcntl.h>
+#include "readline/readline.h"
#include "gdb_string.h"
#include "gdbcore.h"
#include "xcoffsolib.h"
-struct vmap *map_vmap PARAMS ((bfd *, bfd *));
+struct vmap *map_vmap (bfd *, bfd *);
-void (*file_changed_hook) PARAMS ((char *));
+void (*deprecated_file_changed_hook) (char *);
/* Prototypes for local functions */
-static void add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));
-
-static void exec_close PARAMS ((int));
-
-static void file_command PARAMS ((char *, int));
+static void exec_close (int);
-static void set_section_command PARAMS ((char *, int));
+static void file_command (char *, int);
-static void exec_files_info PARAMS ((struct target_ops *));
+static void set_section_command (char *, int);
-static void bfdsec_to_vmap PARAMS ((bfd *, sec_ptr, PTR));
+static void exec_files_info (struct target_ops *);
-static int ignore PARAMS ((CORE_ADDR, char *));
+static int ignore (CORE_ADDR, char *);
-static void init_exec_ops PARAMS ((void));
+static void init_exec_ops (void);
-void _initialize_exec PARAMS ((void));
-
-extern int info_verbose;
+void _initialize_exec (void);
/* The target vector for executable files. */
int write_files = 0;
-/* Text start and end addresses (KLUDGE) if needed */
-
-#ifndef NEED_TEXT_START_END
-#define NEED_TEXT_START_END (0)
-#endif
-CORE_ADDR text_start = 0;
-CORE_ADDR text_end = 0;
-
struct vmap *vmap;
-/* ARGSUSED */
+void
+exec_open (char *args, int from_tty)
+{
+ target_preopen (from_tty);
+ exec_file_attach (args, from_tty);
+}
+
static void
-exec_close (quitting)
- int quitting;
+exec_close (int quitting)
{
int need_symtab_cleanup = 0;
struct vmap *vp, *nxt;
FIXME-as-well: free_objfile already free'd vp->name, so it isn't
valid here. */
free_named_symtabs (vp->name);
- free (vp);
+ xfree (vp);
}
vmap = NULL;
if (!bfd_close (exec_bfd))
warning ("cannot close \"%s\": %s",
name, bfd_errmsg (bfd_get_error ()));
- free (name);
+ xfree (name);
exec_bfd = NULL;
}
if (exec_ops.to_sections)
{
- free ((PTR) exec_ops.to_sections);
+ xfree (exec_ops.to_sections);
exec_ops.to_sections = NULL;
exec_ops.to_sections_end = NULL;
}
}
+void
+exec_file_clear (int from_tty)
+{
+ /* Remove exec file. */
+ unpush_target (&exec_ops);
+
+ if (from_tty)
+ printf_unfiltered ("No executable file now.\n");
+}
+
/* Process the first arg in ARGS as the new exec file.
This function is intended to be behave essentially the same
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.) */
+ we're supplying the exec pathname late for good reason.)
+
+ ARGS is assumed to be the filename. */
void
-exec_file_attach (args, from_tty)
- char *args;
- int from_tty;
+exec_file_attach (char *filename, int from_tty)
{
- char **argv;
- char *filename;
-
/* Remove any previous exec file. */
unpush_target (&exec_ops);
/* Now open and digest the file the user requested, if any. */
- if (args)
+ if (!filename)
+ {
+ if (from_tty)
+ printf_unfiltered ("No executable file now.\n");
+ }
+ else
{
char *scratch_pathname;
int scratch_chan;
- /* 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);
-
- for (; (*argv != NULL) && (**argv == '-'); argv++)
- {;
- }
- if (*argv == NULL)
- error ("no exec file name was specified");
-
- filename = tilde_expand (*argv);
- make_cleanup (free, filename);
-
scratch_chan = openp (getenv ("PATH"), 1, filename,
write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
&scratch_pathname);
-#if defined(__GO32__) || defined(_WIN32)
+#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
if (scratch_chan < 0)
{
char *exename = alloca (strlen (filename) + 5);
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 = strdup (scratch_pathname);
- make_cleanup (free, scratch_pathname);
+ scratch_pathname = xstrdup (scratch_pathname);
+ make_cleanup (xfree, scratch_pathname);
if (!bfd_check_format (exec_bfd, bfd_object))
{
/* FIXME - This should only be run for RS6000, but the ifdef is a poor
way to accomplish. */
-#ifdef IBM6000_TARGET
+#ifdef DEPRECATED_IBM6000_TARGET
/* Setup initial vmap. */
map_vmap (exec_bfd, 0);
error ("\"%s\": can't find the file sections: %s",
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
-#endif /* IBM6000_TARGET */
+#endif /* DEPRECATED_IBM6000_TARGET */
if (build_section_table (exec_bfd, &exec_ops.to_sections,
&exec_ops.to_sections_end))
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
- /* text_end is sometimes used for where to put call dummies. A
- few ports use these for other purposes too. */
- if (NEED_TEXT_START_END)
- {
- struct section_table *p;
-
- /* Set text_start to the lowest address of the start of any
- readonly code section and set text_end to the highest
- address of the end of any readonly code section. */
- /* FIXME: The comment above does not match the code. The
- code checks for sections with are either code *or*
- readonly. */
- text_start = ~(CORE_ADDR) 0;
- text_end = (CORE_ADDR) 0;
- for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
- if (bfd_get_section_flags (p->bfd, p->the_bfd_section)
- & (SEC_CODE | SEC_READONLY))
- {
- if (text_start > p->addr)
- text_start = p->addr;
- if (text_end < p->endaddr)
- text_end = p->endaddr;
- }
- }
+#ifdef DEPRECATED_HPUX_TEXT_END
+ DEPRECATED_HPUX_TEXT_END (&exec_ops);
+#endif
validate_files ();
push_target (&exec_ops);
/* Tell display code (if any) about the changed file name. */
- if (exec_file_display_hook)
- (*exec_file_display_hook) (filename);
+ if (deprecated_exec_file_display_hook)
+ (*deprecated_exec_file_display_hook) (filename);
}
- else if (from_tty)
- printf_unfiltered ("No executable file now.\n");
}
/* Process the first arg in ARGS as the new exec file.
Note that we have to explicitly ignore additional args, since we can
be called from file_command(), which also calls symbol_file_command()
- which can take multiple args. */
+ which can take multiple args.
+
+ If ARGS is NULL, we just want to close the exec file. */
-void
-exec_file_command (args, from_tty)
- char *args;
- int from_tty;
+static void
+exec_file_command (char *args, int from_tty)
{
char **argv;
char *filename;
-
+
target_preopen (from_tty);
- exec_file_attach (args, from_tty);
+ if (args)
+ {
+ /* 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);
+
+ for (; (*argv != NULL) && (**argv == '-'); argv++)
+ {;
+ }
+ if (*argv == NULL)
+ error ("No executable file name was specified");
+
+ filename = tilde_expand (*argv);
+ make_cleanup (xfree, filename);
+ exec_file_attach (filename, from_tty);
+ }
+ else
+ exec_file_attach (NULL, from_tty);
}
/* Set both the exec file and the symbol file, in one command.
command was added? */
static void
-file_command (arg, from_tty)
- char *arg;
- int from_tty;
+file_command (char *arg, int from_tty)
{
/* FIXME, if we lose on reading the symbol file, we should revert
the exec file, but that's rough. */
exec_file_command (arg, from_tty);
symbol_file_command (arg, from_tty);
- if (file_changed_hook)
- file_changed_hook (arg);
+ if (deprecated_file_changed_hook)
+ deprecated_file_changed_hook (arg);
}
\f
we cast it back to its proper type. */
static void
-add_to_section_table (abfd, asect, table_pp_char)
- bfd *abfd;
- sec_ptr asect;
- PTR table_pp_char;
+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;
flagword aflag;
Returns 0 if OK, 1 on error. */
int
-build_section_table (some_bfd, start, end)
- bfd *some_bfd;
- struct section_table **start, **end;
+build_section_table (struct bfd *some_bfd, struct section_table **start,
+ struct section_table **end)
{
unsigned count;
count = bfd_count_sections (some_bfd);
if (*start)
- free ((PTR) * start);
+ xfree (* start);
*start = (struct section_table *) xmalloc (count * sizeof (**start));
*end = *start;
bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end);
if (*end > *start + count)
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
/* We could realloc the table, but it probably loses for most files. */
return 0;
}
\f
static void
-bfdsec_to_vmap (abfd, sect, arg3)
- bfd *abfd;
- sec_ptr sect;
- PTR arg3;
+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;
if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
return;
- if (STREQ (bfd_section_name (abfd, sect), ".text"))
+ if (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".text"))
{
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 (STREQ (bfd_section_name (abfd, sect), ".data"))
+ else if (DEPRECATED_STREQ (bfd_section_name (abfd, sect), ".data"))
{
vp->dstart = bfd_section_vma (abfd, sect);
vp->dend = vp->dstart + bfd_section_size (abfd, sect);
Return the new vmap. */
struct vmap *
-map_vmap (abfd, arch)
- bfd *abfd;
- bfd *arch;
+map_vmap (bfd *abfd, bfd *arch)
{
struct vmap_and_bfd vmap_bfd;
struct vmap *vp, **vpp;
we just tail-call it with more arguments to select between them. */
int
-xfer_memory (memaddr, myaddr, len, write, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int write;
- struct target_ops *target;
+xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ struct mem_attrib *attrib,
+ struct target_ops *target)
{
- boolean res;
+ int res;
struct section_table *p;
CORE_ADDR nextsectaddr, memend;
- boolean (*xfer_fn) PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
- asection *section;
+ asection *section = NULL;
if (len <= 0)
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
if (overlay_debugging)
{
}
memend = memaddr + len;
- xfer_fn = write ? bfd_set_section_contents : bfd_get_section_contents;
nextsectaddr = memend;
-#if 0 /* Stu's implementation */
-/* If a section has been specified, try to use it. Note that we cannot use the
- specified section directly. This is because it usually comes from the
- symbol file, which may be different from the exec or core file. Instead, we
- have to lookup the specified section by name in the bfd associated with
- to_sections. */
-
- if (target_memory_bfd_section)
- {
- asection *s;
- bfd *abfd;
- asection *target_section;
- bfd *target_bfd;
-
- s = target_memory_bfd_section;
- abfd = s->owner;
-
- target_bfd = target->to_sections->bfd;
- target_section = bfd_get_section_by_name (target_bfd, bfd_section_name (abfd, s));
-
- if (target_section)
- {
- bfd_vma sec_addr;
- bfd_size_type sec_size;
-
- sec_addr = bfd_section_vma (target_bfd, target_section);
- sec_size = target_section->_raw_size;
-
- /* Make sure the requested memory starts inside the section. */
-
- if (memaddr >= sec_addr
- && memaddr < sec_addr + sec_size)
- {
- /* Cut back length in case request overflows the end of the section. */
- len = min (len, sec_addr + sec_size - memaddr);
-
- res = xfer_fn (target_bfd, target_section, myaddr, memaddr - sec_addr, len);
-
- return res ? len : 0;
- }
- }
- }
-#endif /* 0, Stu's implementation */
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)
continue; /* not the section we need */
if (memaddr >= p->addr)
- if (memend <= p->endaddr)
- {
- /* Entire transfer is within this section. */
- res = xfer_fn (p->bfd, p->the_bfd_section, myaddr,
- memaddr - p->addr, len);
- return (res != 0) ? len : 0;
- }
- else if (memaddr >= p->endaddr)
- {
- /* This section ends before the transfer starts. */
- continue;
- }
- else
- {
- /* This section overlaps the transfer. Just do half. */
- len = p->endaddr - memaddr;
- res = xfer_fn (p->bfd, p->the_bfd_section, myaddr,
- memaddr - p->addr, len);
- return (res != 0) ? len : 0;
- }
+ {
+ if (memend <= p->endaddr)
+ {
+ /* Entire transfer is within this section. */
+ if (write)
+ res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
+ myaddr, memaddr - p->addr,
+ len);
+ else
+ res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
+ myaddr, memaddr - p->addr,
+ len);
+ return (res != 0) ? len : 0;
+ }
+ else if (memaddr >= p->endaddr)
+ {
+ /* This section ends before the transfer starts. */
+ continue;
+ }
+ else
+ {
+ /* This section overlaps the transfer. Just do half. */
+ len = p->endaddr - memaddr;
+ if (write)
+ res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
+ myaddr, memaddr - p->addr,
+ len);
+ else
+ res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
+ myaddr, memaddr - p->addr,
+ len);
+ return (res != 0) ? len : 0;
+ }
+ }
else
nextsectaddr = min (nextsectaddr, p->addr);
}
\f
void
-print_section_info (t, abfd)
- struct target_ops *t;
- bfd *abfd;
+print_section_info (struct target_ops *t, bfd *abfd)
{
struct section_table *p;
+ /* FIXME: "016l" is not wide enough when TARGET_ADDR_BIT > 64. */
+ char *fmt = TARGET_ADDR_BIT <= 32 ? "08l" : "016l";
printf_filtered ("\t`%s', ", bfd_get_filename (abfd));
wrap_here (" ");
}
for (p = t->to_sections; p < t->to_sections_end; p++)
{
- /* FIXME-32x64 need a print_address_numeric with field width */
- printf_filtered ("\t%s", local_hex_string_custom ((unsigned long) p->addr, "08l"));
- printf_filtered (" - %s", local_hex_string_custom ((unsigned long) p->endaddr, "08l"));
+ printf_filtered ("\t%s", local_hex_string_custom (p->addr, fmt));
+ printf_filtered (" - %s", local_hex_string_custom (p->endaddr, fmt));
+
+ /* FIXME: A format of "08l" is not wide enough for file offsets
+ larger than 4GB. OTOH, making it "016l" isn't desirable either
+ since most output will then be much wider than necessary. It
+ may make sense to test the size of the file and choose the
+ format string accordingly. */
if (info_verbose)
printf_filtered (" @ %s",
- local_hex_string_custom ((unsigned long) p->the_bfd_section->filepos, "08l"));
+ local_hex_string_custom (p->the_bfd_section->filepos, "08l"));
printf_filtered (" is %s", bfd_section_name (p->bfd, p->the_bfd_section));
if (p->bfd != abfd)
{
}
static void
-exec_files_info (t)
- struct target_ops *t;
+exec_files_info (struct target_ops *t)
{
print_section_info (t, exec_bfd);
struct vmap *vp;
printf_unfiltered ("\tMapping info for file `%s'.\n", vmap->name);
- printf_unfiltered ("\t %8.8s %8.8s %8.8s %8.8s %8.8s %s\n",
- "tstart", "tend", "dstart", "dend", "section",
+ printf_unfiltered ("\t %*s %*s %*s %*s %8.8s %s\n",
+ strlen_paddr (), "tstart",
+ strlen_paddr (), "tend",
+ strlen_paddr (), "dstart",
+ strlen_paddr (), "dend",
+ "section",
"file(member)");
for (vp = vmap; vp; vp = vp->nxt)
- printf_unfiltered ("\t0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x %s%s%s%s\n",
- vp->tstart, vp->tend, vp->dstart, vp->dend, vp->name,
+ 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),
+ vp->name,
*vp->member ? "(" : "", vp->member,
*vp->member ? ")" : "");
}
in the exec objfile. */
void
-exec_set_section_offsets (text_off, data_off, bss_off)
- bfd_signed_vma text_off;
- bfd_signed_vma data_off;
- bfd_signed_vma bss_off;
+exec_set_section_offsets (bfd_signed_vma text_off, bfd_signed_vma data_off,
+ bfd_signed_vma bss_off)
{
struct section_table *sect;
}
static void
-set_section_command (args, from_tty)
- char *args;
- int from_tty;
+set_section_command (char *args, int from_tty)
{
struct section_table *p;
char *secname;
breakpoint_init_inferior). */
static int
-ignore (addr, contents)
- CORE_ADDR addr;
- char *contents;
+ignore (CORE_ADDR addr, char *contents)
{
return 0;
}
+/* Find mapped memory. */
+
+extern void
+exec_set_find_memory_regions (int (*func) (int (*) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
+ void *))
+{
+ exec_ops.to_find_memory_regions = func;
+}
+
+static char *exec_make_note_section (bfd *, int *);
+
/* Fill in the exec file target vector. Very few entries need to be
defined. */
-void
-init_exec_ops ()
+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_file_command;
+ exec_ops.to_open = exec_open;
exec_ops.to_close = exec_close;
exec_ops.to_attach = find_default_attach;
- exec_ops.to_require_attach = find_default_require_attach;
- exec_ops.to_require_detach = find_default_require_detach;
exec_ops.to_xfer_memory = xfer_memory;
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_clone_and_follow_inferior = find_default_clone_and_follow_inferior;
exec_ops.to_stratum = file_stratum;
exec_ops.to_has_memory = 1;
+ exec_ops.to_make_corefile_notes = exec_make_note_section;
exec_ops.to_magic = OPS_MAGIC;
}
void
-_initialize_exec ()
+_initialize_exec (void)
{
struct cmd_list_element *c;
If FILE cannot be found as specified, your execution directory path\n\
($PATH) is searched for a command of that name.\n\
No arg means to have no executable file and no symbols.", &cmdlist);
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
}
c = add_cmd ("exec-file", class_files, exec_file_command,
If FILE cannot be found as specified, your execution directory path\n\
is searched for a command of that name.\n\
No arg means have no executable file.", &cmdlist);
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
add_com ("section", class_files, set_section_command,
"Change the base address of section SECTION of the exec file to ADDR.\n\
add_target (&exec_ops);
}
+
+static char *
+exec_make_note_section (bfd *obfd, int *note_size)
+{
+ error ("Can't create a corefile");
+}