/* 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, 2007
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "bfdlink.h"
#include "exec.h"
#include "parser-defs.h"
#include "varobj.h"
+#include "elf-bfd.h"
+#include "solib.h"
#include <sys/types.h>
#include <fcntl.h>
static void simple_free_overlay_region_table (void);
#endif
-static void set_initial_language (void);
-
static void load_command (char *, int);
static void symbol_file_add_main_1 (char *args, int from_tty, int flags);
offsets[sect->index] = start_addr;
arg->lowest = start_addr + bfd_get_section_size (sect);
-
- exec_set_section_address (bfd_get_filename (abfd), sect->index, start_addr);
}
/* Parse the user's idea of an offset for dynamic linking, into our idea
continue;
bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+ exec_set_section_address (bfd_get_filename (abfd), cur_sec->index,
+ offsets[cur_sec->index]);
offsets[cur_sec->index] = 0;
}
}
bfd_map_over_sections (objfile->obfd, find_lowest_section,
&lower_sect);
if (lower_sect == NULL)
- warning (_("no loadable sections found in added symbol-file %s"),
- objfile->name);
- else
- if ((bfd_get_section_flags (objfile->obfd, lower_sect) & SEC_CODE) == 0)
- warning (_("Lowest section in %s is %s at %s"),
- objfile->name,
- bfd_section_name (objfile->obfd, lower_sect),
- paddr (bfd_section_vma (objfile->obfd, lower_sect)));
- if (lower_sect != NULL)
- lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
+ {
+ warning (_("no loadable sections found in added symbol-file %s"),
+ objfile->name);
+ lower_offset = 0;
+ }
else
- lower_offset = 0;
+ lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
/* Calculate offsets for the loadable sections.
FIXME! Sections must be in order of increasing loadable section
{
struct objfile *objfile;
struct partial_symtab *psymtab;
- char *debugfile;
+ char *debugfile = NULL;
struct section_addr_info *orig_addrs = NULL;
struct cleanup *my_cleanups;
const char *name = bfd_get_filename (abfd);
}
}
- debugfile = find_separate_debug_file (objfile);
+ /* If the file has its own symbol tables it has no separate debug info.
+ `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
+ `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */
+ if (objfile->psymtabs == NULL)
+ debugfile = find_separate_debug_file (objfile);
if (debugfile)
{
if (addrs != NULL)
storage has just been released, we'd better wipe the solib
descriptors as well.
*/
-#if defined(SOLIB_RESTART)
- SOLIB_RESTART ();
-#endif
+ no_shared_libraries (NULL, from_tty);
symfile_objfile = NULL;
if (from_tty)
printf_unfiltered (_("No symbol file now.\n"));
}
+struct build_id
+ {
+ size_t size;
+ gdb_byte data[1];
+ };
+
+/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */
+
+static struct build_id *
+build_id_bfd_get (bfd *abfd)
+{
+ struct build_id *retval;
+
+ if (!bfd_check_format (abfd, bfd_object)
+ || bfd_get_flavour (abfd) != bfd_target_elf_flavour
+ || elf_tdata (abfd)->build_id == NULL)
+ return NULL;
+
+ retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
+ retval->size = elf_tdata (abfd)->build_id_size;
+ memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
+
+ return retval;
+}
+
+/* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value. */
+
+static int
+build_id_verify (const char *filename, struct build_id *check)
+{
+ bfd *abfd;
+ struct build_id *found = NULL;
+ int retval = 0;
+
+ /* We expect to be silent on the non-existing files. */
+ abfd = bfd_openr (filename, gnutarget);
+ if (abfd == NULL)
+ return 0;
+
+ found = build_id_bfd_get (abfd);
+
+ if (found == NULL)
+ warning (_("File \"%s\" has no build-id, file skipped"), filename);
+ else if (found->size != check->size
+ || memcmp (found->data, check->data, found->size) != 0)
+ warning (_("File \"%s\" has a different build-id, file skipped"), filename);
+ else
+ retval = 1;
+
+ if (!bfd_close (abfd))
+ warning (_("cannot close \"%s\": %s"), filename,
+ bfd_errmsg (bfd_get_error ()));
+ return retval;
+}
+
+static char *
+build_id_to_debug_filename (struct build_id *build_id)
+{
+ char *link, *s, *retval = NULL;
+ gdb_byte *data = build_id->data;
+ size_t size = build_id->size;
+
+ /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
+ link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
+ + 2 * size + (sizeof ".debug" - 1) + 1);
+ s = link + sprintf (link, "%s/.build-id/", debug_file_directory);
+ if (size > 0)
+ {
+ size--;
+ s += sprintf (s, "%02x", (unsigned) *data++);
+ }
+ if (size > 0)
+ *s++ = '/';
+ while (size-- > 0)
+ s += sprintf (s, "%02x", (unsigned) *data++);
+ strcpy (s, ".debug");
+
+ /* lrealpath() is expensive even for the usually non-existent files. */
+ if (access (link, F_OK) == 0)
+ retval = lrealpath (link);
+ xfree (link);
+
+ if (retval != NULL && !build_id_verify (retval, build_id))
+ {
+ xfree (retval);
+ retval = NULL;
+ }
+
+ return retval;
+}
+
static char *
get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
{
bfd_size_type debuglink_size;
unsigned long crc32;
int i;
+ struct build_id *build_id;
+
+ build_id = build_id_bfd_get (objfile->obfd);
+ if (build_id != NULL)
+ {
+ char *build_id_name;
+
+ build_id_name = build_id_to_debug_filename (build_id);
+ free (build_id);
+ /* Prevent looping on a stripped .debug file. */
+ if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0)
+ {
+ warning (_("\"%s\": separate debug info file has no debug info"),
+ build_id_name);
+ xfree (build_id_name);
+ }
+ else if (build_id_name != NULL)
+ return build_id_name;
+ }
basename = get_debug_link_info (objfile, &crc32);
stabs we find, but we can't do that until later when we read in
full symbols. */
-static void
+void
set_initial_language (void)
{
struct partial_symtab *pst;
entered on the command line. */
section_addrs->other[sec_num].name = sec;
section_addrs->other[sec_num].addr = addr;
- printf_unfiltered ("\t%s_addr = %s\n",
- sec, hex_string ((unsigned long)addr));
+ printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr));
sec_num++;
/* The object's sections are initialized when a
/* We need to do this whenever any symbols go away. */
make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
+ if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd),
+ bfd_get_filename (exec_bfd)) == 0)
+ {
+ /* Reload EXEC_BFD without asking anything. */
+
+ exec_file_attach (bfd_get_filename (objfile->obfd), 0);
+ }
+
/* 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. */
sizeof (objfile->msymbol_hash));
memset (&objfile->msymbol_demangled_hash, 0,
sizeof (objfile->msymbol_demangled_hash));
- objfile->fundamental_types = NULL;
clear_objfile_data (objfile);
if (objfile->sf != NULL)
{
add_filename_language (".f", language_fortran);
add_filename_language (".F", language_fortran);
add_filename_language (".s", language_asm);
+ add_filename_language (".sx", language_asm);
add_filename_language (".S", language_asm);
add_filename_language (".pas", language_pascal);
add_filename_language (".p", language_pascal);
name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
printf_filtered ("Section %s, loaded at ", name);
- deprecated_print_address_numeric (lma, 1, gdb_stdout);
+ fputs_filtered (paddress (lma), gdb_stdout);
puts_filtered (" - ");
- deprecated_print_address_numeric (lma + size, 1, gdb_stdout);
+ fputs_filtered (paddress (lma + size), gdb_stdout);
printf_filtered (", mapped at ");
- deprecated_print_address_numeric (vma, 1, gdb_stdout);
+ fputs_filtered (paddress (vma), gdb_stdout);
puts_filtered (" - ");
- deprecated_print_address_numeric (vma + size, 1, gdb_stdout);
+ fputs_filtered (paddress (vma + size), gdb_stdout);
puts_filtered ("\n");
nmapped++;
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,
+ and
+ - SEGMENT_BASES[0 .. NUM_SEGMENT_BASES - 1], holding the actual
+ segment addresses reported by the target,
+ store the appropriate offsets for each section in OFFSETS.
+
+ If there are fewer entries in SEGMENT_BASES than there are segments
+ in DATA, then apply SEGMENT_BASES' last entry to all the segments.
+
+ If there are more, then verify that all the excess addresses are
+ the same as the last legitimate one, and then ignore them. This
+ allows "TextSeg=X;DataSeg=X" qOffset replies for files which have
+ only a single segment. */
int
symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
struct section_offsets *offsets,
int i;
asection *sect;
+ /* It doesn't make sense to call this function unless you have some
+ segment base addresses. */
+ gdb_assert (segment_bases > 0);
+
/* 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. */
+ /* Check any extra SEGMENT_BASES entries. */
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])
for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
{
- CORE_ADDR vma;
int which = data->segment_info[i];
+ gdb_assert (0 <= which && which <= data->num_segments);
+
+ /* Don't bother computing offsets for sections that aren't
+ loaded as part of any segment. */
+ if (! which)
+ continue;
+
+ /* Use the last SEGMENT_BASES entry as the address of any extra
+ segments mentioned in DATA->segment_info. */
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;
+ which = num_segment_bases;
- offsets->offsets[i] -= data->segment_bases[which - 1];
+ offsets->offsets[i] = (segment_bases[which - 1]
+ - data->segment_bases[which - 1]);
}
return 1;