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 "bfd-target.h"
#include "elf-bfd.h"
#include "exec.h"
+#include "auxv.h"
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
-/* This hook is set to a function that provides native link map
- offsets if the code in solib-legacy.c is linked in. */
-struct link_map_offsets *(*legacy_svr4_fetch_link_map_offsets_hook) (void);
-
/* Link map info to include in an allocated so_list entry */
struct lm_info
char *buf;
CORE_ADDR load_addr = 0;
int load_addr_found = 0;
+ int loader_found_in_list = 0;
struct so_list *so;
bfd *tmp_bfd = NULL;
struct target_ops *tmp_bfd_target;
be trivial on GNU/Linux). Therefore, we have to try an alternate
mechanism to find the dynamic linker's base address. */
- /* TODO drow/2006-09-12: This is somewhat fragile, because it
- relies on read_pc. On both Solaris and GNU/Linux we can use
- the AT_BASE auxilliary entry, which GDB now knows how to
- access, to find the base address. */
-
tmp_fd = solib_open (buf, &tmp_pathname);
if (tmp_fd >= 0)
tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd);
if (strcmp (buf, so->so_original_name) == 0)
{
load_addr_found = 1;
+ loader_found_in_list = 1;
load_addr = LM_ADDR_CHECK (so, tmp_bfd);
break;
}
so = so->next;
}
+ /* If we were not able to find the base address of the loader
+ from our so_list, then try using the AT_BASE auxilliary entry. */
+ if (!load_addr_found)
+ if (target_auxv_search (¤t_target, AT_BASE, &load_addr) > 0)
+ load_addr_found = 1;
+
/* Otherwise we find the dynamic linker's base address by examining
the current pc (which should point at the entry point for the
- dynamic linker) and subtracting the offset of the entry point. */
+ dynamic linker) and subtracting the offset of the entry point.
+
+ This is more fragile than the previous approaches, but is a good
+ fallback method because it has actually been working well in
+ most cases. */
if (!load_addr_found)
+ load_addr = (read_pc ()
+ - exec_entry_point (tmp_bfd, tmp_bfd_target));
+
+ if (!loader_found_in_list)
{
- load_addr = (read_pc ()
- - exec_entry_point (tmp_bfd, tmp_bfd_target));
debug_loader_name = xstrdup (buf);
debug_loader_offset_p = 1;
debug_loader_offset = load_addr;
struct solib_svr4_ops *ops;
ops = OBSTACK_ZALLOC (obstack, struct solib_svr4_ops);
- ops->fetch_link_map_offsets = legacy_svr4_fetch_link_map_offsets_hook;
+ ops->fetch_link_map_offsets = NULL;
return ops;
}
/* Set the architecture-specific `struct link_map_offsets' fetcher for
- GDBARCH to FLMO. */
+ GDBARCH to FLMO. Also, install SVR4 solib_ops into GDBARCH. */
void
set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
struct solib_svr4_ops *ops = gdbarch_data (gdbarch, solib_svr4_data);
ops->fetch_link_map_offsets = flmo;
+
+ set_solib_ops (gdbarch, &svr4_so_ops);
}
/* Fetch a link_map_offsets structure using the architecture-specific
svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
-
- /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */
- current_target_so_ops = &svr4_so_ops;
}