gdb/exec.c - gdb
Global variables defined
Functions defined
Source code
- #include "defs.h"
- #include "frame.h"
- #include "inferior.h"
- #include "target.h"
- #include "gdbcmd.h"
- #include "language.h"
- #include "filenames.h"
- #include "symfile.h"
- #include "objfiles.h"
- #include "completer.h"
- #include "value.h"
- #include "exec.h"
- #include "observer.h"
- #include "arch-utils.h"
- #include "gdbthread.h"
- #include "progspace.h"
- #include "gdb_bfd.h"
- #include "gcore.h"
- #include <fcntl.h>
- #include "readline/readline.h"
- #include "gdbcore.h"
- #include <ctype.h>
- #include <sys/stat.h>
- void (*deprecated_file_changed_hook) (char *);
- static void file_command (char *, int);
- static void set_section_command (char *, int);
- static void exec_files_info (struct target_ops *);
- static void init_exec_ops (void);
- void _initialize_exec (void);
- static struct target_ops exec_ops;
- 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);
- }
- static void
- exec_open (const char *args, int from_tty)
- {
- target_preopen (from_tty);
- exec_file_attach (args, from_tty);
- }
- void
- exec_close (void)
- {
- if (exec_bfd)
- {
- bfd *abfd = exec_bfd;
- gdb_bfd_unref (abfd);
-
- exec_bfd = NULL;
- exec_bfd_mtime = 0;
- remove_target_sections (&exec_bfd);
- xfree (exec_filename);
- exec_filename = NULL;
- }
- }
- static void
- exec_close_1 (struct target_ops *self)
- {
- struct program_space *ss;
- struct cleanup *old_chain;
- old_chain = save_current_program_space ();
- ALL_PSPACES (ss)
- {
- set_current_program_space (ss);
- clear_section_table (current_target_sections);
- exec_close ();
- }
- do_cleanups (old_chain);
- }
- void
- exec_file_clear (int from_tty)
- {
-
- exec_close ();
- if (from_tty)
- printf_unfiltered (_("No executable file now.\n"));
- }
- void
- exec_file_attach (const char *filename, int from_tty)
- {
- struct cleanup *cleanups;
-
- gdb_bfd_ref (exec_bfd);
- cleanups = make_cleanup_bfd_unref (exec_bfd);
-
- exec_close ();
-
- if (!filename)
- {
- if (from_tty)
- printf_unfiltered (_("No executable file now.\n"));
- set_gdbarch_from_file (NULL);
- }
- else
- {
- char *scratch_pathname, *canonical_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,
- &scratch_pathname);
- #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
- 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);
- }
- #endif
- if (scratch_chan < 0)
- perror_with_name (filename);
- make_cleanup (xfree, scratch_pathname);
-
- 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)
- {
- error (_("\"%s\": could not open as an executable file: %s"),
- scratch_pathname, bfd_errmsg (bfd_get_error ()));
- }
- gdb_assert (exec_filename == NULL);
- exec_filename = gdb_realpath_keepfile (scratch_pathname);
- if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching))
- {
-
- exec_close ();
- error (_("\"%s\": not in executable format: %s"),
- scratch_pathname,
- gdb_bfd_errmsg (bfd_get_error (), matching));
- }
- if (build_section_table (exec_bfd, §ions, §ions_end))
- {
-
- exec_close ();
- error (_("\"%s\": can't find the file sections: %s"),
- scratch_pathname, bfd_errmsg (bfd_get_error ()));
- }
- exec_bfd_mtime = bfd_get_mtime (exec_bfd);
- validate_files ();
- set_gdbarch_from_file (exec_bfd);
-
- add_target_sections (&exec_bfd, sections, sections_end);
- xfree (sections);
-
- if (deprecated_exec_file_display_hook)
- (*deprecated_exec_file_display_hook) (filename);
- }
- do_cleanups (cleanups);
- bfd_cache_close_all ();
- observer_notify_executable_changed ();
- }
- static void
- exec_file_command (char *args, int from_tty)
- {
- char **argv;
- 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? ")))
- error (_("File not changed."));
- if (args)
- {
- struct cleanup *cleanups;
-
- argv = gdb_buildargv (args);
- cleanups = 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);
- do_cleanups (cleanups);
- }
- else
- exec_file_attach (NULL, from_tty);
- }
- static void
- file_command (char *arg, int from_tty)
- {
- FIXME
- exec_file_command (arg, from_tty);
- symbol_file_command (arg, from_tty);
- if (deprecated_file_changed_hook)
- deprecated_file_changed_hook (arg);
- }
- static void
- add_to_section_table (bfd *abfd, struct bfd_section *asect,
- void *table_pp_char)
- {
- struct target_section **table_pp = (struct target_section **) table_pp_char;
- flagword aflag;
- gdb_assert (abfd == asect->owner);
-
- aflag = bfd_get_section_flags (abfd, 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)++;
- }
- void
- clear_section_table (struct target_section_table *table)
- {
- xfree (table->sections);
- table->sections = table->sections_end = NULL;
- }
- static int
- resize_section_table (struct target_section_table *table, int adjustment)
- {
- int old_count;
- int new_count;
- old_count = table->sections_end - table->sections;
- new_count = adjustment + old_count;
- if (new_count)
- {
- table->sections = xrealloc (table->sections,
- sizeof (struct target_section) * new_count);
- table->sections_end = table->sections + new_count;
- }
- else
- clear_section_table (table);
- return old_count;
- }
- int
- 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 target_section *) xmalloc (count * sizeof (**start));
- *end = *start;
- bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end);
- if (*end > *start + count)
- internal_error (__FILE__, __LINE__,
- _("failed internal consistency check"));
-
- return 0;
- }
- void
- add_target_sections (void *owner,
- 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);
- int i;
- for (i = 0; i < count; ++i)
- {
- table->sections[space + i] = sections[i];
- table->sections[space + i].owner = owner;
- }
-
- if (!target_is_pushed (&exec_ops))
- push_target (&exec_ops);
- }
- }
- 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;
-
- 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++;
- }
- }
- void
- 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->owner != owner)
- {
-
- if (dest < src)
- *dest = *src;
- dest++;
- }
-
- if (dest < src)
- {
- int old_count;
- old_count = resize_section_table (table, dest - src);
-
- 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);
- }
- }
- }
- enum target_xfer_status
- exec_read_partial_read_only (gdb_byte *readbuf, ULONGEST offset,
- ULONGEST len, ULONGEST *xfered_len)
- {
-
- if (exec_bfd != NULL)
- {
- asection *s;
- bfd_size_type size;
- bfd_vma vma;
- for (s = exec_bfd->sections; s; s = s->next)
- {
- if ((s->flags & SEC_LOAD) == 0
- || (s->flags & SEC_READONLY) == 0)
- continue;
- vma = s->vma;
- size = bfd_get_section_size (s);
- if (vma <= offset && offset < (vma + size))
- {
- ULONGEST amt;
- amt = (vma + size) - offset;
- if (amt > len)
- amt = len;
- amt = bfd_get_section_contents (exec_bfd, s,
- readbuf, offset - vma, amt);
- if (amt == 0)
- return TARGET_XFER_EOF;
- else
- {
- *xfered_len = amt;
- return TARGET_XFER_OK;
- }
- }
- }
- }
-
- return TARGET_XFER_E_IO;
- }
- static VEC(mem_range_s) *
- section_table_available_memory (VEC(mem_range_s) *memory,
- CORE_ADDR memaddr, ULONGEST len,
- struct target_section *sections,
- struct target_section *sections_end)
- {
- struct target_section *p;
- for (p = sections; p < sections_end; p++)
- {
- if ((bfd_get_section_flags (p->the_bfd_section->owner,
- p->the_bfd_section)
- & SEC_READONLY) == 0)
- continue;
-
- 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;
- lo2 = p->addr;
- hi2 = p->endaddr;
- r = VEC_safe_push (mem_range_s, memory, NULL);
- r->start = max (lo1, lo2);
- r->length = min (hi1, hi2) - r->start;
- }
- }
- return memory;
- }
- 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);
- old_chain = make_cleanup (VEC_cleanup(mem_range_s),
- &available_memory);
- normalize_mem_ranges (available_memory);
- for (i = 0;
- VEC_iterate (mem_range_s, available_memory, i, r);
- i++)
- {
- if (mem_ranges_overlap (r->start, r->length, offset, len))
- {
- CORE_ADDR end;
- enum target_xfer_status status;
-
- end = min (offset + len, r->start + r->length);
- gdb_assert (end - offset <= len);
- if (offset >= r->start)
- status = exec_read_partial_read_only (readbuf, offset,
- end - offset,
- xfered_len);
- else
- {
- *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;
- }
- enum target_xfer_status
- section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len,
- struct target_section *sections,
- struct target_section *sections_end,
- const char *section_name)
- {
- int res;
- struct target_section *p;
- ULONGEST memaddr = offset;
- ULONGEST memend = memaddr + len;
- if (len == 0)
- internal_error (__FILE__, __LINE__,
- _("failed internal consistency check"));
- for (p = sections; p < sections_end; p++)
- {
- struct bfd_section *asect = p->the_bfd_section;
- bfd *abfd = asect->owner;
- if (section_name && strcmp (section_name, asect->name) != 0)
- continue;
- if (memaddr >= p->addr)
- {
- if (memend <= p->endaddr)
- {
-
- if (writebuf)
- res = bfd_set_section_contents (abfd, asect,
- writebuf, memaddr - p->addr,
- len);
- else
- res = bfd_get_section_contents (abfd, asect,
- readbuf, memaddr - p->addr,
- len);
- if (res != 0)
- {
- *xfered_len = len;
- return TARGET_XFER_OK;
- }
- else
- return TARGET_XFER_EOF;
- }
- else if (memaddr >= p->endaddr)
- {
-
- continue;
- }
- else
- {
-
- len = p->endaddr - memaddr;
- if (writebuf)
- res = bfd_set_section_contents (abfd, asect,
- writebuf, memaddr - p->addr,
- len);
- else
- res = bfd_get_section_contents (abfd, asect,
- readbuf, memaddr - p->addr,
- len);
- if (res != 0)
- {
- *xfered_len = len;
- return TARGET_XFER_OK;
- }
- else
- return TARGET_XFER_EOF;
- }
- }
- }
- return TARGET_XFER_EOF;
- }
- static struct target_section_table *
- exec_get_section_table (struct target_ops *ops)
- {
- 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)
- {
- 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, xfered_len,
- table->sections,
- table->sections_end,
- NULL);
- else
- return TARGET_XFER_E_IO;
- }
- void
- print_section_info (struct target_section_table *t, bfd *abfd)
- {
- struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
- struct target_section *p;
- FIXME
- 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)
- {
-
- bfd_vma displacement = 0;
- bfd_vma entry_point;
- 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))
- != (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)))
- {
- displacement = p->addr - bfd_get_section_vma (pbfd, psect);
- break;
- }
- }
- if (p == t->sections_end)
- warning (_("Cannot find section for the entry point of %s."),
- 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++)
- {
- 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));
- FIXME
- FIXME
- if (info_verbose)
- printf_filtered (" @ %s",
- 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");
- }
- }
- static void
- exec_files_info (struct target_ops *t)
- {
- if (exec_bfd)
- print_section_info (current_target_sections, exec_bfd);
- else
- puts_filtered (_("\t<no file loaded>\n"));
- }
- static void
- set_section_command (char *args, int from_tty)
- {
- 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"));
-
- for (secname = args; !isspace (*args); args++);
- seclen = args - secname;
-
- secaddr = parse_and_eval_address (args);
- 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')
- {
- offset = secaddr - p->addr;
- p->addr += offset;
- p->endaddr += offset;
- if (from_tty)
- exec_files_info (&exec_ops);
- return;
- }
- }
- if (seclen >= sizeof (secprint))
- seclen = sizeof (secprint) - 1;
- strncpy (secprint, secname, seclen);
- secprint[seclen] = '\0';
- error (_("Section %s not found"), secprint);
- }
- 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 (filename_cmp (filename, p->the_bfd_section->owner->filename) == 0
- && index == p->the_bfd_section->index)
- {
- p->endaddr += address - p->addr;
- p->addr = address;
- }
- }
- }
- static int
- ignore (struct target_ops *ops, struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
- {
- return 0;
- }
- static int
- exec_has_memory (struct target_ops *ops)
- {
-
- return (current_target_sections->sections
- != current_target_sections->sections_end);
- }
- static char *
- exec_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
- {
- error (_("Can't create a corefile"));
- }
- 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_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 = ignore;
- 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;
- }
- void
- _initialize_exec (void)
- {
- struct cmd_list_element *c;
- init_exec_ops ();
- if (!dbx_commands)
- {
- c = add_cmd ("file", class_files, file_command, _("\
- Use FILE as program to be debugged.\n\
- It is read for its symbols, for getting the contents of pure memory,\n\
- and it is the program executed when you use the `run' command.\n\
- 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);
- set_cmd_completer (c, filename_completer);
- }
- c = add_cmd ("exec-file", class_files, exec_file_command, _("\
- Use FILE as program for getting contents of pure memory.\n\
- 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);
- 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\
- This can be used if the exec file does not contain section addresses,\n\
- (such as in the a.out format), or when the addresses specified in the\n\
- file itself are wrong. Each section must be changed separately. The\n\
- ``info files'' command lists all the sections and their addresses."));
- add_setshow_boolean_cmd ("write", class_support, &write_files, _("\
- Set writing into executable and core files."), _("\
- Show writing into executable and core files."), NULL,
- NULL,
- show_write_files,
- &setlist, &showlist);
- add_target_with_completer (&exec_ops, filename_completer);
- }