Index: gdb/symfile.c |
diff --git a/gdb/symfile.c b/gdb/symfile.c |
index 175d61c2a8860c282f65a4d91ad0879c7649397f..71f6b3e8c77fd0671d17c7f52963d2b158066793 100644 |
--- a/gdb/symfile.c |
+++ b/gdb/symfile.c |
@@ -1,6 +1,6 @@ |
/* Generic symbol file reading for the GNU debugger, GDB. |
- Copyright (C) 1990-2012 Free Software Foundation, Inc. |
+ Copyright (C) 1990-2013 Free Software Foundation, Inc. |
Contributed by Cygnus Support, using pieces from other GDB modules. |
@@ -55,11 +55,14 @@ |
#include "solib.h" |
#include "remote.h" |
#include "stack.h" |
+#include "gdb_bfd.h" |
+#include "cli/cli-utils.h" |
+#include "target.h" |
#include <sys/types.h> |
#include <fcntl.h> |
-#include "gdb_string.h" |
-#include "gdb_stat.h" |
+#include <string.h> |
+#include <sys/stat.h> |
#include <ctype.h> |
#include <time.h> |
#include <sys/time.h> |
@@ -81,34 +84,20 @@ static void clear_symtab_users_cleanup (void *ignore); |
/* Global variables owned by this file. */ |
int readnow_symbol_files; /* Read full symbols immediately. */ |
-/* External variables and functions referenced. */ |
- |
-extern void report_transfer_performance (unsigned long, time_t, time_t); |
- |
/* Functions this file defines. */ |
static void load_command (char *, int); |
-static void symbol_file_add_main_1 (char *args, int from_tty, int flags); |
+static void symbol_file_add_main_1 (const char *args, int from_tty, int flags); |
static void add_symbol_file_command (char *, int); |
-bfd *symfile_bfd_open (char *); |
- |
-int get_section_index (struct objfile *, char *); |
- |
static const struct sym_fns *find_sym_fns (bfd *); |
static void decrement_reading_symtab (void *); |
static void overlay_invalidate_all (void); |
-void list_overlays_command (char *, int); |
- |
-void map_overlay_command (char *, int); |
- |
-void unmap_overlay_command (char *, int); |
- |
static void overlay_auto_command (char *, int); |
static void overlay_manual_command (char *, int); |
@@ -142,10 +131,18 @@ void _initialize_symfile (void); |
calls add_symtab_fns() to register information on each format it is |
prepared to read. */ |
-typedef const struct sym_fns *sym_fns_ptr; |
-DEF_VEC_P (sym_fns_ptr); |
+typedef struct |
+{ |
+ /* BFD flavour that we handle. */ |
+ enum bfd_flavour sym_flavour; |
+ |
+ /* The "vtable" of symbol functions. */ |
+ const struct sym_fns *sym_fns; |
+} registered_sym_fns; |
+ |
+DEF_VEC_O (registered_sym_fns); |
-static VEC (sym_fns_ptr) *symtab_fns = NULL; |
+static VEC (registered_sym_fns) *symtab_fns = NULL; |
/* If non-zero, shared library symbols will be added automatically |
when the inferior is created, new libraries are loaded, or when |
@@ -160,56 +157,6 @@ static VEC (sym_fns_ptr) *symtab_fns = NULL; |
int auto_solib_add = 1; |
-/* Make a null terminated copy of the string at PTR with SIZE characters in |
- the obstack pointed to by OBSTACKP . Returns the address of the copy. |
- Note that the string at PTR does not have to be null terminated, I.e. it |
- may be part of a larger string and we are only saving a substring. */ |
- |
-char * |
-obsavestring (const char *ptr, int size, struct obstack *obstackp) |
-{ |
- char *p = (char *) obstack_alloc (obstackp, size + 1); |
- /* Open-coded memcpy--saves function call time. These strings are usually |
- short. FIXME: Is this really still true with a compiler that can |
- inline memcpy? */ |
- { |
- const char *p1 = ptr; |
- char *p2 = p; |
- const char *end = ptr + size; |
- |
- while (p1 != end) |
- *p2++ = *p1++; |
- } |
- p[size] = 0; |
- return p; |
-} |
- |
-/* Concatenate NULL terminated variable argument list of `const char *' |
- strings; return the new string. Space is found in the OBSTACKP. |
- Argument list must be terminated by a sentinel expression `(char *) |
- NULL'. */ |
- |
-char * |
-obconcat (struct obstack *obstackp, ...) |
-{ |
- va_list ap; |
- |
- va_start (ap, obstackp); |
- for (;;) |
- { |
- const char *s = va_arg (ap, const char *); |
- |
- if (s == NULL) |
- break; |
- |
- obstack_grow_str (obstackp, s); |
- } |
- va_end (ap); |
- obstack_1grow (obstackp, 0); |
- |
- return obstack_finish (obstackp); |
-} |
- |
/* True if we are reading a symbol table. */ |
int currently_reading_symtab = 0; |
@@ -218,14 +165,17 @@ static void |
decrement_reading_symtab (void *dummy) |
{ |
currently_reading_symtab--; |
+ gdb_assert (currently_reading_symtab >= 0); |
} |
/* Increment currently_reading_symtab and return a cleanup that can be |
used to decrement it. */ |
+ |
struct cleanup * |
increment_reading_symtab (void) |
{ |
++currently_reading_symtab; |
+ gdb_assert (currently_reading_symtab > 0); |
return make_cleanup (decrement_reading_symtab, NULL); |
} |
@@ -255,7 +205,9 @@ find_lowest_section (bfd *abfd, asection *sect, void *obj) |
*lowest = sect; |
} |
-/* Create a new section_addr_info, with room for NUM_SECTIONS. */ |
+/* Create a new section_addr_info, with room for NUM_SECTIONS. The |
+ new object's 'num_sections' field is set to 0; it must be updated |
+ by the caller. */ |
struct section_addr_info * |
alloc_section_addr_info (size_t num_sections) |
@@ -267,7 +219,6 @@ alloc_section_addr_info (size_t num_sections) |
+ sizeof (struct other_sections) * (num_sections - 1)); |
sap = (struct section_addr_info *) xmalloc (size); |
memset (sap, 0, size); |
- sap->num_sections = num_sections; |
return sap; |
} |
@@ -287,18 +238,21 @@ build_section_addr_info_from_section_table (const struct target_section *start, |
for (stp = start, oidx = 0; stp != end; stp++) |
{ |
- if (bfd_get_section_flags (stp->bfd, |
- stp->the_bfd_section) & (SEC_ALLOC | SEC_LOAD) |
+ struct bfd_section *asect = stp->the_bfd_section; |
+ bfd *abfd = asect->owner; |
+ |
+ if (bfd_get_section_flags (abfd, asect) & (SEC_ALLOC | SEC_LOAD) |
&& oidx < end - start) |
{ |
sap->other[oidx].addr = stp->addr; |
- sap->other[oidx].name |
- = xstrdup (bfd_section_name (stp->bfd, stp->the_bfd_section)); |
- sap->other[oidx].sectindex = stp->the_bfd_section->index; |
+ sap->other[oidx].name = xstrdup (bfd_section_name (abfd, asect)); |
+ sap->other[oidx].sectindex = gdb_bfd_section_index (abfd, asect); |
oidx++; |
} |
} |
+ sap->num_sections = oidx; |
+ |
return sap; |
} |
@@ -317,9 +271,12 @@ build_section_addr_info_from_bfd (bfd *abfd) |
{ |
sap->other[i].addr = bfd_get_section_vma (abfd, sec); |
sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec)); |
- sap->other[i].sectindex = sec->index; |
+ sap->other[i].sectindex = gdb_bfd_section_index (abfd, sec); |
i++; |
} |
+ |
+ sap->num_sections = i; |
+ |
return sap; |
} |
@@ -335,7 +292,7 @@ build_section_addr_info_from_objfile (const struct objfile *objfile) |
gdb_assert (objfile->num_sections == bfd_count_sections (objfile->obfd)); |
*/ |
sap = build_section_addr_info_from_bfd (objfile->obfd); |
- for (i = 0; i < sap->num_sections && sap->other[i].name; i++) |
+ for (i = 0; i < sap->num_sections; i++) |
{ |
int sectindex = sap->other[i].sectindex; |
@@ -352,13 +309,12 @@ free_section_addr_info (struct section_addr_info *sap) |
int idx; |
for (idx = 0; idx < sap->num_sections; idx++) |
- if (sap->other[idx].name) |
- xfree (sap->other[idx].name); |
+ xfree (sap->other[idx].name); |
xfree (sap); |
} |
- |
/* Initialize OBJFILE's sect_index_* members. */ |
+ |
static void |
init_objfile_sect_indices (struct objfile *objfile) |
{ |
@@ -442,7 +398,7 @@ place_section (bfd *abfd, asection *sect, void *obj) |
return; |
/* If the user specified an offset, honor it. */ |
- if (offsets[sect->index] != 0) |
+ if (offsets[gdb_bfd_section_index (abfd, sect)] != 0) |
return; |
/* Otherwise, let's try to find a place for the section. */ |
@@ -486,7 +442,7 @@ place_section (bfd *abfd, asection *sect, void *obj) |
} |
while (!done); |
- offsets[sect->index] = start_addr; |
+ offsets[gdb_bfd_section_index (abfd, sect)] = start_addr; |
arg->lowest = start_addr + bfd_get_section_size (sect); |
} |
@@ -497,16 +453,16 @@ place_section (bfd *abfd, asection *sect, void *obj) |
void |
relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, |
int num_sections, |
- struct section_addr_info *addrs) |
+ const struct section_addr_info *addrs) |
{ |
int i; |
memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections)); |
/* Now calculate offsets for section that were specified by the caller. */ |
- for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) |
+ for (i = 0; i < addrs->num_sections; i++) |
{ |
- struct other_sections *osp; |
+ const struct other_sections *osp; |
osp = &addrs->other[i]; |
if (osp->sectindex == -1) |
@@ -564,7 +520,7 @@ addrs_section_sort (struct section_addr_info *addrs) |
/* `+ 1' for the NULL terminator. */ |
array = xmalloc (sizeof (*array) * (addrs->num_sections + 1)); |
- for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) |
+ for (i = 0; i < addrs->num_sections; i++) |
array[i] = &addrs->other[i]; |
array[i] = NULL; |
@@ -663,7 +619,7 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) |
(the loadable section directly below it in memory). |
this_offset = lower_offset = lower_addr - lower_orig_addr */ |
- for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++) |
+ for (i = 0; i < addrs->num_sections; i++) |
{ |
struct other_sections *sect = addrs_to_abfd_addrs[i]; |
@@ -728,9 +684,9 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) |
void |
default_symfile_offsets (struct objfile *objfile, |
- struct section_addr_info *addrs) |
+ const struct section_addr_info *addrs) |
{ |
- objfile->num_sections = bfd_count_sections (objfile->obfd); |
+ objfile->num_sections = gdb_bfd_count_sections (objfile->obfd); |
objfile->section_offsets = (struct section_offsets *) |
obstack_alloc (&objfile->objfile_obstack, |
SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); |
@@ -810,7 +766,6 @@ default_symfile_offsets (struct objfile *objfile, |
init_objfile_sect_indices (objfile); |
} |
- |
/* Divide the file into segments, which are individual relocatable units. |
This is the default version of the sym_fns.sym_segments function for |
symbol readers that do not have an explicit representation of segments. |
@@ -875,9 +830,92 @@ default_symfile_segments (bfd *abfd) |
return data; |
} |
+/* This is a convenience function to call sym_read for OBJFILE and |
+ possibly force the partial symbols to be read. */ |
+ |
+static void |
+read_symbols (struct objfile *objfile, int add_flags) |
+{ |
+ (*objfile->sf->sym_read) (objfile, add_flags); |
+ |
+ /* find_separate_debug_file_in_section should be called only if there is |
+ single binary with no existing separate debug info file. */ |
+ if (!objfile_has_partial_symbols (objfile) |
+ && objfile->separate_debug_objfile == NULL |
+ && objfile->separate_debug_objfile_backlink == NULL) |
+ { |
+ bfd *abfd = find_separate_debug_file_in_section (objfile); |
+ struct cleanup *cleanup = make_cleanup_bfd_unref (abfd); |
+ |
+ if (abfd != NULL) |
+ { |
+ /* find_separate_debug_file_in_section uses the same filename for the |
+ virtual section-as-bfd like the bfd filename containing the |
+ section. Therefore use also non-canonical name form for the same |
+ file containing the section. */ |
+ symbol_file_add_separate (abfd, objfile->original_name, add_flags, |
+ objfile); |
+ } |
+ |
+ do_cleanups (cleanup); |
+ } |
+ if ((add_flags & SYMFILE_NO_READ) == 0) |
+ require_partial_symbols (objfile, 0); |
+} |
+ |
+/* Initialize entry point information for this objfile. */ |
+ |
+static void |
+init_entry_point_info (struct objfile *objfile) |
+{ |
+ /* Save startup file's range of PC addresses to help blockframe.c |
+ decide where the bottom of the stack is. */ |
+ |
+ if (bfd_get_file_flags (objfile->obfd) & EXEC_P) |
+ { |
+ /* Executable file -- record its entry point so we'll recognize |
+ the startup file because it contains the entry point. */ |
+ objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); |
+ objfile->ei.entry_point_p = 1; |
+ } |
+ else if (bfd_get_file_flags (objfile->obfd) & DYNAMIC |
+ && bfd_get_start_address (objfile->obfd) != 0) |
+ { |
+ /* Some shared libraries may have entry points set and be |
+ runnable. There's no clear way to indicate this, so just check |
+ for values other than zero. */ |
+ objfile->ei.entry_point = bfd_get_start_address (objfile->obfd); |
+ objfile->ei.entry_point_p = 1; |
+ } |
+ else |
+ { |
+ /* Examination of non-executable.o files. Short-circuit this stuff. */ |
+ objfile->ei.entry_point_p = 0; |
+ } |
+ |
+ if (objfile->ei.entry_point_p) |
+ { |
+ CORE_ADDR entry_point = objfile->ei.entry_point; |
+ |
+ /* Make certain that the address points at real code, and not a |
+ function descriptor. */ |
+ entry_point |
+ = gdbarch_convert_from_func_ptr_addr (get_objfile_arch (objfile), |
+ entry_point, |
+ ¤t_target); |
+ |
+ /* Remove any ISA markers, so that this matches entries in the |
+ symbol table. */ |
+ objfile->ei.entry_point |
+ = gdbarch_addr_bits_remove (get_objfile_arch (objfile), entry_point); |
+ } |
+} |
+ |
/* Process a symbol file, as either the main file or as a dynamically |
loaded file. |
+ This function does not set the OBJFILE's entry-point info. |
+ |
OBJFILE is where the symbols are to be read from. |
ADDRS is the list of section load addresses. If the user has given |
@@ -889,58 +927,50 @@ default_symfile_segments (bfd *abfd) |
into an offset from the section VMA's as it appears in the object |
file, and then call the file's sym_offsets function to convert this |
into a format-specific offset table --- a `struct section_offsets'. |
- If ADDRS is non-zero, OFFSETS must be zero. |
- |
- OFFSETS is a table of section offsets already in the right |
- format-specific representation. NUM_OFFSETS is the number of |
- elements present in OFFSETS->offsets. If OFFSETS is non-zero, we |
- assume this is the proper table the call to sym_offsets described |
- above would produce. Instead of calling sym_offsets, we just dump |
- it right into objfile->section_offsets. (When we're re-reading |
- symbols from an objfile, we don't have the original load address |
- list any more; all we have is the section offset table.) If |
- OFFSETS is non-zero, ADDRS must be zero. |
ADD_FLAGS encodes verbosity level, whether this is main symbol or |
an extra symbol file such as dynamically loaded code, and wether |
breakpoint reset should be deferred. */ |
-void |
-syms_from_objfile (struct objfile *objfile, |
- struct section_addr_info *addrs, |
- struct section_offsets *offsets, |
- int num_offsets, |
- int add_flags) |
+static void |
+syms_from_objfile_1 (struct objfile *objfile, |
+ struct section_addr_info *addrs, |
+ int add_flags) |
{ |
struct section_addr_info *local_addr = NULL; |
struct cleanup *old_chain; |
const int mainline = add_flags & SYMFILE_MAINLINE; |
- gdb_assert (! (addrs && offsets)); |
- |
- init_entry_point_info (objfile); |
- objfile->sf = find_sym_fns (objfile->obfd); |
+ objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd)); |
if (objfile->sf == NULL) |
- return; /* No symbols. */ |
+ { |
+ /* No symbols to load, but we still need to make sure |
+ that the section_offsets table is allocated. */ |
+ int num_sections = gdb_bfd_count_sections (objfile->obfd); |
+ size_t size = SIZEOF_N_SECTION_OFFSETS (num_sections); |
+ |
+ objfile->num_sections = num_sections; |
+ objfile->section_offsets |
+ = obstack_alloc (&objfile->objfile_obstack, size); |
+ memset (objfile->section_offsets, 0, size); |
+ return; |
+ } |
/* Make sure that partially constructed symbol tables will be cleaned up |
if an error occurs during symbol reading. */ |
old_chain = make_cleanup_free_objfile (objfile); |
- /* If ADDRS and OFFSETS are both NULL, put together a dummy address |
- list. We now establish the convention that an addr of zero means |
+ /* If ADDRS is NULL, put together a dummy address list. |
+ We now establish the convention that an addr of zero means |
no load address was specified. */ |
- if (! addrs && ! offsets) |
+ if (! addrs) |
{ |
- local_addr |
- = alloc_section_addr_info (bfd_count_sections (objfile->obfd)); |
+ local_addr = alloc_section_addr_info (1); |
make_cleanup (xfree, local_addr); |
addrs = local_addr; |
} |
- /* Now either addrs or offsets is non-zero. */ |
- |
if (mainline) |
{ |
/* We will modify the main symbol table, make sure that all its users |
@@ -969,7 +999,7 @@ syms_from_objfile (struct objfile *objfile, |
We no longer warn if the lowest section is not a text segment (as |
happens for the PA64 port. */ |
- if (addrs && addrs->other[0].name) |
+ if (addrs->num_sections > 0) |
addr_info_make_relative (addrs, objfile->obfd); |
/* Initialize symbol reading routines for this objfile, allow complaints to |
@@ -979,26 +1009,9 @@ syms_from_objfile (struct objfile *objfile, |
(*objfile->sf->sym_init) (objfile); |
clear_complaints (&symfile_complaints, 1, add_flags & SYMFILE_VERBOSE); |
- if (addrs) |
- (*objfile->sf->sym_offsets) (objfile, addrs); |
- else |
- { |
- size_t size = SIZEOF_N_SECTION_OFFSETS (num_offsets); |
- |
- /* Just copy in the offset table directly as given to us. */ |
- objfile->num_sections = num_offsets; |
- objfile->section_offsets |
- = ((struct section_offsets *) |
- obstack_alloc (&objfile->objfile_obstack, size)); |
- memcpy (objfile->section_offsets, offsets, size); |
- |
- init_objfile_sect_indices (objfile); |
- } |
- |
- (*objfile->sf->sym_read) (objfile, add_flags); |
+ (*objfile->sf->sym_offsets) (objfile, addrs); |
- if ((add_flags & SYMFILE_NO_READ) == 0) |
- require_partial_symbols (objfile, 0); |
+ read_symbols (objfile, add_flags); |
/* Discard cleanups as symbol reading was successful. */ |
@@ -1006,6 +1019,18 @@ syms_from_objfile (struct objfile *objfile, |
xfree (local_addr); |
} |
+/* Same as syms_from_objfile_1, but also initializes the objfile |
+ entry-point info. */ |
+ |
+static void |
+syms_from_objfile (struct objfile *objfile, |
+ struct section_addr_info *addrs, |
+ int add_flags) |
+{ |
+ syms_from_objfile_1 (objfile, addrs, add_flags); |
+ init_entry_point_info (objfile); |
+} |
+ |
/* Perform required actions after either reading in the initial |
symbols for a new objfile, or mapping in the symbols from a reusable |
objfile. ADD_FLAGS is a bitmask of enum symfile_add_flags. */ |
@@ -1036,13 +1061,14 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) |
loaded file. |
ABFD is a BFD already open on the file, as from symfile_bfd_open. |
- This BFD will be closed on error, and is always consumed by this function. |
+ A new reference is acquired by this function. |
+ |
+ For NAME description see allocate_objfile's definition. |
ADD_FLAGS encodes verbosity, whether this is main symbol file or |
extra, such as dynamically loaded code, and what to do with breakpoins. |
- ADDRS, OFFSETS, and NUM_OFFSETS are as described for |
- syms_from_objfile, above. |
+ ADDRS is as described for syms_from_objfile_1, above. |
ADDRS is ignored when SYMFILE_MAINLINE bit is set in ADD_FLAGS. |
PARENT is the original objfile if ABFD is a separate debug info file. |
@@ -1052,16 +1078,11 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) |
Upon failure, jumps back to command level (never returns). */ |
static struct objfile * |
-symbol_file_add_with_addrs_or_offsets (bfd *abfd, |
- int add_flags, |
- struct section_addr_info *addrs, |
- struct section_offsets *offsets, |
- int num_offsets, |
- int flags, struct objfile *parent) |
+symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags, |
+ struct section_addr_info *addrs, |
+ int flags, struct objfile *parent) |
{ |
struct objfile *objfile; |
- struct cleanup *my_cleanups; |
- const char *name = bfd_get_filename (abfd); |
const int from_tty = add_flags & SYMFILE_VERBOSE; |
const int mainline = add_flags & SYMFILE_MAINLINE; |
const int should_print = ((from_tty || info_verbose) |
@@ -1074,8 +1095,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, |
add_flags &= ~SYMFILE_NO_READ; |
} |
- my_cleanups = make_cleanup_bfd_close (abfd); |
- |
/* Give user a chance to burp if we'd be |
interactively wiping out any existing symbols. */ |
@@ -1085,8 +1104,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, |
&& !query (_("Load new symbol table from \"%s\"? "), name)) |
error (_("Not confirmed.")); |
- objfile = allocate_objfile (abfd, flags | (mainline ? OBJF_MAINLINE : 0)); |
- discard_cleanups (my_cleanups); |
+ objfile = allocate_objfile (abfd, name, |
+ flags | (mainline ? OBJF_MAINLINE : 0)); |
if (parent) |
add_separate_debug_objfile (objfile, parent); |
@@ -1105,8 +1124,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, |
gdb_flush (gdb_stdout); |
} |
} |
- syms_from_objfile (objfile, addrs, offsets, num_offsets, |
- add_flags); |
+ syms_from_objfile (objfile, addrs, add_flags); |
/* We now have at least a partial symbol table. Check to see if the |
user requested that all symbols be read on initial access via either |
@@ -1160,10 +1178,12 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, |
return (objfile); |
} |
-/* Add BFD as a separate debug file for OBJFILE. */ |
+/* Add BFD as a separate debug file for OBJFILE. For NAME description |
+ see allocate_objfile's definition. */ |
void |
-symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile) |
+symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags, |
+ struct objfile *objfile) |
{ |
struct objfile *new_objfile; |
struct section_addr_info *sap; |
@@ -1175,9 +1195,8 @@ symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile) |
sap = build_section_addr_info_from_objfile (objfile); |
my_cleanup = make_cleanup_free_section_addr_info (sap); |
- new_objfile = symbol_file_add_with_addrs_or_offsets |
- (bfd, symfile_flags, |
- sap, NULL, 0, |
+ new_objfile = symbol_file_add_with_addrs |
+ (bfd, name, symfile_flags, sap, |
objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW |
| OBJF_USERLOADED), |
objfile); |
@@ -1187,30 +1206,32 @@ symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile) |
/* Process the symbol file ABFD, as either the main file or as a |
dynamically loaded file. |
+ See symbol_file_add_with_addrs's comments for details. */ |
- See symbol_file_add_with_addrs_or_offsets's comments for |
- details. */ |
struct objfile * |
-symbol_file_add_from_bfd (bfd *abfd, int add_flags, |
+symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags, |
struct section_addr_info *addrs, |
int flags, struct objfile *parent) |
{ |
- return symbol_file_add_with_addrs_or_offsets (abfd, add_flags, addrs, 0, 0, |
- flags, parent); |
+ return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags, |
+ parent); |
} |
- |
/* Process a symbol file, as either the main file or as a dynamically |
- loaded file. See symbol_file_add_with_addrs_or_offsets's comments |
- for details. */ |
+ loaded file. See symbol_file_add_with_addrs's comments for details. */ |
+ |
struct objfile * |
-symbol_file_add (char *name, int add_flags, struct section_addr_info *addrs, |
- int flags) |
+symbol_file_add (const char *name, int add_flags, |
+ struct section_addr_info *addrs, int flags) |
{ |
- return symbol_file_add_from_bfd (symfile_bfd_open (name), add_flags, addrs, |
- flags, NULL); |
-} |
+ bfd *bfd = symfile_bfd_open (name); |
+ struct cleanup *cleanup = make_cleanup_bfd_unref (bfd); |
+ struct objfile *objf; |
+ objf = symbol_file_add_from_bfd (bfd, name, add_flags, addrs, flags, NULL); |
+ do_cleanups (cleanup); |
+ return objf; |
+} |
/* Call symbol_file_add() with default values and update whatever is |
affected by the loading of a new main(). |
@@ -1221,13 +1242,13 @@ symbol_file_add (char *name, int add_flags, struct section_addr_info *addrs, |
command itself. */ |
void |
-symbol_file_add_main (char *args, int from_tty) |
+symbol_file_add_main (const char *args, int from_tty) |
{ |
symbol_file_add_main_1 (args, from_tty, 0); |
} |
static void |
-symbol_file_add_main_1 (char *args, int from_tty, int flags) |
+symbol_file_add_main_1 (const char *args, int from_tty, int flags) |
{ |
const int add_flags = (current_inferior ()->symfile_flags |
| SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0)); |
@@ -1249,7 +1270,7 @@ symbol_file_clear (int from_tty) |
&& from_tty |
&& (symfile_objfile |
? !query (_("Discard symbol table from `%s'? "), |
- symfile_objfile->name) |
+ objfile_name (symfile_objfile)) |
: !query (_("Discard symbol table? ")))) |
error (_("Not confirmed.")); |
@@ -1264,73 +1285,6 @@ symbol_file_clear (int from_tty) |
printf_unfiltered (_("No symbol file now.\n")); |
} |
-static char * |
-get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out) |
-{ |
- asection *sect; |
- bfd_size_type debuglink_size; |
- unsigned long crc32; |
- char *contents; |
- int crc_offset; |
- |
- sect = bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink"); |
- |
- if (sect == NULL) |
- return NULL; |
- |
- debuglink_size = bfd_section_size (objfile->obfd, sect); |
- |
- contents = xmalloc (debuglink_size); |
- bfd_get_section_contents (objfile->obfd, sect, contents, |
- (file_ptr)0, (bfd_size_type)debuglink_size); |
- |
- /* Crc value is stored after the filename, aligned up to 4 bytes. */ |
- crc_offset = strlen (contents) + 1; |
- crc_offset = (crc_offset + 3) & ~3; |
- |
- crc32 = bfd_get_32 (objfile->obfd, (bfd_byte *) (contents + crc_offset)); |
- |
- *crc32_out = crc32; |
- return contents; |
-} |
- |
-/* Return 32-bit CRC for ABFD. If successful store it to *FILE_CRC_RETURN and |
- return 1. Otherwise print a warning and return 0. ABFD seek position is |
- not preserved. */ |
- |
-static int |
-get_file_crc (bfd *abfd, unsigned long *file_crc_return) |
-{ |
- unsigned long file_crc = 0; |
- |
- if (bfd_seek (abfd, 0, SEEK_SET) != 0) |
- { |
- warning (_("Problem reading \"%s\" for CRC: %s"), |
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); |
- return 0; |
- } |
- |
- for (;;) |
- { |
- gdb_byte buffer[8 * 1024]; |
- bfd_size_type count; |
- |
- count = bfd_bread (buffer, sizeof (buffer), abfd); |
- if (count == (bfd_size_type) -1) |
- { |
- warning (_("Problem reading \"%s\" for CRC: %s"), |
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); |
- return 0; |
- } |
- if (count == 0) |
- break; |
- file_crc = gnu_debuglink_crc32 (file_crc, buffer, count); |
- } |
- |
- *file_crc_return = file_crc; |
- return 1; |
-} |
- |
static int |
separate_debug_file_exists (const char *name, unsigned long crc, |
struct objfile *parent_objfile) |
@@ -1347,10 +1301,10 @@ separate_debug_file_exists (const char *name, unsigned long crc, |
".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where |
the separate debug infos with the same basename can exist. */ |
- if (filename_cmp (name, parent_objfile->name) == 0) |
+ if (filename_cmp (name, objfile_name (parent_objfile)) == 0) |
return 0; |
- abfd = bfd_open_maybe_remote (name); |
+ abfd = gdb_bfd_open_maybe_remote (name); |
if (!abfd) |
return 0; |
@@ -1372,7 +1326,7 @@ separate_debug_file_exists (const char *name, unsigned long crc, |
if (abfd_stat.st_dev == parent_stat.st_dev |
&& abfd_stat.st_ino == parent_stat.st_ino) |
{ |
- bfd_close (abfd); |
+ gdb_bfd_unref (abfd); |
return 0; |
} |
verified_as_different = 1; |
@@ -1380,31 +1334,31 @@ separate_debug_file_exists (const char *name, unsigned long crc, |
else |
verified_as_different = 0; |
- file_crc_p = get_file_crc (abfd, &file_crc); |
+ file_crc_p = gdb_bfd_crc (abfd, &file_crc); |
- bfd_close (abfd); |
+ gdb_bfd_unref (abfd); |
if (!file_crc_p) |
return 0; |
if (crc != file_crc) |
{ |
+ unsigned long parent_crc; |
+ |
/* If one (or both) the files are accessed for example the via "remote:" |
gdbserver way it does not support the bfd_stat operation. Verify |
whether those two files are not the same manually. */ |
- if (!verified_as_different && !parent_objfile->crc32_p) |
+ if (!verified_as_different) |
{ |
- parent_objfile->crc32_p = get_file_crc (parent_objfile->obfd, |
- &parent_objfile->crc32); |
- if (!parent_objfile->crc32_p) |
+ if (!gdb_bfd_crc (parent_objfile->obfd, &parent_crc)) |
return 0; |
} |
- if (verified_as_different || parent_objfile->crc32 != file_crc) |
+ if (verified_as_different || parent_crc != file_crc) |
warning (_("the debug information found in \"%s\"" |
" does not match \"%s\" (CRC mismatch).\n"), |
- name, parent_objfile->name); |
+ name, objfile_name (parent_objfile)); |
return 0; |
} |
@@ -1430,7 +1384,9 @@ show_debug_file_directory (struct ui_file *file, int from_tty, |
/* Find a separate debuginfo file for OBJFILE, using DIR as the directory |
where the original file resides (may not be the same as |
dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are |
- looking for. Returns the name of the debuginfo, of NULL. */ |
+ looking for. CANON_DIR is the "realpath" form of DIR. |
+ DIR must contain a trailing '/'. |
+ Returns the path of the file with separate debug info, of NULL. */ |
static char * |
find_separate_debug_file (const char *dir, |
@@ -1489,7 +1445,10 @@ find_separate_debug_file (const char *dir, |
strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- return debugfile; |
+ { |
+ do_cleanups (back_to); |
+ return debugfile; |
+ } |
/* If the file is in the sysroot, try using its base path in the |
global debugfile directory. */ |
@@ -1504,7 +1463,10 @@ find_separate_debug_file (const char *dir, |
strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- return debugfile; |
+ { |
+ do_cleanups (back_to); |
+ return debugfile; |
+ } |
} |
} |
@@ -1513,7 +1475,7 @@ find_separate_debug_file (const char *dir, |
return NULL; |
} |
-/* Modify PATH to contain only "directory/" part of PATH. |
+/* Modify PATH to contain only "[/]directory/" part of PATH. |
If there were no directory separators in PATH, PATH will be empty |
string on return. */ |
@@ -1544,7 +1506,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) |
unsigned long crc32; |
struct cleanup *cleanups; |
- debuglink = get_debug_link_info (objfile, &crc32); |
+ debuglink = bfd_get_debug_link_info (objfile->obfd, &crc32); |
if (debuglink == NULL) |
{ |
@@ -1554,7 +1516,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) |
} |
cleanups = make_cleanup (xfree, debuglink); |
- dir = xstrdup (objfile->name); |
+ dir = xstrdup (objfile_name (objfile)); |
make_cleanup (xfree, dir); |
terminate_after_last_dir_separator (dir); |
canon_dir = lrealpath (dir); |
@@ -1571,11 +1533,12 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) |
struct stat st_buf; |
- if (lstat (objfile->name, &st_buf) == 0 && S_ISLNK(st_buf.st_mode)) |
+ if (lstat (objfile_name (objfile), &st_buf) == 0 |
+ && S_ISLNK (st_buf.st_mode)) |
{ |
char *symlink_dir; |
- symlink_dir = lrealpath (objfile->name); |
+ symlink_dir = lrealpath (objfile_name (objfile)); |
if (symlink_dir != NULL) |
{ |
make_cleanup (xfree, symlink_dir); |
@@ -1598,7 +1561,6 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile) |
return debugfile; |
} |
- |
/* This is the symbol-file command. Read the file, analyze its |
symbols, and add a struct symtab to a symtab list. The syntax of |
the command is rather bizarre: |
@@ -1672,11 +1634,11 @@ set_initial_language (void) |
lang = language_of_main; |
else |
{ |
- const char *filename; |
+ char *name = main_name (); |
+ struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL); |
- filename = find_main_filename (); |
- if (filename != NULL) |
- lang = deduce_language_from_filename (filename); |
+ if (sym != NULL) |
+ lang = SYMBOL_LANGUAGE (sym); |
} |
if (lang == language_unknown) |
@@ -1690,17 +1652,21 @@ set_initial_language (void) |
} |
/* If NAME is a remote name open the file using remote protocol, otherwise |
- open it normally. */ |
+ open it normally. Returns a new reference to the BFD. On error, |
+ returns NULL with the BFD error set. */ |
bfd * |
-bfd_open_maybe_remote (const char *name) |
+gdb_bfd_open_maybe_remote (const char *name) |
{ |
+ bfd *result; |
+ |
if (remote_filename_p (name)) |
- return remote_bfd_open (name, gnutarget); |
+ result = remote_bfd_open (name, gnutarget); |
else |
- return bfd_openr (name, gnutarget); |
-} |
+ result = gdb_bfd_open (name, gnutarget, -1); |
+ return result; |
+} |
/* Open the file specified by NAME and hand it off to BFD for |
preliminary analysis. Return a newly initialized bfd *, which |
@@ -1708,38 +1674,34 @@ bfd_open_maybe_remote (const char *name) |
absolute). In case of trouble, error() is called. */ |
bfd * |
-symfile_bfd_open (char *name) |
+symfile_bfd_open (const char *cname) |
{ |
bfd *sym_bfd; |
int desc; |
- char *absolute_name; |
+ char *name, *absolute_name; |
+ struct cleanup *back_to; |
- if (remote_filename_p (name)) |
+ if (remote_filename_p (cname)) |
{ |
- name = xstrdup (name); |
- sym_bfd = remote_bfd_open (name, gnutarget); |
+ sym_bfd = remote_bfd_open (cname, gnutarget); |
if (!sym_bfd) |
- { |
- make_cleanup (xfree, name); |
- error (_("`%s': can't open to read symbols: %s."), name, |
- bfd_errmsg (bfd_get_error ())); |
- } |
+ error (_("`%s': can't open to read symbols: %s."), cname, |
+ bfd_errmsg (bfd_get_error ())); |
if (!bfd_check_format (sym_bfd, bfd_object)) |
{ |
- bfd_close (sym_bfd); |
- make_cleanup (xfree, name); |
- error (_("`%s': can't read symbols: %s."), name, |
+ make_cleanup_bfd_unref (sym_bfd); |
+ error (_("`%s': can't read symbols: %s."), cname, |
bfd_errmsg (bfd_get_error ())); |
} |
return sym_bfd; |
} |
- name = tilde_expand (name); /* Returns 1st new malloc'd copy. */ |
+ name = tilde_expand (cname); /* Returns 1st new malloc'd copy. */ |
/* Look down path for it, allocate 2nd new malloc'd copy. */ |
- desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, name, |
+ desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, name, |
O_RDONLY | O_BINARY, &absolute_name); |
#if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__) |
if (desc < 0) |
@@ -1747,8 +1709,8 @@ symfile_bfd_open (char *name) |
char *exename = alloca (strlen (name) + 5); |
strcat (strcpy (exename, name), ".exe"); |
- desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename, |
- O_RDONLY | O_BINARY, &absolute_name); |
+ desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, |
+ exename, O_RDONLY | O_BINARY, &absolute_name); |
} |
#endif |
if (desc < 0) |
@@ -1757,33 +1719,24 @@ symfile_bfd_open (char *name) |
perror_with_name (name); |
} |
- /* Free 1st new malloc'd copy, but keep the 2nd malloc'd copy in |
- bfd. It'll be freed in free_objfile(). */ |
xfree (name); |
name = absolute_name; |
+ back_to = make_cleanup (xfree, name); |
- sym_bfd = bfd_fopen (name, gnutarget, FOPEN_RB, desc); |
+ sym_bfd = gdb_bfd_open (name, gnutarget, desc); |
if (!sym_bfd) |
- { |
- make_cleanup (xfree, name); |
- error (_("`%s': can't open to read symbols: %s."), name, |
- bfd_errmsg (bfd_get_error ())); |
- } |
+ error (_("`%s': can't open to read symbols: %s."), name, |
+ bfd_errmsg (bfd_get_error ())); |
bfd_set_cacheable (sym_bfd, 1); |
if (!bfd_check_format (sym_bfd, bfd_object)) |
{ |
- /* FIXME: should be checking for errors from bfd_close (for one |
- thing, on error it does not free all the storage associated |
- with the bfd). */ |
- bfd_close (sym_bfd); /* This also closes desc. */ |
- make_cleanup (xfree, name); |
+ make_cleanup_bfd_unref (sym_bfd); |
error (_("`%s': can't read symbols: %s."), name, |
bfd_errmsg (bfd_get_error ())); |
} |
- /* bfd_usrdata exists for applications and libbfd must not touch it. */ |
- gdb_assert (bfd_usrdata (sym_bfd) == NULL); |
+ do_cleanups (back_to); |
return sym_bfd; |
} |
@@ -1802,14 +1755,18 @@ get_section_index (struct objfile *objfile, char *section_name) |
return -1; |
} |
-/* Link SF into the global symtab_fns list. Called on startup by the |
- _initialize routine in each object file format reader, to register |
- information about each format the reader is prepared to handle. */ |
+/* Link SF into the global symtab_fns list. |
+ FLAVOUR is the file format that SF handles. |
+ Called on startup by the _initialize routine in each object file format |
+ reader, to register information about each format the reader is prepared |
+ to handle. */ |
void |
-add_symtab_fns (const struct sym_fns *sf) |
+add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf) |
{ |
- VEC_safe_push (sym_fns_ptr, symtab_fns, sf); |
+ registered_sym_fns fns = { flavour, sf }; |
+ |
+ VEC_safe_push (registered_sym_fns, symtab_fns, &fns); |
} |
/* Initialize OBJFILE to read symbols from its associated BFD. It |
@@ -1820,7 +1777,7 @@ add_symtab_fns (const struct sym_fns *sf) |
static const struct sym_fns * |
find_sym_fns (bfd *abfd) |
{ |
- const struct sym_fns *sf; |
+ registered_sym_fns *rsf; |
enum bfd_flavour our_flavour = bfd_get_flavour (abfd); |
int i; |
@@ -1829,9 +1786,9 @@ find_sym_fns (bfd *abfd) |
|| our_flavour == bfd_target_tekhex_flavour) |
return NULL; /* No symbols. */ |
- for (i = 0; VEC_iterate (sym_fns_ptr, symtab_fns, i, sf); ++i) |
- if (our_flavour == sf->sym_flavour) |
- return sf; |
+ for (i = 0; VEC_iterate (registered_sym_fns, symtab_fns, i, rsf); ++i) |
+ if (our_flavour == rsf->sym_flavour) |
+ return rsf->sym_fns; |
error (_("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown."), |
bfd_get_target (abfd)); |
@@ -1843,6 +1800,8 @@ find_sym_fns (bfd *abfd) |
static void |
load_command (char *arg, int from_tty) |
{ |
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); |
+ |
dont_repeat (); |
/* The user might be reloading because the binary has changed. Take |
@@ -1892,6 +1851,8 @@ load_command (char *arg, int from_tty) |
/* After re-loading the executable, we don't really know which |
overlays are mapped any more. */ |
overlay_cache_invalid = 1; |
+ |
+ do_cleanups (cleanup); |
} |
/* This version of "load" should be usable for any target. Currently |
@@ -1917,7 +1878,7 @@ add_section_size_callback (bfd *abfd, asection *asec, void *data) |
/* Opaque data for load_section_callback. */ |
struct load_section_data { |
- unsigned long load_offset; |
+ CORE_ADDR load_offset; |
struct load_progress_data *progress_data; |
VEC(memory_write_request_s) *requests; |
}; |
@@ -1963,7 +1924,7 @@ load_progress (ULONGEST bytes, void *untyped_arg) |
this section. */ |
ui_out_message (current_uiout, 0, "Loading section %s, size %s lma %s\n", |
args->section_name, hex_string (args->section_size), |
- paddress (target_gdbarch, args->lma)); |
+ paddress (target_gdbarch (), args->lma)); |
return; |
} |
@@ -1981,10 +1942,10 @@ load_progress (ULONGEST bytes, void *untyped_arg) |
if (target_read_memory (args->lma, check, bytes) != 0) |
error (_("Download verify read failed at %s"), |
- paddress (target_gdbarch, args->lma)); |
+ paddress (target_gdbarch (), args->lma)); |
if (memcmp (args->buffer, check, bytes) != 0) |
error (_("Download verify compare failed at %s"), |
- paddress (target_gdbarch, args->lma)); |
+ paddress (target_gdbarch (), args->lma)); |
do_cleanups (verify_cleanups); |
} |
totals->data_count += bytes; |
@@ -1992,7 +1953,7 @@ load_progress (ULONGEST bytes, void *untyped_arg) |
args->buffer += bytes; |
totals->write_count += 1; |
args->section_sent += bytes; |
- if (quit_flag |
+ if (check_quit_flag () |
|| (deprecated_ui_load_progress_hook != NULL |
&& deprecated_ui_load_progress_hook (args->section_name, |
args->section_sent))) |
@@ -2095,9 +2056,9 @@ generic_load (char *args, int from_tty) |
if (argv[1] != NULL) |
{ |
- char *endptr; |
+ const char *endptr; |
- cbdata.load_offset = strtoul (argv[1], &endptr, 0); |
+ cbdata.load_offset = strtoulst (argv[1], &endptr, 0); |
/* If the last word was not a valid number then |
treat it as a file name with spaces in. */ |
@@ -2109,17 +2070,14 @@ generic_load (char *args, int from_tty) |
} |
/* Open the file for loading. */ |
- loadfile_bfd = bfd_openr (filename, gnutarget); |
+ loadfile_bfd = gdb_bfd_open (filename, gnutarget, -1); |
if (loadfile_bfd == NULL) |
{ |
perror_with_name (filename); |
return; |
} |
- /* FIXME: should be checking for errors from bfd_close (for one thing, |
- on error it does not free all the storage associated with the |
- bfd). */ |
- make_cleanup_bfd_close (loadfile_bfd); |
+ make_cleanup_bfd_unref (loadfile_bfd); |
if (!bfd_check_format (loadfile_bfd, bfd_object)) |
{ |
@@ -2141,8 +2099,9 @@ generic_load (char *args, int from_tty) |
gettimeofday (&end_time, NULL); |
entry = bfd_get_start_address (loadfile_bfd); |
+ entry = gdbarch_addr_bits_remove (target_gdbarch (), entry); |
ui_out_text (uiout, "Start address "); |
- ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch, entry)); |
+ ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch (), entry)); |
ui_out_text (uiout, ", load size "); |
ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count); |
ui_out_text (uiout, "\n"); |
@@ -2175,24 +2134,6 @@ generic_load (char *args, int from_tty) |
/* Report how fast the transfer went. */ |
-/* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being |
- replaced by print_transfer_performance (with a very different |
- function signature). */ |
- |
-void |
-report_transfer_performance (unsigned long data_count, time_t start_time, |
- time_t end_time) |
-{ |
- struct timeval start, end; |
- |
- start.tv_sec = start_time; |
- start.tv_usec = 0; |
- end.tv_sec = end_time; |
- end.tv_usec = 0; |
- |
- print_transfer_performance (gdb_stdout, data_count, 0, &start, &end); |
-} |
- |
void |
print_transfer_performance (struct ui_file *stream, |
unsigned long data_count, |
@@ -2266,6 +2207,7 @@ add_symbol_file_command (char *args, int from_tty) |
int expecting_sec_name = 0; |
int expecting_sec_addr = 0; |
char **argv; |
+ struct objfile *objf; |
struct sect_opt |
{ |
@@ -2299,63 +2241,54 @@ add_symbol_file_command (char *args, int from_tty) |
filename = tilde_expand (arg); |
make_cleanup (xfree, filename); |
} |
+ else if (argcnt == 1) |
+ { |
+ /* The second argument is always the text address at which |
+ to load the program. */ |
+ sect_opts[section_index].name = ".text"; |
+ sect_opts[section_index].value = arg; |
+ if (++section_index >= num_sect_opts) |
+ { |
+ num_sect_opts *= 2; |
+ sect_opts = ((struct sect_opt *) |
+ xrealloc (sect_opts, |
+ num_sect_opts |
+ * sizeof (struct sect_opt))); |
+ } |
+ } |
else |
- if (argcnt == 1) |
- { |
- /* The second argument is always the text address at which |
- to load the program. */ |
- sect_opts[section_index].name = ".text"; |
- sect_opts[section_index].value = arg; |
- if (++section_index >= num_sect_opts) |
- { |
- num_sect_opts *= 2; |
- sect_opts = ((struct sect_opt *) |
- xrealloc (sect_opts, |
- num_sect_opts |
- * sizeof (struct sect_opt))); |
- } |
- } |
- else |
- { |
- /* It's an option (starting with '-') or it's an argument |
- to an option. */ |
- |
- if (*arg == '-') |
- { |
- if (strcmp (arg, "-readnow") == 0) |
- flags |= OBJF_READNOW; |
- else if (strcmp (arg, "-s") == 0) |
- { |
- expecting_sec_name = 1; |
- expecting_sec_addr = 1; |
- } |
- } |
- else |
- { |
- if (expecting_sec_name) |
- { |
- sect_opts[section_index].name = arg; |
- expecting_sec_name = 0; |
- } |
- else |
- if (expecting_sec_addr) |
- { |
- sect_opts[section_index].value = arg; |
- expecting_sec_addr = 0; |
- if (++section_index >= num_sect_opts) |
- { |
- num_sect_opts *= 2; |
- sect_opts = ((struct sect_opt *) |
- xrealloc (sect_opts, |
- num_sect_opts |
- * sizeof (struct sect_opt))); |
- } |
- } |
- else |
- error (_("USAGE: add-symbol-file <filename> <textaddress>" |
- " [-readnow] [-s <secname> <addr>]*")); |
- } |
- } |
+ { |
+ /* It's an option (starting with '-') or it's an argument |
+ to an option. */ |
+ if (expecting_sec_name) |
+ { |
+ sect_opts[section_index].name = arg; |
+ expecting_sec_name = 0; |
+ } |
+ else if (expecting_sec_addr) |
+ { |
+ sect_opts[section_index].value = arg; |
+ expecting_sec_addr = 0; |
+ if (++section_index >= num_sect_opts) |
+ { |
+ num_sect_opts *= 2; |
+ sect_opts = ((struct sect_opt *) |
+ xrealloc (sect_opts, |
+ num_sect_opts |
+ * sizeof (struct sect_opt))); |
+ } |
+ } |
+ else if (strcmp (arg, "-readnow") == 0) |
+ flags |= OBJF_READNOW; |
+ else if (strcmp (arg, "-s") == 0) |
+ { |
+ expecting_sec_name = 1; |
+ expecting_sec_addr = 1; |
+ } |
+ else |
+ error (_("USAGE: add-symbol-file <filename> <textaddress>" |
+ " [-readnow] [-s <secname> <addr>]*")); |
+ } |
} |
/* This command takes at least two arguments. The first one is a |
@@ -2396,12 +2329,15 @@ add_symbol_file_command (char *args, int from_tty) |
At this point, we don't know what file type this is, |
so we can't determine what section names are valid. */ |
} |
+ section_addrs->num_sections = sec_num; |
if (from_tty && (!query ("%s", ""))) |
error (_("Not confirmed.")); |
- symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0, |
- section_addrs, flags); |
+ objf = symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0, |
+ section_addrs, flags); |
+ |
+ add_target_sections_of_objfile (objf); |
/* Getting new symbols may change our opinion about what is |
frameless. */ |
@@ -2410,11 +2346,88 @@ add_symbol_file_command (char *args, int from_tty) |
} |
+/* This function removes a symbol file that was added via add-symbol-file. */ |
+ |
+static void |
+remove_symbol_file_command (char *args, int from_tty) |
+{ |
+ char **argv; |
+ struct objfile *objf = NULL; |
+ struct cleanup *my_cleanups; |
+ struct program_space *pspace = current_program_space; |
+ struct gdbarch *gdbarch = get_current_arch (); |
+ |
+ dont_repeat (); |
+ |
+ if (args == NULL) |
+ error (_("remove-symbol-file: no symbol file provided")); |
+ |
+ my_cleanups = make_cleanup (null_cleanup, NULL); |
+ |
+ argv = gdb_buildargv (args); |
+ |
+ if (strcmp (argv[0], "-a") == 0) |
+ { |
+ /* Interpret the next argument as an address. */ |
+ CORE_ADDR addr; |
+ |
+ if (argv[1] == NULL) |
+ error (_("Missing address argument")); |
+ |
+ if (argv[2] != NULL) |
+ error (_("Junk after %s"), argv[1]); |
+ |
+ addr = parse_and_eval_address (argv[1]); |
+ |
+ ALL_OBJFILES (objf) |
+ { |
+ if (objf != 0 |
+ && objf->flags & OBJF_USERLOADED |
+ && objf->pspace == pspace && is_addr_in_objfile (addr, objf)) |
+ break; |
+ } |
+ } |
+ else if (argv[0] != NULL) |
+ { |
+ /* Interpret the current argument as a file name. */ |
+ char *filename; |
+ |
+ if (argv[1] != NULL) |
+ error (_("Junk after %s"), argv[0]); |
+ |
+ filename = tilde_expand (argv[0]); |
+ make_cleanup (xfree, filename); |
+ |
+ ALL_OBJFILES (objf) |
+ { |
+ if (objf != 0 |
+ && objf->flags & OBJF_USERLOADED |
+ && objf->pspace == pspace |
+ && filename_cmp (filename, objfile_name (objf)) == 0) |
+ break; |
+ } |
+ } |
+ |
+ if (objf == NULL) |
+ error (_("No symbol file found")); |
+ |
+ if (from_tty |
+ && !query (_("Remove symbol table from file \"%s\"? "), |
+ objfile_name (objf))) |
+ error (_("Not confirmed.")); |
+ |
+ free_objfile (objf); |
+ clear_symtab_users (0); |
+ |
+ do_cleanups (my_cleanups); |
+} |
+ |
typedef struct objfile *objfilep; |
DEF_VEC_P (objfilep); |
/* Re-read symbols if a symbol-file has changed. */ |
+ |
void |
reread_symbols (void) |
{ |
@@ -2435,7 +2448,6 @@ reread_symbols (void) |
for (objfile = object_files; objfile; objfile = objfile->next) |
{ |
- /* solib-sunos.c creates one objfile with obfd. */ |
if (objfile->obfd == NULL) |
continue; |
@@ -2450,12 +2462,12 @@ reread_symbols (void) |
if (objfile->obfd->my_archive) |
res = stat (objfile->obfd->my_archive->filename, &new_statbuf); |
else |
- res = stat (objfile->name, &new_statbuf); |
+ res = stat (objfile_name (objfile), &new_statbuf); |
if (res != 0) |
{ |
/* FIXME, should use print_sys_errmsg but it's not filtered. */ |
printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), |
- objfile->name); |
+ objfile_name (objfile)); |
continue; |
} |
new_modtime = new_statbuf.st_mtime; |
@@ -2464,10 +2476,10 @@ reread_symbols (void) |
struct cleanup *old_cleanups; |
struct section_offsets *offsets; |
int num_offsets; |
- char *obfd_filename; |
+ char *original_name; |
printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"), |
- objfile->name); |
+ objfile_name (objfile)); |
/* There are various functions like symbol_file_add, |
symfile_bfd_open, syms_from_objfile, etc., which might |
@@ -2515,21 +2527,32 @@ reread_symbols (void) |
clear_objfile_data (objfile); |
- /* Clean up any state BFD has sitting around. We don't need |
- to close the descriptor but BFD lacks a way of closing the |
- BFD without closing the descriptor. */ |
- obfd_filename = bfd_get_filename (objfile->obfd); |
- if (!bfd_close (objfile->obfd)) |
- error (_("Can't close BFD for %s: %s"), objfile->name, |
- bfd_errmsg (bfd_get_error ())); |
- objfile->obfd = bfd_open_maybe_remote (obfd_filename); |
- if (objfile->obfd == NULL) |
- error (_("Can't open %s to read symbols."), objfile->name); |
- else |
- objfile->obfd = gdb_bfd_ref (objfile->obfd); |
+ /* Clean up any state BFD has sitting around. */ |
+ { |
+ struct bfd *obfd = objfile->obfd; |
+ char *obfd_filename; |
+ |
+ obfd_filename = bfd_get_filename (objfile->obfd); |
+ /* Open the new BFD before freeing the old one, so that |
+ the filename remains live. */ |
+ objfile->obfd = gdb_bfd_open_maybe_remote (obfd_filename); |
+ if (objfile->obfd == NULL) |
+ { |
+ /* We have to make a cleanup and error here, rather |
+ than erroring later, because once we unref OBFD, |
+ OBFD_FILENAME will be freed. */ |
+ make_cleanup_bfd_unref (obfd); |
+ error (_("Can't open %s to read symbols."), obfd_filename); |
+ } |
+ gdb_bfd_unref (obfd); |
+ } |
+ |
+ original_name = xstrdup (objfile->original_name); |
+ make_cleanup (xfree, original_name); |
+ |
/* bfd_openr sets cacheable to true, which is what we want. */ |
if (!bfd_check_format (objfile->obfd, bfd_object)) |
- error (_("Can't read symbols from %s: %s."), objfile->name, |
+ error (_("Can't read symbols from %s: %s."), objfile_name (objfile), |
bfd_errmsg (bfd_get_error ())); |
/* Save the offsets, we will nuke them with the rest of the |
@@ -2554,15 +2577,6 @@ reread_symbols (void) |
/* Free the obstacks for non-reusable objfiles. */ |
psymbol_bcache_free (objfile->psymbol_cache); |
objfile->psymbol_cache = psymbol_bcache_init (); |
- bcache_xfree (objfile->macro_cache); |
- objfile->macro_cache = bcache_xmalloc (NULL, NULL); |
- bcache_xfree (objfile->filename_cache); |
- objfile->filename_cache = bcache_xmalloc (NULL,NULL); |
- if (objfile->demangled_names_hash != NULL) |
- { |
- htab_delete (objfile->demangled_names_hash); |
- objfile->demangled_names_hash = NULL; |
- } |
obstack_free (&objfile->objfile_obstack, 0); |
objfile->sections = NULL; |
objfile->symtabs = NULL; |
@@ -2571,7 +2585,6 @@ reread_symbols (void) |
objfile->free_psymtabs = NULL; |
objfile->template_symbols = NULL; |
objfile->msymbols = NULL; |
- objfile->deprecated_sym_private = NULL; |
objfile->minimal_symbol_count = 0; |
memset (&objfile->msymbol_hash, 0, |
sizeof (objfile->msymbol_hash)); |
@@ -2582,6 +2595,22 @@ reread_symbols (void) |
empty. We could use obstack_specify_allocation but |
gdb_obstack.h specifies the alloc/dealloc functions. */ |
obstack_init (&objfile->objfile_obstack); |
+ |
+ /* set_objfile_per_bfd potentially allocates the per-bfd |
+ data on the objfile's obstack (if sharing data across |
+ multiple users is not possible), so it's important to |
+ do it *after* the obstack has been initialized. */ |
+ set_objfile_per_bfd (objfile); |
+ |
+ objfile->original_name = obstack_copy0 (&objfile->objfile_obstack, |
+ original_name, |
+ strlen (original_name)); |
+ |
+ /* Reset the sym_fns pointer. The ELF reader can change it |
+ based on whether .gdb_index is present, and we need it to |
+ start over. PR symtab/15885 */ |
+ objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd)); |
+ |
build_objfile_section_table (objfile); |
terminate_minimal_symbol_table (objfile); |
@@ -2604,14 +2633,9 @@ reread_symbols (void) |
(*objfile->sf->sym_init) (objfile); |
clear_complaints (&symfile_complaints, 1, 1); |
- /* Do not set flags as this is safe and we don't want to be |
- verbose. */ |
- (*objfile->sf->sym_read) (objfile, 0); |
- if ((objfile->flags & OBJF_PSYMTABS_READ) != 0) |
- { |
- objfile->flags &= ~OBJF_PSYMTABS_READ; |
- require_partial_symbols (objfile, 0); |
- } |
+ |
+ objfile->flags &= ~OBJF_PSYMTABS_READ; |
+ read_symbols (objfile, 0); |
if (!objfile_has_symbols (objfile)) |
{ |
@@ -2665,7 +2689,6 @@ reread_symbols (void) |
} |
- |
typedef struct |
{ |
char *ext; |
@@ -2727,8 +2750,7 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e) |
*cp++ = '\0'; |
/* Find beginning of second arg, which should be a source language. */ |
- while (*cp && isspace (*cp)) |
- cp++; |
+ cp = skip_spaces (cp); |
if (*cp == '\0') |
error (_("'%s': two arguments required -- " |
@@ -2861,8 +2883,8 @@ allocate_symtab (const char *filename, struct objfile *objfile) |
symtab = (struct symtab *) |
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab)); |
memset (symtab, 0, sizeof (*symtab)); |
- symtab->filename = (char *) bcache (filename, strlen (filename) + 1, |
- objfile->filename_cache); |
+ symtab->filename = bcache (filename, strlen (filename) + 1, |
+ objfile->per_bfd->filename_cache); |
symtab->fullname = NULL; |
symtab->language = deduce_language_from_filename (filename); |
symtab->debugformat = "unknown"; |
@@ -2873,17 +2895,19 @@ allocate_symtab (const char *filename, struct objfile *objfile) |
symtab->next = objfile->symtabs; |
objfile->symtabs = symtab; |
- if (symtab_create_debug) |
+ /* This can be very verbose with lots of headers. |
+ Only print at higher debug levels. */ |
+ if (symtab_create_debug >= 2) |
{ |
/* Be a bit clever with debugging messages, and don't print objfile |
every time, only when it changes. */ |
static char *last_objfile_name = NULL; |
if (last_objfile_name == NULL |
- || strcmp (last_objfile_name, objfile->name) != 0) |
+ || strcmp (last_objfile_name, objfile_name (objfile)) != 0) |
{ |
xfree (last_objfile_name); |
- last_objfile_name = xstrdup (objfile->name); |
+ last_objfile_name = xstrdup (objfile_name (objfile)); |
fprintf_unfiltered (gdb_stdlog, |
"Creating one or more symtabs for objfile %s ...\n", |
last_objfile_name); |
@@ -3103,9 +3127,9 @@ pc_in_mapped_range (CORE_ADDR pc, struct obj_section *section) |
return 0; |
} |
- |
/* Return true if the mapped ranges of sections A and B overlap, false |
otherwise. */ |
+ |
static int |
sections_overlap (struct obj_section *a, struct obj_section *b) |
{ |
@@ -3155,7 +3179,6 @@ overlay_mapped_address (CORE_ADDR pc, struct obj_section *section) |
return pc; |
} |
- |
/* Function: symbol_overlayed_address |
Return one of two addresses (relative to the VMA or to the LMA), |
depending on whether the section is mapped or not. */ |
@@ -3234,7 +3257,7 @@ find_pc_mapped_section (CORE_ADDR pc) |
/* Function: list_overlays_command |
Print a list of mapped sections and their PC ranges. */ |
-void |
+static void |
list_overlays_command (char *args, int from_tty) |
{ |
int nmapped = 0; |
@@ -3274,7 +3297,7 @@ list_overlays_command (char *args, int from_tty) |
/* Function: map_overlay_command |
Mark the named section as mapped (ie. residing at its VMA address). */ |
-void |
+static void |
map_overlay_command (char *args, int from_tty) |
{ |
struct objfile *objfile, *objfile2; |
@@ -3319,7 +3342,7 @@ map_overlay_command (char *args, int from_tty) |
Mark the overlay section as unmapped |
(ie. resident in its LMA address range, rather than the VMA range). */ |
-void |
+static void |
unmap_overlay_command (char *args, int from_tty) |
{ |
struct objfile *objfile; |
@@ -3399,7 +3422,7 @@ overlay_load_command (char *args, int from_tty) |
A place-holder for a mis-typed command. */ |
/* Command list chain containing all defined "overlay" subcommands. */ |
-struct cmd_list_element *overlaylist; |
+static struct cmd_list_element *overlaylist; |
static void |
overlay_command (char *args, int from_tty) |
@@ -3409,7 +3432,6 @@ overlay_command (char *args, int from_tty) |
help_list (overlaylist, "overlay ", -1, gdb_stdout); |
} |
- |
/* Target Overlays for the "Simplest" overlay manager: |
This is GDB's default target overlay layer. It works with the |
@@ -3453,6 +3475,7 @@ enum ovly_index |
}; |
/* Throw away the cached copy of _ovly_table. */ |
+ |
static void |
simple_free_overlay_table (void) |
{ |
@@ -3465,6 +3488,7 @@ simple_free_overlay_table (void) |
/* Read an array of ints of size SIZE from the target into a local buffer. |
Convert to host order. int LEN is number of ints. */ |
+ |
static void |
read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, |
int len, int size, enum bfd_endian byte_order) |
@@ -3480,10 +3504,12 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, |
/* Find and grab a copy of the target _ovly_table |
(and _novlys, which is needed for the table's size). */ |
+ |
static int |
simple_read_overlay_table (void) |
{ |
- struct minimal_symbol *novlys_msym, *ovly_table_msym; |
+ struct minimal_symbol *novlys_msym; |
+ struct bound_minimal_symbol ovly_table_msym; |
struct gdbarch *gdbarch; |
int word_size; |
enum bfd_endian byte_order; |
@@ -3498,8 +3524,8 @@ simple_read_overlay_table (void) |
return 0; |
} |
- ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, NULL); |
- if (! ovly_table_msym) |
+ ovly_table_msym = lookup_bound_minimal_symbol ("_ovly_table"); |
+ if (! ovly_table_msym.minsym) |
{ |
error (_("Error reading inferior's overlay table: couldn't find " |
"`_ovly_table' array\n" |
@@ -3507,7 +3533,7 @@ simple_read_overlay_table (void) |
return 0; |
} |
- gdbarch = get_objfile_arch (msymbol_objfile (ovly_table_msym)); |
+ gdbarch = get_objfile_arch (ovly_table_msym.objfile); |
word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT; |
byte_order = gdbarch_byte_order (gdbarch); |
@@ -3515,7 +3541,7 @@ simple_read_overlay_table (void) |
4, byte_order); |
cache_ovly_table |
= (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table)); |
- cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym); |
+ cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym.minsym); |
read_target_long_array (cache_ovly_table_base, |
(unsigned int *) cache_ovly_table, |
cache_novlys * 4, word_size, byte_order); |
@@ -3640,7 +3666,6 @@ symfile_dummy_outputs (bfd *abfd, asection *sectp, void *dummy) |
/* Default implementation for sym_relocate. */ |
- |
bfd_byte * |
default_symfile_relocate (struct objfile *objfile, asection *sectp, |
bfd_byte *buf) |
@@ -3704,7 +3729,6 @@ free_symfile_segment_data (struct symfile_segment_data *data) |
xfree (data); |
} |
- |
/* Given: |
- DATA, containing segment addresses from the object file ABFD, and |
the mapping from ABFD's sections onto the segments that own them, |
@@ -3719,8 +3743,10 @@ free_symfile_segment_data (struct symfile_segment_data *data) |
If there are more entries, then ignore the extra. The target may |
not be able to distinguish between an empty data segment and a |
missing data segment; a missing text segment is less plausible. */ |
+ |
int |
-symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data, |
+symfile_map_offsets_to_segments (bfd *abfd, |
+ const struct symfile_segment_data *data, |
struct section_offsets *offsets, |
int num_segment_bases, |
const CORE_ADDR *segment_bases) |
@@ -3803,11 +3829,23 @@ symfile_find_segment_sections (struct objfile *objfile) |
free_symfile_segment_data (data); |
} |
+/* Listen for free_objfile events. */ |
+ |
+static void |
+symfile_free_objfile (struct objfile *objfile) |
+{ |
+ /* Remove the target sections of user-added objfiles. */ |
+ if (objfile != 0 && objfile->flags & OBJF_USERLOADED) |
+ remove_target_sections ((void *) objfile); |
+} |
+ |
void |
_initialize_symfile (void) |
{ |
struct cmd_list_element *c; |
+ observer_attach_free_objfile (symfile_free_objfile); |
+ |
c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\ |
Load symbol table from executable file FILE.\n\ |
The `file' command can also load symbol tables, as well as setting the file\n\ |
@@ -3824,6 +3862,15 @@ with the text. SECT is a section name to be loaded at SECT_ADDR."), |
&cmdlist); |
set_cmd_completer (c, filename_completer); |
+ c = add_cmd ("remove-symbol-file", class_files, |
+ remove_symbol_file_command, _("\ |
+Remove a symbol file added via the add-symbol-file command.\n\ |
+Usage: remove-symbol-file FILENAME\n\ |
+ remove-symbol-file -a ADDRESS\n\ |
+The file to remove can be identified by its filename or by an address\n\ |
+that lies within the boundaries of this symbol file in memory."), |
+ &cmdlist); |
+ |
c = add_cmd ("load", class_files, load_command, _("\ |
Dynamically load FILE into the running program, and record its symbols\n\ |
for access from GDB.\n\ |