/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
- 2001
+
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
+ 2000, 2001, 2003, 2004
Free Software Foundation, Inc.
This file is part of GDB.
#include "solist.h"
#include "solib-svr4.h"
+#include "bfd-target.h"
+#include "exec.h"
+
#ifndef SVR4_FETCH_LINK_MAP_OFFSETS
#define SVR4_FETCH_LINK_MAP_OFFSETS() svr4_fetch_link_map_offsets ()
#endif
for (i = 0; i < number_of_symbols; i++)
{
sym = *symbol_table++;
- if (STREQ (sym->name, symname)
+ if (strcmp (sym->name, symname) == 0
&& (sym->section->flags & sect_flags) == sect_flags)
{
/* Bfd symbols are section relative. */
{
sym = *symbol_table++;
- if (STREQ (sym->name, symname)
+ if (strcmp (sym->name, symname) == 0
&& (sym->section->flags & sect_flags) == sect_flags)
{
/* Bfd symbols are section relative. */
static CORE_ADDR
elf_locate_base (void)
{
- sec_ptr dyninfo_sect;
+ struct bfd_section *dyninfo_sect;
int dyninfo_sect_size;
CORE_ADDR dyninfo_addr;
char *buf;
|| in_plt_section (pc, NULL));
}
+/* Given an executable's ABFD and target, compute the entry-point
+ address. */
+
+static CORE_ADDR
+exec_entry_point (struct bfd *abfd, struct target_ops *targ)
+{
+ /* KevinB wrote ... for most targets, the address returned by
+ bfd_get_start_address() is the entry point for the start
+ function. But, for some targets, bfd_get_start_address() returns
+ the address of a function descriptor from which the entry point
+ address may be extracted. This address is extracted by
+ gdbarch_convert_from_func_ptr_addr(). The method
+ gdbarch_convert_from_func_ptr_addr() is the merely the identify
+ function for targets which don't use function descriptors. */
+ return gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ bfd_get_start_address (abfd),
+ targ);
+}
/*
int load_addr_found = 0;
struct so_list *inferior_sos;
bfd *tmp_bfd = NULL;
+ struct target_ops *tmp_bfd_target;
int tmp_fd = -1;
char *tmp_pathname = NULL;
CORE_ADDR sym_addr = 0;
goto bkpt_at_symbol;
}
+ /* Now convert the TMP_BFD into a target. That way target, as
+ well as BFD operations can be used. Note that closing the
+ target will also close the underlying bfd. */
+ tmp_bfd_target = target_bfd_reopen (tmp_bfd);
+
/* If the entry in _DYNAMIC for the dynamic linker has already
been filled in, we can read its base address from there. */
inferior_sos = svr4_current_sos ();
the current pc (which should point at the entry point for the
dynamic linker) and subtracting the offset of the entry point. */
if (!load_addr_found)
- load_addr = read_pc () - tmp_bfd->start_address;
+ load_addr = (read_pc ()
+ - exec_entry_point (tmp_bfd, tmp_bfd_target));
/* Record the relocated start and end address of the dynamic linker
text and plt section for svr4_in_dynsym_resolve_code. */
break;
}
- /* We're done with the temporary bfd. */
- bfd_close (tmp_bfd);
+ /* We're done with both the temporary bfd and target. Remember,
+ closing the target closes the underlying bfd. */
+ target_close (tmp_bfd_target, 0);
if (sym_addr != 0)
{
interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
if (interp_sect == NULL
&& (bfd_get_file_flags (exec_bfd) & DYNAMIC) != 0
- && bfd_get_start_address (exec_bfd) != pc)
+ && (exec_entry_point (exec_bfd, &exec_ops) != pc))
{
struct cleanup *old_chain;
struct section_offsets *new_offsets;
The same language also appears in Edition 4.0 of the System V
ABI and is left unspecified in some of the earlier editions. */
- displacement = pc - bfd_get_start_address (exec_bfd);
+ displacement = pc - exec_entry_point (exec_bfd, &exec_ops);
changed = 0;
new_offsets = xcalloc (symfile_objfile->num_sections,
return legacy_fetch_link_map_offsets;
}
+/* Most OS'es that have SVR4-style ELF dynamic libraries define a
+ `struct r_debug' and a `struct link_map' that are binary compatible
+ with the origional SVR4 implementation. */
+
+/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
+ for an ILP32 SVR4 system. */
+
+struct link_map_offsets *
+svr4_ilp32_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ /* Everything we need is in the first 8 bytes. */
+ lmo.r_debug_size = 8;
+ lmo.r_map_offset = 4;
+ lmo.r_map_size = 4;
+
+ /* Everything we need is in the first 20 bytes. */
+ lmo.link_map_size = 20;
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 4;
+ lmo.l_name_offset = 4;
+ lmo.l_name_size = 4;
+ lmo.l_next_offset = 12;
+ lmo.l_next_size = 4;
+ lmo.l_prev_offset = 16;
+ lmo.l_prev_size = 4;
+ }
+
+ return lmp;
+}
+
+/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
+ for an LP64 SVR4 system. */
+
+struct link_map_offsets *
+svr4_lp64_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ /* Everything we need is in the first 16 bytes. */
+ lmo.r_debug_size = 16;
+ lmo.r_map_offset = 8;
+ lmo.r_map_size = 8;
+
+ /* Everything we need is in the first 40 bytes. */
+ lmo.link_map_size = 40;
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 8;
+ lmo.l_name_offset = 8;
+ lmo.l_name_size = 8;
+ lmo.l_next_offset = 24;
+ lmo.l_next_size = 8;
+ lmo.l_prev_offset = 32;
+ lmo.l_prev_size = 8;
+ }
+
+ return lmp;
+}
+\f
+
static struct target_so_ops svr4_so_ops;
extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */