/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "observer.h"
#include "exec.h"
#include "parser-defs.h"
+#include "varobj.h"
#include <sys/types.h>
#include <fcntl.h>
unsigned long total_size);
void (*deprecated_pre_add_symbol_hook) (const char *);
void (*deprecated_post_add_symbol_hook) (void);
-void (*deprecated_target_new_objfile_hook) (struct objfile *);
static void clear_symtab_users_cleanup (void *ignore);
int get_section_index (struct objfile *, char *);
-static void find_sym_fns (struct objfile *);
+static struct sym_fns *find_sym_fns (bfd *);
static void decrement_reading_symtab (void *);
static void init_filename_language_table (void);
+static void symfile_find_segment_sections (struct objfile *objfile);
+
void _initialize_symfile (void);
/* List of all available sym_fns. On gdb startup, each object file reader
/* This is where things get really weird... We MUST have valid
indices for the various sect_index_* members or gdb will abort.
So if for example, there is no ".text" section, we have to
- accomodate that. Except when explicitly adding symbol files at
- some address, section_offsets contains nothing but zeros, so it
- doesn't matter which slot in section_offsets the individual
- sect_index_* members index into. So if they are all zero, it is
- safe to just point all the currently uninitialized indices to the
- first slot. */
+ accomodate that. First, check for a file with the standard
+ one or two segments. */
+
+ symfile_find_segment_sections (objfile);
+
+ /* Except when explicitly adding symbol files at some address,
+ section_offsets contains nothing but zeros, so it doesn't matter
+ which slot in section_offsets the individual sect_index_* members
+ index into. So if they are all zero, it is safe to just point
+ all the currently uninitialized indices to the first slot. But
+ beware: if this is the main executable, it may be relocated
+ later, e.g. by the remote qOffsets packet, and then this will
+ be wrong! That's why we try segments first. */
for (i = 0; i < objfile->num_sections; i++)
{
int done;
ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
- /* We are only interested in loadable sections. */
- if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ /* We are only interested in allocated sections. */
+ if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
return;
/* If the user specified an offset, honor it. */
if (cur_sec == sect)
continue;
- /* We can only conflict with loadable sections. */
- if ((bfd_get_section_flags (abfd, cur_sec) & SEC_LOAD) == 0)
- continue;
-
- /* We do not expect this to happen; just ignore sections in a
- relocatable file with an assigned VMA. */
- if (bfd_section_vma (abfd, cur_sec) != 0)
+ /* We can only conflict with allocated sections. */
+ if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
continue;
/* If the section offset is 0, either the section has not been placed
if ((bfd_get_file_flags (objfile->obfd) & (EXEC_P | DYNAMIC)) == 0)
{
struct place_section_arg arg;
- arg.offsets = objfile->section_offsets;
- arg.lowest = 0;
- bfd_map_over_sections (objfile->obfd, place_section, &arg);
+ bfd *abfd = objfile->obfd;
+ asection *cur_sec;
+ CORE_ADDR lowest = 0;
+
+ for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
+ /* We do not expect this to happen; just skip this step if the
+ relocatable file has a section with an assigned VMA. */
+ if (bfd_section_vma (abfd, cur_sec) != 0)
+ break;
+
+ if (cur_sec == NULL)
+ {
+ CORE_ADDR *offsets = objfile->section_offsets->offsets;
+
+ /* Pick non-overlapping offsets for sections the user did not
+ place explicitly. */
+ arg.offsets = objfile->section_offsets;
+ arg.lowest = 0;
+ bfd_map_over_sections (objfile->obfd, place_section, &arg);
+
+ /* Correctly filling in the section offsets is not quite
+ enough. Relocatable files have two properties that
+ (most) shared objects do not:
+
+ - Their debug information will contain relocations. Some
+ shared libraries do also, but many do not, so this can not
+ be assumed.
+
+ - If there are multiple code sections they will be loaded
+ at different relative addresses in memory than they are
+ in the objfile, since all sections in the file will start
+ at address zero.
+
+ Because GDB has very limited ability to map from an
+ address in debug info to the correct code section,
+ it relies on adding SECT_OFF_TEXT to things which might be
+ code. If we clear all the section offsets, and set the
+ section VMAs instead, then symfile_relocate_debug_section
+ will return meaningful debug information pointing at the
+ correct sections.
+
+ GDB has too many different data structures for section
+ addresses - a bfd, objfile, and so_list all have section
+ tables, as does exec_ops. Some of these could probably
+ be eliminated. */
+
+ for (cur_sec = abfd->sections; cur_sec != NULL;
+ cur_sec = cur_sec->next)
+ {
+ if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
+ continue;
+
+ bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+ offsets[cur_sec->index] = 0;
+ }
+ }
}
/* Remember the bfd indexes for the .text, .data, .bss and
}
+/* 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.
+ It assumes that object files do not have segments, and fully linked
+ files have a single segment. */
+
+struct symfile_segment_data *
+default_symfile_segments (bfd *abfd)
+{
+ int num_sections, i;
+ asection *sect;
+ struct symfile_segment_data *data;
+ CORE_ADDR low, high;
+
+ /* Relocatable files contain enough information to position each
+ loadable section independently; they should not be relocated
+ in segments. */
+ if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) == 0)
+ return NULL;
+
+ /* Make sure there is at least one loadable section in the file. */
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ {
+ if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+ continue;
+
+ break;
+ }
+ if (sect == NULL)
+ return NULL;
+
+ low = bfd_get_section_vma (abfd, sect);
+ high = low + bfd_get_section_size (sect);
+
+ data = XZALLOC (struct symfile_segment_data);
+ data->num_segments = 1;
+ data->segment_bases = XCALLOC (1, CORE_ADDR);
+ data->segment_sizes = XCALLOC (1, CORE_ADDR);
+
+ num_sections = bfd_count_sections (abfd);
+ data->segment_info = XCALLOC (num_sections, int);
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ CORE_ADDR vma;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+ continue;
+
+ vma = bfd_get_section_vma (abfd, sect);
+ if (vma < low)
+ low = vma;
+ if (vma + bfd_get_section_size (sect) > high)
+ high = vma + bfd_get_section_size (sect);
+
+ data->segment_info[i] = 1;
+ }
+
+ data->segment_bases[0] = low;
+ data->segment_sizes[0] = high - low;
+
+ return data;
+}
+
/* Process a symbol file, as either the main file or as a dynamically
loaded file.
gdb_assert (! (addrs && offsets));
init_entry_point_info (objfile);
- find_sym_fns (objfile);
+ objfile->sf = find_sym_fns (objfile->obfd);
if (objfile->sf == NULL)
return; /* No symbols. */
new_symfile_objfile (objfile, mainline, from_tty);
- if (deprecated_target_new_objfile_hook)
- deprecated_target_new_objfile_hook (objfile);
+ observer_notify_new_objfile (objfile);
bfd_cache_close_all ();
return (objfile);
return crc == file_crc;
}
-static char *debug_file_directory = NULL;
+char *debug_file_directory = NULL;
static void
show_debug_file_directory (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
char *dir;
char *debugfile;
char *name_copy;
+ char *canon_name;
bfd_size_type debuglink_size;
unsigned long crc32;
int i;
return xstrdup (debugfile);
}
+ /* If the file is in the sysroot, try using its base path in the
+ global debugfile directory. */
+ canon_name = lrealpath (dir);
+ if (canon_name
+ && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
+ && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
+ {
+ strcpy (debugfile, debug_file_directory);
+ strcat (debugfile, canon_name + strlen (gdb_sysroot));
+ strcat (debugfile, "/");
+ strcat (debugfile, basename);
+
+ if (separate_debug_file_exists (debugfile, crc32))
+ {
+ xfree (canon_name);
+ xfree (basename);
+ xfree (dir);
+ return xstrdup (debugfile);
+ }
+ }
+
+ if (canon_name)
+ xfree (canon_name);
+
xfree (basename);
xfree (dir);
return NULL;
struct sym_fns in the objfile structure, that contains cached
information about the symbol file. */
-static void
-find_sym_fns (struct objfile *objfile)
+static struct sym_fns *
+find_sym_fns (bfd *abfd)
{
struct sym_fns *sf;
- enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd);
- char *our_target = bfd_get_target (objfile->obfd);
+ enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
if (our_flavour == bfd_target_srec_flavour
|| our_flavour == bfd_target_ihex_flavour
|| our_flavour == bfd_target_tekhex_flavour)
- return; /* No symbols. */
+ return NULL; /* No symbols. */
for (sf = symtab_fns; sf != NULL; sf = sf->next)
- {
- if (our_flavour == sf->sym_flavour)
- {
- objfile->sf = sf;
- return;
- }
- }
+ if (our_flavour == sf->sym_flavour)
+ return sf;
error (_("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown."),
- bfd_get_target (objfile->obfd));
+ bfd_get_target (abfd));
}
\f
/* Opaque data for load_section_callback. */
struct load_section_data {
unsigned long load_offset;
+ struct load_progress_data *progress_data;
+ VEC(memory_write_request_s) *requests;
+};
+
+/* Opaque data for load_progress. */
+struct load_progress_data {
+ /* Cumulative data. */
unsigned long write_count;
unsigned long data_count;
bfd_size_type total_size;
+};
- /* Per-section data for load_progress. */
+/* Opaque data for load_progress for a single section. */
+struct load_progress_section_data {
+ struct load_progress_data *cumulative;
+
+ /* Per-section data. */
const char *section_name;
ULONGEST section_sent;
ULONGEST section_size;
gdb_byte *buffer;
};
-/* Target write callback routine for load_section_callback. */
+/* Target write callback routine for progress reporting. */
static void
load_progress (ULONGEST bytes, void *untyped_arg)
{
- struct load_section_data *args = untyped_arg;
+ struct load_progress_section_data *args = untyped_arg;
+ struct load_progress_data *totals;
+
+ if (args == NULL)
+ /* Writing padding data. No easy way to get at the cumulative
+ stats, so just ignore this. */
+ return;
+
+ totals = args->cumulative;
+
+ if (bytes == 0 && args->section_sent == 0)
+ {
+ /* The write is just starting. Let the user know we've started
+ this section. */
+ ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
+ args->section_name, paddr_nz (args->section_size),
+ paddr_nz (args->lma));
+ return;
+ }
if (validate_download)
{
paddr (args->lma));
do_cleanups (verify_cleanups);
}
- args->data_count += bytes;
+ totals->data_count += bytes;
args->lma += bytes;
args->buffer += bytes;
- args->write_count += 1;
+ totals->write_count += 1;
args->section_sent += bytes;
if (quit_flag
|| (deprecated_ui_load_progress_hook != NULL
deprecated_show_load_progress (args->section_name,
args->section_sent,
args->section_size,
- args->data_count,
- args->total_size);
+ totals->data_count,
+ totals->total_size);
}
/* Callback service function for generic_load (bfd_map_over_sections). */
static void
load_section_callback (bfd *abfd, asection *asec, void *data)
{
+ struct memory_write_request *new_request;
struct load_section_data *args = data;
+ struct load_progress_section_data *section_data;
bfd_size_type size = bfd_get_section_size (asec);
gdb_byte *buffer;
- struct cleanup *old_chain;
const char *sect_name = bfd_get_section_name (abfd, asec);
- LONGEST transferred;
if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
return;
if (size == 0)
return;
- buffer = xmalloc (size);
- old_chain = make_cleanup (xfree, buffer);
+ new_request = VEC_safe_push (memory_write_request_s,
+ args->requests, NULL);
+ memset (new_request, 0, sizeof (struct memory_write_request));
+ section_data = xcalloc (1, sizeof (struct load_progress_section_data));
+ new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset;
+ new_request->end = new_request->begin + size; /* FIXME Should size be in instead? */
+ new_request->data = xmalloc (size);
+ new_request->baton = section_data;
- args->section_name = sect_name;
- args->section_sent = 0;
- args->section_size = size;
- args->lma = bfd_section_lma (abfd, asec) + args->load_offset;
- args->buffer = buffer;
+ buffer = new_request->data;
- /* Is this really necessary? I guess it gives the user something
- to look at during a long download. */
- ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
- sect_name, paddr_nz (size), paddr_nz (args->lma));
+ section_data->cumulative = args->progress_data;
+ section_data->section_name = sect_name;
+ section_data->section_size = size;
+ section_data->lma = new_request->begin;
+ section_data->buffer = buffer;
bfd_get_section_contents (abfd, asec, buffer, 0, size);
+}
- transferred = target_write_with_progress (¤t_target,
- TARGET_OBJECT_MEMORY,
- NULL, buffer, args->lma,
- size, load_progress, args);
- if (transferred < size)
- error (_("Memory access error while loading section %s."),
- sect_name);
+/* Clean up an entire memory request vector, including load
+ data and progress records. */
- do_cleanups (old_chain);
+static void
+clear_memory_write_data (void *arg)
+{
+ VEC(memory_write_request_s) **vec_p = arg;
+ VEC(memory_write_request_s) *vec = *vec_p;
+ int i;
+ struct memory_write_request *mr;
+
+ for (i = 0; VEC_iterate (memory_write_request_s, vec, i, mr); ++i)
+ {
+ xfree (mr->data);
+ xfree (mr->baton);
+ }
+ VEC_free (memory_write_request_s, vec);
}
void
generic_load (char *args, int from_tty)
{
- asection *s;
bfd *loadfile_bfd;
struct timeval start_time, end_time;
char *filename;
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
struct load_section_data cbdata;
+ struct load_progress_data total_progress;
+
CORE_ADDR entry;
char **argv;
- cbdata.load_offset = 0; /* Offset to add to vma for each section. */
- cbdata.write_count = 0; /* Number of writes needed. */
- cbdata.data_count = 0; /* Number of bytes written to target memory. */
- cbdata.total_size = 0; /* Total size of all bfd sectors. */
+ memset (&cbdata, 0, sizeof (cbdata));
+ memset (&total_progress, 0, sizeof (total_progress));
+ cbdata.progress_data = &total_progress;
+
+ make_cleanup (clear_memory_write_data, &cbdata.requests);
argv = buildargv (args);
}
bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
- (void *) &cbdata.total_size);
+ (void *) &total_progress.total_size);
+
+ bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
gettimeofday (&start_time, NULL);
- bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+ if (target_write_memory_blocks (cbdata.requests, flash_discard,
+ load_progress) != 0)
+ error (_("Load failed"));
gettimeofday (&end_time, NULL);
ui_out_text (uiout, "Start address ");
ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
ui_out_text (uiout, ", load size ");
- ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
+ ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
ui_out_text (uiout, "\n");
/* We were doing this in remote-mips.c, I suspect it is right
for other targets too. */
file is loaded in. Some targets do (e.g., remote-vx.c) but
others don't (or didn't - perhaps they have all been deleted). */
- print_transfer_performance (gdb_stdout, cbdata.data_count,
- cbdata.write_count, &start_time, &end_time);
+ print_transfer_performance (gdb_stdout, total_progress.data_count,
+ total_progress.write_count,
+ &start_time, &end_time);
do_cleanups (old_cleanups);
}
symtab->next = objfile->symtabs;
objfile->symtabs = symtab;
- /* FIXME: This should go away. It is only defined for the Z8000,
- and the Z8000 definition of this macro doesn't have anything to
- do with the now-nonexistent EXTRA_SYMTAB_INFO macro, it's just
- here for convenience. */
-#ifdef INIT_EXTRA_SYMTAB_INFO
- INIT_EXTRA_SYMTAB_INFO (symtab);
-#endif
-
return (symtab);
}
breakpoint_re_set ();
set_default_breakpoint (0, 0, 0, 0);
clear_pc_function_cache ();
- if (deprecated_target_new_objfile_hook)
- deprecated_target_new_objfile_hook (NULL);
+ observer_notify_new_objfile (NULL);
/* Clear globals which might have pointed into a removed objfile.
FIXME: It's not clear which of these are supposed to persist
between expressions and which ought to be reset each time. */
expression_context_block = NULL;
innermost_block = NULL;
+
+ /* Varobj may refer to old symbols, perform a cleanup. */
+ varobj_invalidate ();
+
}
static void
return psym;
}
-/* Add a symbol with a long value to a psymtab. This differs from
- * add_psymbol_to_list above in taking both a mangled and a demangled
- * name. */
-
-void
-add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name,
- int dem_namelength, domain_enum domain,
- enum address_class class,
- struct psymbol_allocation_list *list, long val, /* Value as a long */
- CORE_ADDR coreaddr, /* Value as a CORE_ADDR */
- enum language language,
- struct objfile *objfile)
-{
- struct partial_symbol *psym;
- char *buf = alloca (namelength + 1);
- /* psymbol is static so that there will be no uninitialized gaps in the
- structure which might contain random data, causing cache misses in
- bcache. */
- static struct partial_symbol psymbol;
-
- /* Create local copy of the partial symbol */
-
- memcpy (buf, name, namelength);
- buf[namelength] = '\0';
- DEPRECATED_SYMBOL_NAME (&psymbol) = deprecated_bcache (buf, namelength + 1,
- objfile->psymbol_cache);
-
- buf = alloca (dem_namelength + 1);
- memcpy (buf, dem_name, dem_namelength);
- buf[dem_namelength] = '\0';
-
- switch (language)
- {
- case language_c:
- case language_cplus:
- SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) =
- deprecated_bcache (buf, dem_namelength + 1, objfile->psymbol_cache);
- break;
- /* FIXME What should be done for the default case? Ignoring for now. */
- }
-
- /* val and coreaddr are mutually exclusive, one of them *will* be zero */
- if (val != 0)
- {
- SYMBOL_VALUE (&psymbol) = val;
- }
- else
- {
- SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
- }
- SYMBOL_SECTION (&psymbol) = 0;
- SYMBOL_LANGUAGE (&psymbol) = language;
- PSYMBOL_DOMAIN (&psymbol) = domain;
- PSYMBOL_CLASS (&psymbol) = class;
- SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
-
- /* Stash the partial symbol away in the cache */
- psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol),
- objfile->psymbol_cache);
-
- /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
- if (list->next >= list->list + list->size)
- {
- extend_psymbol_list (list, objfile);
- }
- *list->next++ = psym;
- OBJSTAT (objfile, n_psyms++);
-}
-
/* Initialize storage for partial symbols. */
void
enum overlay_debugging_state overlay_debugging = ovly_off;
int overlay_cache_invalid = 0; /* True if need to refresh mapped state */
-/* Target vector for refreshing overlay mapped state */
-static void simple_overlay_update (struct obj_section *);
-void (*target_overlay_update) (struct obj_section *) = simple_overlay_update;
-
/* Function: section_is_overlay (SECTION)
Returns true if SECTION has VMA not equal to LMA, ie.
SECTION is loaded at an address different from where it will "run". */
case ovly_off:
return 0; /* overlay debugging off */
case ovly_auto: /* overlay debugging automatic */
- /* Unles there is a target_overlay_update function,
+ /* Unles there is a gdbarch_overlay_update function,
there's really nothing useful to do here (can't really go auto) */
- if (target_overlay_update)
+ if (gdbarch_overlay_update_p (current_gdbarch))
{
if (overlay_cache_invalid)
{
overlay_cache_invalid = 0;
}
if (osect->ovly_mapped == -1)
- (*target_overlay_update) (osect);
+ gdbarch_overlay_update (current_gdbarch, osect);
}
/* fall thru to manual case */
case ovly_on: /* overlay debugging manual */
static void
overlay_load_command (char *args, int from_tty)
{
- if (target_overlay_update)
- (*target_overlay_update) (NULL);
+ if (gdbarch_overlay_update_p (current_gdbarch))
+ gdbarch_overlay_update (current_gdbarch, NULL);
else
error (_("This target does not know how to read its overlay state."));
}
This is GDB's default target overlay layer. It works with the
minimal overlay manager supplied as an example by Cygnus. The
- entry point is via a function pointer "target_overlay_update",
+ entry point is via a function pointer "gdbarch_overlay_update",
so targets that use a different runtime overlay manager can
substitute their own overlay_update function and take over the
function pointer.
{
VMA, SIZE, LMA, MAPPED
};
-#define TARGET_LONG_BYTES (TARGET_LONG_BIT / TARGET_CHAR_BIT)
+#define TARGET_LONG_BYTES (gdbarch_long_bit (current_gdbarch) \
+ / TARGET_CHAR_BIT)
/* Throw away the cached copy of _ovly_table */
static void
If a cached entry can't be found or the cache isn't valid, then
re-read the entire cache, and go ahead and update all sections. */
-static void
+void
simple_overlay_update (struct obj_section *osect)
{
struct objfile *objfile;
return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL);
}
+struct symfile_segment_data *
+get_symfile_segment_data (bfd *abfd)
+{
+ struct sym_fns *sf = find_sym_fns (abfd);
+
+ if (sf == NULL)
+ return NULL;
+
+ return sf->sym_segments (abfd);
+}
+
+void
+free_symfile_segment_data (struct symfile_segment_data *data)
+{
+ xfree (data->segment_bases);
+ xfree (data->segment_sizes);
+ xfree (data->segment_info);
+ xfree (data);
+}
+
+int
+symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
+ struct section_offsets *offsets,
+ int num_segment_bases,
+ const CORE_ADDR *segment_bases)
+{
+ int i;
+ asection *sect;
+
+ /* If we do not have segment mappings for the object file, we
+ can not relocate it by segments. */
+ gdb_assert (data != NULL);
+ gdb_assert (data->num_segments > 0);
+
+ /* If more offsets are provided than we have segments, make sure the
+ excess offsets are all the same as the last segment's offset.
+ This allows "Text=X;Data=X" for files which have only a single
+ segment. */
+ if (num_segment_bases > data->num_segments)
+ for (i = data->num_segments; i < num_segment_bases; i++)
+ if (segment_bases[i] != segment_bases[data->num_segments - 1])
+ return 0;
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ CORE_ADDR vma;
+ int which = data->segment_info[i];
+
+ if (which > num_segment_bases)
+ offsets->offsets[i] = segment_bases[num_segment_bases - 1];
+ else if (which > 0)
+ offsets->offsets[i] = segment_bases[which - 1];
+ else
+ continue;
+
+ offsets->offsets[i] -= data->segment_bases[which - 1];
+ }
+
+ return 1;
+}
+
+static void
+symfile_find_segment_sections (struct objfile *objfile)
+{
+ bfd *abfd = objfile->obfd;
+ int i;
+ asection *sect;
+ struct symfile_segment_data *data;
+
+ data = get_symfile_segment_data (objfile->obfd);
+ if (data == NULL)
+ return;
+
+ if (data->num_segments != 1 && data->num_segments != 2)
+ {
+ free_symfile_segment_data (data);
+ return;
+ }
+
+ for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+ {
+ CORE_ADDR vma;
+ int which = data->segment_info[i];
+
+ if (which == 1)
+ {
+ if (objfile->sect_index_text == -1)
+ objfile->sect_index_text = sect->index;
+
+ if (objfile->sect_index_rodata == -1)
+ objfile->sect_index_rodata = sect->index;
+ }
+ else if (which == 2)
+ {
+ if (objfile->sect_index_data == -1)
+ objfile->sect_index_data = sect->index;
+
+ if (objfile->sect_index_bss == -1)
+ objfile->sect_index_bss = sect->index;
+ }
+ }
+
+ free_symfile_segment_data (data);
+}
+
void
_initialize_symfile (void)
{
add_info ("extensions", info_ext_lang_command,
_("All filename extensions associated with a source language."));
- debug_file_directory = xstrdup (DEBUGDIR);
add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
&debug_file_directory, _("\
Set the directory where separate debug symbols are searched for."), _("\