X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsolib-svr4.c;h=702e6f685bb53bcdf5e5cd6c8b0b979ef2ede299;hb=8d4e36bad1bab0ff367a2f9ab7a131d63e030de0;hp=48fb6cb94f12d297233ebdc1028f4da4dd7db102;hpb=6314a3493442b8fa5942312c2a3b0264024f7b78;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 48fb6cb94f..702e6f685b 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1,13 +1,13 @@
/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
- 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+ 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GDB.
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,
@@ -16,9 +16,7 @@
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see . */
#include "defs.h"
@@ -34,30 +32,23 @@
#include "target.h"
#include "inferior.h"
+#include "gdb_assert.h"
+
#include "solist.h"
+#include "solib.h"
#include "solib-svr4.h"
#include "bfd-target.h"
+#include "elf-bfd.h"
#include "exec.h"
-
-#ifndef SVR4_FETCH_LINK_MAP_OFFSETS
-#define SVR4_FETCH_LINK_MAP_OFFSETS() svr4_fetch_link_map_offsets ()
-#endif
+#include "auxv.h"
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
-static struct link_map_offsets *legacy_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
-/* fetch_link_map_offsets_gdbarch_data is a handle used to obtain the
- architecture specific link map offsets fetching function. */
-
-static struct gdbarch_data *fetch_link_map_offsets_gdbarch_data;
-
-/* legacy_svr4_fetch_link_map_offsets_hook is a pointer to a function
- which is used to fetch link map offsets. It will only be set
- by solib-legacy.c, if at all. */
-
-struct link_map_offsets *(*legacy_svr4_fetch_link_map_offsets_hook)(void) = 0;
+/* 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 */
@@ -66,7 +57,14 @@ struct lm_info
/* Pointer to copy of link map from inferior. The type is char *
rather than void *, so that we may use byte offsets to find the
various fields without the need for a cast. */
- char *lm;
+ gdb_byte *lm;
+
+ /* Amount by which addresses in the binary should be relocated to
+ match the inferior. This could most often be taken directly
+ from lm, but when prelinking is involved and the prelink base
+ address changes, we may need a different offset, we want to
+ warn about the difference and compute it only once. */
+ CORE_ADDR l_addr;
};
/* On SVR4 systems, a list of symbols in the dynamic linker where
@@ -85,16 +83,6 @@ static char *solib_break_names[] =
"rtld_db_dlactivity",
"_rtld_debug_state",
- /* On the 64-bit PowerPC, the linker symbol with the same name as
- the C function points to a function descriptor, not to the entry
- point. The linker symbol whose name is the C function name
- prefixed with a '.' points to the function's entry point. So
- when we look through this table, we ignore symbols that point
- into the data section (thus skipping the descriptor's symbol),
- and eventually try this one, giving us the real entry point
- address. */
- "._dl_debug_state",
-
NULL
};
@@ -119,68 +107,152 @@ static char *main_name_list[] =
NULL
};
-/* Macro to extract an address from a solib structure. When GDB is
- configured for some 32-bit targets (e.g. Solaris 2.7 sparc), BFD is
- configured to handle 64-bit targets, so CORE_ADDR is 64 bits. We
- have to extract only the significant bits of addresses to get the
- right address when accessing the core file BFD.
+/* link map access functions */
- Assume that the address is unsigned. */
+static CORE_ADDR
+LM_ADDR_FROM_LINK_MAP (struct so_list *so)
+{
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-#define SOLIB_EXTRACT_ADDRESS(MEMBER) \
- extract_unsigned_integer (&(MEMBER), sizeof (MEMBER))
+ return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset,
+ builtin_type_void_data_ptr);
+}
-/* local data declarations */
+static int
+HAS_LM_DYNAMIC_FROM_LINK_MAP ()
+{
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-/* link map access functions */
+ return lmo->l_ld_offset >= 0;
+}
static CORE_ADDR
-LM_ADDR (struct so_list *so)
+LM_DYNAMIC_FROM_LINK_MAP (struct so_list *so)
{
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+
+ return extract_typed_address (so->lm_info->lm + lmo->l_ld_offset,
+ builtin_type_void_data_ptr);
+}
+
+static CORE_ADDR
+LM_ADDR_CHECK (struct so_list *so, bfd *abfd)
+{
+ if (so->lm_info->l_addr == (CORE_ADDR)-1)
+ {
+ struct bfd_section *dyninfo_sect;
+ CORE_ADDR l_addr, l_dynaddr, dynaddr, align = 0x1000;
+
+ l_addr = LM_ADDR_FROM_LINK_MAP (so);
+
+ if (! abfd || ! HAS_LM_DYNAMIC_FROM_LINK_MAP ())
+ goto set_addr;
+
+ l_dynaddr = LM_DYNAMIC_FROM_LINK_MAP (so);
+
+ dyninfo_sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (dyninfo_sect == NULL)
+ goto set_addr;
+
+ dynaddr = bfd_section_vma (abfd, dyninfo_sect);
+
+ if (dynaddr + l_addr != l_dynaddr)
+ {
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ {
+ Elf_Internal_Ehdr *ehdr = elf_tdata (abfd)->elf_header;
+ Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
+ int i;
+
+ align = 1;
- return (CORE_ADDR) extract_signed_integer (so->lm_info->lm + lmo->l_addr_offset,
- lmo->l_addr_size);
+ for (i = 0; i < ehdr->e_phnum; i++)
+ if (phdr[i].p_type == PT_LOAD && phdr[i].p_align > align)
+ align = phdr[i].p_align;
+ }
+
+ /* Turn it into a mask. */
+ align--;
+
+ /* If the changes match the alignment requirements, we
+ assume we're using a core file that was generated by the
+ same binary, just prelinked with a different base offset.
+ If it doesn't match, we may have a different binary, the
+ same binary with the dynamic table loaded at an unrelated
+ location, or anything, really. To avoid regressions,
+ don't adjust the base offset in the latter case, although
+ odds are that, if things really changed, debugging won't
+ quite work. */
+ if ((l_addr & align) == ((l_dynaddr - dynaddr) & align))
+ {
+ l_addr = l_dynaddr - dynaddr;
+
+ warning (_(".dynamic section for \"%s\" "
+ "is not at the expected address"), so->so_name);
+ warning (_("difference appears to be caused by prelink, "
+ "adjusting expectations"));
+ }
+ else
+ warning (_(".dynamic section for \"%s\" "
+ "is not at the expected address "
+ "(wrong library or version mismatch?)"), so->so_name);
+ }
+
+ set_addr:
+ so->lm_info->l_addr = l_addr;
+ }
+
+ return so->lm_info->l_addr;
}
static CORE_ADDR
LM_NEXT (struct so_list *so)
{
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- /* Assume that the address is unsigned. */
- return extract_unsigned_integer (so->lm_info->lm + lmo->l_next_offset,
- lmo->l_next_size);
+ return extract_typed_address (so->lm_info->lm + lmo->l_next_offset,
+ builtin_type_void_data_ptr);
}
static CORE_ADDR
LM_NAME (struct so_list *so)
{
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- /* Assume that the address is unsigned. */
- return extract_unsigned_integer (so->lm_info->lm + lmo->l_name_offset,
- lmo->l_name_size);
+ return extract_typed_address (so->lm_info->lm + lmo->l_name_offset,
+ builtin_type_void_data_ptr);
}
static int
IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so)
{
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+
+ /* Assume that everything is a library if the dynamic loader was loaded
+ late by a static executable. */
+ if (bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
+ return 0;
- /* Assume that the address is unsigned. */
- return extract_unsigned_integer (so->lm_info->lm + lmo->l_prev_offset,
- lmo->l_prev_size) == 0;
+ return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
+ builtin_type_void_data_ptr) == 0;
}
static CORE_ADDR debug_base; /* Base of dynamic linker structures */
-static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
+
+/* Validity flag for debug_loader_offset. */
+static int debug_loader_offset_p;
+
+/* Load address for the dynamic linker, inferred. */
+static CORE_ADDR debug_loader_offset;
+
+/* Name of the dynamic linker, valid if debug_loader_offset_p. */
+static char *debug_loader_name;
/* Local function prototypes */
static int match_main (char *);
-static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
+static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
/*
@@ -190,24 +262,25 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
SYNOPSIS
- CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
+ CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
DESCRIPTION
An expensive way to lookup the value of a single symbol for
bfd's that are only temporary anyway. This is used by the
shared library support to find the address of the debugger
- interface structures in the shared library.
+ notification routine in the shared library.
- If SECT_FLAGS is non-zero, only match symbols in sections whose
- flags include all those in SECT_FLAGS.
+ The returned symbol may be in a code or data section; functions
+ will normally be in a code section, but may be in a data section
+ if this architecture uses function descriptors.
Note that 0 is specifically allowed as an error return (no
such symbol).
*/
static CORE_ADDR
-bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
+bfd_lookup_symbol (bfd *abfd, char *symname)
{
long storage_needed;
asymbol *sym;
@@ -229,9 +302,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
{
sym = *symbol_table++;
if (strcmp (sym->name, symname) == 0
- && (sym->section->flags & sect_flags) == sect_flags)
+ && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
{
- /* Bfd symbols are section relative. */
+ /* BFD symbols are section relative. */
symaddr = sym->value + sym->section->vma;
break;
}
@@ -258,9 +331,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
sym = *symbol_table++;
if (strcmp (sym->name, symname) == 0
- && (sym->section->flags & sect_flags) == sect_flags)
+ && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
{
- /* Bfd symbols are section relative. */
+ /* BFD symbols are section relative. */
symaddr = sym->value + sym->section->vma;
break;
}
@@ -271,132 +344,83 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
return symaddr;
}
-#ifdef HANDLE_SVR4_EXEC_EMULATORS
-
-/*
- Solaris BCP (the part of Solaris which allows it to run SunOS4
- a.out files) throws in another wrinkle. Solaris does not fill
- in the usual a.out link map structures when running BCP programs,
- the only way to get at them is via groping around in the dynamic
- linker.
- The dynamic linker and it's structures are located in the shared
- C library, which gets run as the executable's "interpreter" by
- the kernel.
-
- Note that we can assume nothing about the process state at the time
- we need to find these structures. We may be stopped on the first
- instruction of the interpreter (C shared library), the first
- instruction of the executable itself, or somewhere else entirely
- (if we attached to the process for example).
- */
-
-static char *debug_base_symbols[] =
-{
- "r_debug", /* Solaris 2.3 */
- "_r_debug", /* Solaris 2.1, 2.2 */
- NULL
-};
-
-static int look_for_base (int, CORE_ADDR);
-
-/*
-
- LOCAL FUNCTION
-
- look_for_base -- examine file for each mapped address segment
-
- SYNOPSYS
-
- static int look_for_base (int fd, CORE_ADDR baseaddr)
-
- DESCRIPTION
-
- This function is passed to proc_iterate_over_mappings, which
- causes it to get called once for each mapped address space, with
- an open file descriptor for the file mapped to that space, and the
- base address of that mapped space.
-
- Our job is to find the debug base symbol in the file that this
- fd is open on, if it exists, and if so, initialize the dynamic
- linker structure base address debug_base.
-
- Note that this is a computationally expensive proposition, since
- we basically have to open a bfd on every call, so we specifically
- avoid opening the exec file.
- */
+/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
+ returned and the corresponding PTR is set. */
static int
-look_for_base (int fd, CORE_ADDR baseaddr)
+scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
{
- bfd *interp_bfd;
- CORE_ADDR address = 0;
- char **symbolp;
-
- /* If the fd is -1, then there is no file that corresponds to this
- mapped memory segment, so skip it. Also, if the fd corresponds
- to the exec file, skip it as well. */
-
- if (fd == -1
- || (exec_bfd != NULL
- && fdmatch (fileno ((FILE *) (exec_bfd->iostream)), fd)))
- {
- return (0);
- }
-
- /* Try to open whatever random file this fd corresponds to. Note that
- we have no way currently to find the filename. Don't gripe about
- any problems we might have, just fail. */
-
- if ((interp_bfd = bfd_fdopenr ("unnamed", gnutarget, fd)) == NULL)
- {
- return (0);
- }
- if (!bfd_check_format (interp_bfd, bfd_object))
- {
- /* FIXME-leak: on failure, might not free all memory associated with
- interp_bfd. */
- bfd_close (interp_bfd);
- return (0);
- }
-
- /* Now try to find our debug base symbol in this file, which we at
- least know to be a valid ELF executable or shared library. */
+ int arch_size, step, sect_size;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr, dyn_addr;
+ gdb_byte *bufend, *bufstart, *buf;
+ Elf32_External_Dyn *x_dynp_32;
+ Elf64_External_Dyn *x_dynp_64;
+ struct bfd_section *sect;
+
+ if (abfd == NULL)
+ return 0;
+ arch_size = bfd_get_arch_size (abfd);
+ if (arch_size == -1)
+ return 0;
- for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
- {
- address = bfd_lookup_symbol (interp_bfd, *symbolp, 0);
- if (address != 0)
- {
- break;
- }
- }
- if (address == 0)
- {
- /* FIXME-leak: on failure, might not free all memory associated with
- interp_bfd. */
- bfd_close (interp_bfd);
- return (0);
- }
+ /* Find the start address of the .dynamic section. */
+ sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (sect == NULL)
+ return 0;
+ dyn_addr = bfd_section_vma (abfd, sect);
+
+ /* Read in .dynamic from the BFD. We will get the actual value
+ from memory later. */
+ sect_size = bfd_section_size (abfd, sect);
+ buf = bufstart = alloca (sect_size);
+ if (!bfd_get_section_contents (abfd, sect,
+ buf, 0, sect_size))
+ return 0;
- /* Eureka! We found the symbol. But now we may need to relocate it
- by the base address. If the symbol's value is less than the base
- address of the shared library, then it hasn't yet been relocated
- by the dynamic linker, and we have to do it ourself. FIXME: Note
- that we make the assumption that the first segment that corresponds
- to the shared library has the base address to which the library
- was relocated. */
+ /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
+ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+ : sizeof (Elf64_External_Dyn);
+ for (bufend = buf + sect_size;
+ buf < bufend;
+ buf += step)
+ {
+ if (arch_size == 32)
+ {
+ x_dynp_32 = (Elf32_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
+ dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
+ }
+ else
+ {
+ x_dynp_64 = (Elf64_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+ dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
+ }
+ if (dyn_tag == DT_NULL)
+ return 0;
+ if (dyn_tag == dyntag)
+ {
+ /* If requested, try to read the runtime value of this .dynamic
+ entry. */
+ if (ptr)
+ {
+ gdb_byte ptr_buf[8];
+ CORE_ADDR ptr_addr;
+
+ ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
+ if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
+ dyn_ptr = extract_typed_address (ptr_buf,
+ builtin_type_void_data_ptr);
+ *ptr = dyn_ptr;
+ }
+ return 1;
+ }
+ }
- if (address < baseaddr)
- {
- address += baseaddr;
- }
- debug_base = address;
- /* FIXME-leak: on failure, might not free all memory associated with
- interp_bfd. */
- bfd_close (interp_bfd);
- return (1);
+ return 0;
}
-#endif /* HANDLE_SVR4_EXEC_EMULATORS */
+
/*
@@ -425,104 +449,34 @@ look_for_base (int fd, CORE_ADDR baseaddr)
static CORE_ADDR
elf_locate_base (void)
{
- struct bfd_section *dyninfo_sect;
- int dyninfo_sect_size;
- CORE_ADDR dyninfo_addr;
- char *buf;
- char *bufend;
- int arch_size;
-
- /* Find the start address of the .dynamic section. */
- dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
- if (dyninfo_sect == NULL)
- return 0;
- dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
-
- /* Read in .dynamic section, silently ignore errors. */
- dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
- buf = alloca (dyninfo_sect_size);
- if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
- return 0;
-
- /* Find the DT_DEBUG entry in the the .dynamic section.
- For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
- no DT_DEBUG entries. */
-
- arch_size = bfd_get_arch_size (exec_bfd);
- if (arch_size == -1) /* failure */
- return 0;
-
- if (arch_size == 32)
- { /* 32-bit elf */
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf32_External_Dyn))
- {
- Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
+ struct minimal_symbol *msymbol;
+ CORE_ADDR dyn_ptr;
- dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- char *pbuf;
- int pbuf_size = TARGET_PTR_BIT / HOST_CHAR_BIT;
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_unsigned_integer (pbuf, pbuf_size);
- }
- }
- }
- else /* 64-bit elf */
+ /* Look for DT_MIPS_RLD_MAP first. MIPS executables use this
+ instead of DT_DEBUG, although they sometimes contain an unused
+ DT_DEBUG. */
+ if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr))
{
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf64_External_Dyn))
- {
- Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
-
- dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- char *pbuf;
- int pbuf_size = TARGET_PTR_BIT / HOST_CHAR_BIT;
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_unsigned_integer (pbuf, pbuf_size);
- }
- }
+ gdb_byte *pbuf;
+ int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ pbuf = alloca (pbuf_size);
+ /* DT_MIPS_RLD_MAP contains a pointer to the address
+ of the dynamic link structure. */
+ if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
+ return 0;
+ return extract_typed_address (pbuf, builtin_type_void_data_ptr);
}
+ /* Find DT_DEBUG. */
+ if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr))
+ return dyn_ptr;
+
+ /* This may be a static executable. Look for the symbol
+ conventionally named _r_debug, as a last resort. */
+ msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
+ if (msymbol != NULL)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
+
/* DT_DEBUG entry not found. */
return 0;
}
@@ -578,52 +532,44 @@ locate_base (void)
if (exec_bfd != NULL
&& bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
debug_base = elf_locate_base ();
-#ifdef HANDLE_SVR4_EXEC_EMULATORS
- /* Try it the hard way for emulated executables. */
- else if (!ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
- proc_iterate_over_mappings (look_for_base);
-#endif
}
return (debug_base);
}
-/*
-
- LOCAL FUNCTION
-
- first_link_map_member -- locate first member in dynamic linker's map
+/* Find the first element in the inferior's dynamic link map, and
+ return its address in the inferior.
- SYNOPSIS
-
- static CORE_ADDR first_link_map_member (void)
-
- DESCRIPTION
-
- Find the first element in the inferior's dynamic link map, and
- return its address in the inferior. This function doesn't copy the
- link map entry itself into our address space; current_sos actually
- does the reading. */
+ FIXME: Perhaps we should validate the info somehow, perhaps by
+ checking r_version for a known version number, or r_state for
+ RT_CONSISTENT. */
static CORE_ADDR
-first_link_map_member (void)
+solib_svr4_r_map (void)
{
- CORE_ADDR lm = 0;
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
- char *r_map_buf = xmalloc (lmo->r_map_size);
- struct cleanup *cleanups = make_cleanup (xfree, r_map_buf);
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- read_memory (debug_base + lmo->r_map_offset, r_map_buf, lmo->r_map_size);
-
- /* Assume that the address is unsigned. */
- lm = extract_unsigned_integer (r_map_buf, lmo->r_map_size);
+ return read_memory_typed_address (debug_base + lmo->r_map_offset,
+ builtin_type_void_data_ptr);
+}
- /* FIXME: Perhaps we should validate the info somehow, perhaps by
- checking r_version for a known version number, or r_state for
- RT_CONSISTENT. */
+/* Find the link map for the dynamic linker (if it is not in the
+ normal list of loaded shared objects). */
- do_cleanups (cleanups);
+static CORE_ADDR
+solib_svr4_r_ldsomap (void)
+{
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ ULONGEST version;
+
+ /* Check version, and return zero if `struct r_debug' doesn't have
+ the r_ldsomap member. */
+ version = read_memory_unsigned_integer (debug_base + lmo->r_version_offset,
+ lmo->r_version_size);
+ if (version < 2 || lmo->r_ldsomap_offset == -1)
+ return 0;
- return (lm);
+ return read_memory_typed_address (debug_base + lmo->r_ldsomap_offset,
+ builtin_type_void_data_ptr);
}
/*
@@ -655,8 +601,9 @@ open_symbol_file_object (void *from_ttyp)
char *filename;
int errcode;
int from_tty = *(int *)from_ttyp;
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
- char *l_name_buf = xmalloc (lmo->l_name_size);
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ int l_name_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ gdb_byte *l_name_buf = xmalloc (l_name_size);
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
if (symfile_objfile)
@@ -667,15 +614,15 @@ open_symbol_file_object (void *from_ttyp)
return 0; /* failed somehow... */
/* First link map member should be the executable. */
- if ((lm = first_link_map_member ()) == 0)
+ lm = solib_svr4_r_map ();
+ if (lm == 0)
return 0; /* failed somehow... */
/* Read address of name from target memory to GDB. */
- read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
+ read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size);
- /* Convert the address to host format. Assume that the address is
- unsigned. */
- l_name = extract_unsigned_integer (l_name_buf, lmo->l_name_size);
+ /* Convert the address to host format. */
+ l_name = extract_typed_address (l_name_buf, builtin_type_void_data_ptr);
/* Free l_name_buf. */
do_cleanups (cleanups);
@@ -685,21 +632,52 @@ open_symbol_file_object (void *from_ttyp)
/* Now fetch the filename from target memory. */
target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ make_cleanup (xfree, filename);
if (errcode)
{
- warning ("failed to read exec filename from attached file: %s",
+ warning (_("failed to read exec filename from attached file: %s"),
safe_strerror (errcode));
return 0;
}
- make_cleanup (xfree, filename);
/* Have a pathname: read the symbol file. */
symbol_file_add_main (filename, from_tty);
return 1;
}
+/* If no shared library information is available from the dynamic
+ linker, build a fallback list from other sources. */
+
+static struct so_list *
+svr4_default_sos (void)
+{
+ struct so_list *head = NULL;
+ struct so_list **link_ptr = &head;
+
+ if (debug_loader_offset_p)
+ {
+ struct so_list *new = XZALLOC (struct so_list);
+
+ new->lm_info = xmalloc (sizeof (struct lm_info));
+
+ /* Nothing will ever check the cached copy of the link
+ map if we set l_addr. */
+ new->lm_info->l_addr = debug_loader_offset;
+ new->lm_info->lm = NULL;
+
+ strncpy (new->so_name, debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
+ new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (new->so_original_name, new->so_name);
+
+ *link_ptr = new;
+ link_ptr = &new->next;
+ }
+
+ return head;
+}
+
/* LOCAL FUNCTION
current_sos -- build a list of currently loaded shared objects
@@ -725,6 +703,7 @@ svr4_current_sos (void)
CORE_ADDR lm;
struct so_list *head = 0;
struct so_list **link_ptr = &head;
+ CORE_ADDR ldsomap = 0;
/* Make sure we've looked up the inferior's dynamic linker's base
structure. */
@@ -735,27 +714,25 @@ svr4_current_sos (void)
/* If we can't find the dynamic linker's base structure, this
must not be a dynamically linked executable. Hmm. */
if (! debug_base)
- return 0;
+ return svr4_default_sos ();
}
/* Walk the inferior's link map list, and build our list of
`struct so_list' nodes. */
- lm = first_link_map_member ();
+ lm = solib_svr4_r_map ();
+
while (lm)
{
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
- struct so_list *new
- = (struct so_list *) xmalloc (sizeof (struct so_list));
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ struct so_list *new = XZALLOC (struct so_list);
struct cleanup *old_chain = make_cleanup (xfree, new);
- memset (new, 0, sizeof (*new));
-
new->lm_info = xmalloc (sizeof (struct lm_info));
make_cleanup (xfree, new->lm_info);
- new->lm_info->lm = xmalloc (lmo->link_map_size);
+ new->lm_info->l_addr = (CORE_ADDR)-1;
+ new->lm_info->lm = xzalloc (lmo->link_map_size);
make_cleanup (xfree, new->lm_info->lm);
- memset (new->lm_info->lm, 0, lmo->link_map_size);
read_memory (lm, new->lm_info->lm, lmo->link_map_size);
@@ -766,7 +743,7 @@ svr4_current_sos (void)
SVR4, it has no name. For others (Solaris 2.3 for example), it
does have a name, so we can no longer use a missing name to
decide when to ignore it. */
- if (IGNORE_FIRST_LINK_MAP_ENTRY (new))
+ if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
free_so (new);
else
{
@@ -777,17 +754,15 @@ svr4_current_sos (void)
target_read_string (LM_NAME (new), &buffer,
SO_NAME_MAX_PATH_SIZE - 1, &errcode);
if (errcode != 0)
- {
- warning ("current_sos: Can't read pathname for load map: %s\n",
- safe_strerror (errcode));
- }
+ warning (_("Can't read pathname for load map: %s."),
+ safe_strerror (errcode));
else
{
strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
- xfree (buffer);
strcpy (new->so_original_name, new->so_name);
}
+ xfree (buffer);
/* If this entry has no name, or its name matches the name
for the main executable, don't include it in the list. */
@@ -802,9 +777,19 @@ svr4_current_sos (void)
}
}
+ /* On Solaris, the dynamic linker is not in the normal list of
+ shared objects, so make sure we pick it up too. Having
+ symbol information for the dynamic linker is quite crucial
+ for skipping dynamic linker resolver code. */
+ if (lm == 0 && ldsomap == 0)
+ lm = ldsomap = solib_svr4_r_ldsomap ();
+
discard_cleanups (old_chain);
}
+ if (head == NULL)
+ return svr4_default_sos ();
+
return head;
}
@@ -823,59 +808,59 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
return 0; /* failed somehow... */
/* Position ourselves on the first link map. */
- lm = first_link_map_member ();
+ lm = solib_svr4_r_map ();
while (lm)
{
/* Get info on the layout of the r_debug and link_map structures. */
- struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
int errcode;
char *buffer;
struct lm_info objfile_lm_info;
struct cleanup *old_chain;
CORE_ADDR name_address;
- char *l_name_buf = xmalloc (lmo->l_name_size);
+ int l_name_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ gdb_byte *l_name_buf = xmalloc (l_name_size);
old_chain = make_cleanup (xfree, l_name_buf);
/* Set up the buffer to contain the portion of the link_map
structure that gdb cares about. Note that this is not the
whole link_map structure. */
- objfile_lm_info.lm = xmalloc (lmo->link_map_size);
+ objfile_lm_info.lm = xzalloc (lmo->link_map_size);
make_cleanup (xfree, objfile_lm_info.lm);
- memset (objfile_lm_info.lm, 0, lmo->link_map_size);
/* Read the link map into our internal structure. */
read_memory (lm, objfile_lm_info.lm, lmo->link_map_size);
/* Read address of name from target memory to GDB. */
- read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
+ read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size);
- /* Extract this object's name. Assume that the address is
- unsigned. */
- name_address = extract_unsigned_integer (l_name_buf, lmo->l_name_size);
+ /* Extract this object's name. */
+ name_address = extract_typed_address (l_name_buf,
+ builtin_type_void_data_ptr);
target_read_string (name_address, &buffer,
SO_NAME_MAX_PATH_SIZE - 1, &errcode);
make_cleanup (xfree, buffer);
if (errcode != 0)
- {
- warning ("svr4_fetch_objfile_link_map: Can't read pathname for load map: %s\n",
- safe_strerror (errcode));
- }
+ warning (_("Can't read pathname for load map: %s."),
+ safe_strerror (errcode));
else
{
/* Is this the linkmap for the file we want? */
/* If the file is not a shared library and has no name,
we are sure it is the main executable, so we return that. */
- if ((buffer && strcmp (buffer, objfile->name) == 0)
- || (!(objfile->flags & OBJF_SHARED) && (strcmp (buffer, "") == 0)))
+
+ if (buffer
+ && ((strcmp (buffer, objfile->name) == 0)
+ || (!(objfile->flags & OBJF_SHARED)
+ && (strcmp (buffer, "") == 0))))
{
do_cleanups (old_chain);
return lm;
}
}
- /* Not the file we wanted, continue checking. Assume that the
- address is unsigned. */
- lm = extract_unsigned_integer (objfile_lm_info.lm + lmo->l_next_offset,
- lmo->l_next_size);
+ /* Not the file we wanted, continue checking. */
+ lm = extract_typed_address (objfile_lm_info.lm + lmo->l_next_offset,
+ builtin_type_void_data_ptr);
do_cleanups (old_chain);
}
return 0;
@@ -906,7 +891,7 @@ static CORE_ADDR interp_text_sect_high;
static CORE_ADDR interp_plt_sect_low;
static CORE_ADDR interp_plt_sect_high;
-static int
+int
svr4_in_dynsym_resolve_code (CORE_ADDR pc)
{
return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
@@ -979,8 +964,6 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
static int
enable_break (void)
{
- int success = 0;
-
#ifdef BKPT_AT_SYMBOL
struct minimal_symbol *msymbol;
@@ -1003,7 +986,7 @@ enable_break (void)
char *buf;
CORE_ADDR load_addr = 0;
int load_addr_found = 0;
- struct so_list *inferior_sos;
+ struct so_list *so;
bfd *tmp_bfd = NULL;
struct target_ops *tmp_bfd_target;
int tmp_fd = -1;
@@ -1026,9 +1009,9 @@ enable_break (void)
be trivial on GNU/Linux). Therefore, we have to try an alternate
mechanism to find the dynamic linker's base address. */
- tmp_fd = solib_open (buf, &tmp_pathname);
+ tmp_fd = solib_open (buf, &tmp_pathname);
if (tmp_fd >= 0)
- tmp_bfd = bfd_fdopenr (tmp_pathname, gnutarget, tmp_fd);
+ tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd);
if (tmp_bfd == NULL)
goto bkpt_at_symbol;
@@ -1036,7 +1019,7 @@ enable_break (void)
/* Make sure the dynamic linker's really a useful object. */
if (!bfd_check_format (tmp_bfd, bfd_object))
{
- warning ("Unable to grok dynamic linker %s as an object file", buf);
+ warning (_("Unable to grok dynamic linker %s as an object file"), buf);
bfd_close (tmp_bfd);
goto bkpt_at_symbol;
}
@@ -1046,31 +1029,43 @@ enable_break (void)
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 ();
- if (inferior_sos)
- {
- /* Connected to a running target. Update our shared library table. */
- solib_add (NULL, 0, NULL, auto_solib_add);
- }
- while (inferior_sos)
+ /* On a running target, we can get the dynamic linker's base
+ address from the shared library table. */
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+ so = master_so_list ();
+ while (so)
{
- if (strcmp (buf, inferior_sos->so_original_name) == 0)
+ if (strcmp (buf, so->so_original_name) == 0)
{
load_addr_found = 1;
- load_addr = LM_ADDR (inferior_sos);
+ load_addr = LM_ADDR_CHECK (so, tmp_bfd);
break;
}
- inferior_sos = inferior_sos->next;
+ 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));
+ {
+ 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;
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+ }
/* Record the relocated start and end address of the dynamic linker
text and plt section for svr4_in_dynsym_resolve_code. */
@@ -1094,20 +1089,19 @@ enable_break (void)
/* Now try to set a breakpoint in the dynamic linker. */
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
- /* On ABI's that use function descriptors, there are usually
- two linker symbols associated with each C function: one
- pointing at the actual entry point of the machine code,
- and one pointing at the function's descriptor. The
- latter symbol has the same name as the C function.
-
- What we're looking for here is the machine code entry
- point, so we are only interested in symbols in code
- sections. */
- sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep, SEC_CODE);
+ sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
if (sym_addr != 0)
break;
}
+ if (sym_addr != 0)
+ /* Convert 'sym_addr' from a function pointer to an address.
+ Because we pass tmp_bfd_target instead of the current
+ target, this will always produce an unrelocated value. */
+ sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ sym_addr,
+ tmp_bfd_target);
+
/* We're done with both the temporary bfd and target. Remember,
closing the target closes the underlying bfd. */
target_close (tmp_bfd_target, 0);
@@ -1121,14 +1115,16 @@ enable_break (void)
/* For whatever reason we couldn't set a breakpoint in the dynamic
linker. Warn and drop into the old code. */
bkpt_at_symbol:
- warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
+ xfree (tmp_pathname);
+ warning (_("Unable to find dynamic linker breakpoint function.\n"
+ "GDB will be unable to debug shared library initializers\n"
+ "and track explicitly loaded dynamic code."));
}
- /* Scan through the list of symbols, trying to look up the symbol and
- set a breakpoint there. Terminate loop when we/if we succeed. */
+ /* Scan through the lists of symbols, trying to look up the symbol and
+ set a breakpoint there. Terminate loop when we/if we succeed. */
- breakpoint_addr = 0;
- for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
+ for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
@@ -1138,12 +1134,18 @@ enable_break (void)
}
}
- /* Nothing good happened. */
- success = 0;
-
+ for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
+ {
+ msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+ return 1;
+ }
+ }
#endif /* BKPT_AT_SYMBOL */
- return (success);
+ return 0;
}
/*
@@ -1290,7 +1292,7 @@ svr4_relocate_main_executable (void)
SYNOPSIS
- void svr4_solib_create_inferior_hook()
+ void svr4_solib_create_inferior_hook ()
DESCRIPTION
@@ -1341,17 +1343,10 @@ svr4_solib_create_inferior_hook (void)
svr4_relocate_main_executable ();
if (!svr4_have_link_map_offsets ())
- {
- warning ("no shared library support for this OS / ABI");
- return;
-
- }
+ return;
if (!enable_break ())
- {
- warning ("shared library handler failed to enable breakpoint");
- return;
- }
+ return;
#if defined(_SCO_DS)
/* SCO needs the loop below, other systems should be using the
@@ -1380,6 +1375,10 @@ static void
svr4_clear_solib (void)
{
debug_base = 0;
+ debug_loader_offset_p = 0;
+ debug_loader_offset = 0;
+ xfree (debug_loader_name);
+ debug_loader_name = NULL;
}
static void
@@ -1401,17 +1400,17 @@ svr4_free_so (struct so_list *so)
natural pointer/address correspondence. (For example, on the MIPS,
converting a 32-bit pointer to a 64-bit CORE_ADDR requires you to
sign-extend the value. There, simply truncating the bits above
- TARGET_PTR_BIT, as we do below, is no good.) This should probably
+ gdbarch_ptr_bit, as we do below, is no good.) This should probably
be a new gdbarch method or something. */
static CORE_ADDR
svr4_truncate_ptr (CORE_ADDR addr)
{
- if (TARGET_PTR_BIT == sizeof (CORE_ADDR) * 8)
+ if (gdbarch_ptr_bit (current_gdbarch) == sizeof (CORE_ADDR) * 8)
/* We don't need to truncate anything, and the bit twiddling below
will fail due to overflow problems. */
return addr;
else
- return addr & (((CORE_ADDR) 1 << TARGET_PTR_BIT) - 1);
+ return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (current_gdbarch)) - 1);
}
@@ -1419,104 +1418,161 @@ static void
svr4_relocate_section_addresses (struct so_list *so,
struct section_table *sec)
{
- sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
- sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
+ sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR_CHECK (so,
+ sec->bfd));
+ sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR_CHECK (so,
+ sec->bfd));
}
+
+/* Architecture-specific operations. */
-/* Fetch a link_map_offsets structure for native targets using struct
- definitions from link.h. See solib-legacy.c for the function
- which does the actual work.
-
- Note: For non-native targets (i.e. cross-debugging situations),
- a target specific fetch_link_map_offsets() function should be
- defined and registered via set_solib_svr4_fetch_link_map_offsets(). */
+/* Per-architecture data key. */
+static struct gdbarch_data *solib_svr4_data;
-static struct link_map_offsets *
-legacy_fetch_link_map_offsets (void)
+struct solib_svr4_ops
{
- if (legacy_svr4_fetch_link_map_offsets_hook)
- return legacy_svr4_fetch_link_map_offsets_hook ();
- else
- {
- internal_error (__FILE__, __LINE__,
- "legacy_fetch_link_map_offsets called without legacy "
- "link_map support enabled.");
- return 0;
- }
+ /* Return a description of the layout of `struct link_map'. */
+ struct link_map_offsets *(*fetch_link_map_offsets)(void);
+};
+
+/* Return a default for the architecture-specific operations. */
+
+static void *
+solib_svr4_init (struct obstack *obstack)
+{
+ 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;
+ return ops;
}
-/* Fetch a link_map_offsets structure using the method registered in the
- architecture vector. */
+/* Set the architecture-specific `struct link_map_offsets' fetcher for
+ GDBARCH to FLMO. */
+
+void
+set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
+ struct link_map_offsets *(*flmo) (void))
+{
+ struct solib_svr4_ops *ops = gdbarch_data (gdbarch, solib_svr4_data);
+
+ ops->fetch_link_map_offsets = flmo;
+}
+
+/* Fetch a link_map_offsets structure using the architecture-specific
+ `struct link_map_offsets' fetcher. */
static struct link_map_offsets *
svr4_fetch_link_map_offsets (void)
{
- struct link_map_offsets *(*flmo)(void) =
- gdbarch_data (current_gdbarch, fetch_link_map_offsets_gdbarch_data);
+ struct solib_svr4_ops *ops = gdbarch_data (current_gdbarch, solib_svr4_data);
- if (flmo == NULL)
- {
- internal_error (__FILE__, __LINE__,
- "svr4_fetch_link_map_offsets: fetch_link_map_offsets "
- "method not defined for this architecture.");
- return 0;
- }
- else
- return (flmo ());
+ gdb_assert (ops->fetch_link_map_offsets);
+ return ops->fetch_link_map_offsets ();
}
/* Return 1 if a link map offset fetcher has been defined, 0 otherwise. */
+
static int
svr4_have_link_map_offsets (void)
{
- struct link_map_offsets *(*flmo)(void) =
- gdbarch_data (current_gdbarch, fetch_link_map_offsets_gdbarch_data);
- if (flmo == NULL
- || (flmo == legacy_fetch_link_map_offsets
- && legacy_svr4_fetch_link_map_offsets_hook == NULL))
- return 0;
- else
- return 1;
+ struct solib_svr4_ops *ops = gdbarch_data (current_gdbarch, solib_svr4_data);
+ return (ops->fetch_link_map_offsets != NULL);
}
+
-/* set_solib_svr4_fetch_link_map_offsets() is intended to be called by
- a _gdbarch_init() function. It is used to establish an
- architecture specific link_map_offsets fetcher for the architecture
- being defined. */
+/* 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. */
-void
-set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
- struct link_map_offsets *(*flmo) (void))
+/* 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)
{
- set_gdbarch_data (gdbarch, fetch_link_map_offsets_gdbarch_data, flmo);
-}
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
-/* Initialize the architecture-specific link_map_offsets fetcher.
- This is called after _gdbarch_init() has set up its `struct
- gdbarch' for the new architecture, and is only called if the
- link_map_offsets fetcher isn't already initialized (which is
- usually done by calling set_solib_svr4_fetch_link_map_offsets()
- above in _gdbarch_init()). Therefore we attempt to provide a
- reasonable alternative (for native targets anyway) if the
- _gdbarch_init() fails to call
- set_solib_svr4_fetch_link_map_offsets(). */
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ lmo.r_version_offset = 0;
+ lmo.r_version_size = 4;
+ lmo.r_map_offset = 4;
+ lmo.r_ldsomap_offset = 20;
+
+ /* Everything we need is in the first 20 bytes. */
+ lmo.link_map_size = 20;
+ lmo.l_addr_offset = 0;
+ lmo.l_name_offset = 4;
+ lmo.l_ld_offset = 8;
+ lmo.l_next_offset = 12;
+ lmo.l_prev_offset = 16;
+ }
-static void *
-init_fetch_link_map_offsets (struct gdbarch *gdbarch)
+ 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)
{
- return legacy_fetch_link_map_offsets;
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ lmo.r_version_offset = 0;
+ lmo.r_version_size = 4;
+ lmo.r_map_offset = 8;
+ lmo.r_ldsomap_offset = 40;
+
+ /* Everything we need is in the first 40 bytes. */
+ lmo.link_map_size = 40;
+ lmo.l_addr_offset = 0;
+ lmo.l_name_offset = 8;
+ lmo.l_ld_offset = 16;
+ lmo.l_next_offset = 24;
+ lmo.l_prev_offset = 32;
+ }
+
+ return lmp;
}
+
+
+struct target_so_ops svr4_so_ops;
+
+/* Lookup global symbol for ELF DSOs linked with -Bsymbolic. Those DSOs have a
+ different rule for symbol lookup. The lookup begins here in the DSO, not in
+ the main executable. */
-static struct target_so_ops svr4_so_ops;
+static struct symbol *
+elf_lookup_lib_symbol (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain, struct symtab **symtab)
+{
+ if (objfile->obfd == NULL
+ || scan_dyntag (DT_SYMBOLIC, objfile->obfd, NULL) != 1)
+ return NULL;
+
+ return lookup_global_symbol_from_objfile
+ (objfile, name, linkage_name, domain, symtab);
+}
extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
void
_initialize_svr4_solib (void)
{
- fetch_link_map_offsets_gdbarch_data =
- register_gdbarch_data (init_fetch_link_map_offsets);
+ solib_svr4_data = gdbarch_data_register_pre_init (solib_svr4_init);
svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses;
svr4_so_ops.free_so = svr4_free_so;
@@ -1526,6 +1582,7 @@ _initialize_svr4_solib (void)
svr4_so_ops.current_sos = svr4_current_sos;
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;