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;