diff options
Diffstat (limited to 'gdb/pa64solib.c')
-rw-r--r-- | gdb/pa64solib.c | 1248 |
1 files changed, 0 insertions, 1248 deletions
diff --git a/gdb/pa64solib.c b/gdb/pa64solib.c deleted file mode 100644 index f0589e7..0000000 --- a/gdb/pa64solib.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* Handle HP ELF shared libraries for GDB, the GNU Debugger. - - Copyright 1999, 2000, 2001, 2002, 2003, 2004 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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. - - HP in their infinite stupidity choose not to use standard ELF dynamic - linker interfaces. They also choose not to make their ELF dymamic - linker interfaces compatible with the SOM dynamic linker. The - net result is we can not use either of the existing somsolib.c or - solib.c. What a crock. - - Even more disgusting. This file depends on functions provided only - in certain PA64 libraries. Thus this file is supposed to only be - used native. When will HP ever learn that they need to provide the - same functionality in all their libraries! */ - -#include <dlfcn.h> -#include <elf.h> -#include <elf_hp.h> - -#include "defs.h" - -#include "frame.h" -#include "bfd.h" -#include "libhppa.h" -#include "gdbcore.h" -#include "symtab.h" -#include "breakpoint.h" -#include "symfile.h" -#include "objfiles.h" -#include "inferior.h" -#include "gdb-stabs.h" -#include "gdb_stat.h" -#include "gdbcmd.h" -#include "language.h" -#include "regcache.h" -#include "exec.h" -#include "hppa-tdep.h" - -#include <fcntl.h> - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -static CORE_ADDR bfd_lookup_symbol (bfd *, char *); -/* This lives in hppa-tdep.c. */ -extern struct unwind_table_entry *find_unwind_entry (CORE_ADDR pc); - -/* These ought to be defined in some public interface, but aren't. They - identify dynamic linker events. */ -#define DLD_CB_LOAD 1 -#define DLD_CB_UNLOAD 0 - -/* A structure to keep track of all the known shared objects. */ -struct so_list - { - bfd *abfd; - char *name; - struct so_list *next; - struct objfile *objfile; - CORE_ADDR pa64_solib_desc_addr; - struct load_module_desc pa64_solib_desc; - struct section_table *sections; - struct section_table *sections_end; - int loaded; - }; - -static struct so_list *so_list_head; - -/* This is the cumulative size in bytes of the symbol tables of all - shared objects on the so_list_head list. (When we say size, here - we mean of the information before it is brought into memory and - potentially expanded by GDB.) When adding a new shlib, this value - is compared against a threshold size, held by auto_solib_limit (in - megabytes). If adding symbols for the new shlib would cause the - total size to exceed the threshold, then the new shlib's symbols - are not loaded. */ -static LONGEST pa64_solib_total_st_size; - -/* When the threshold is reached for any shlib, we refuse to add - symbols for subsequent shlibs, even if those shlibs' symbols would - be small enough to fit under the threshold. Although this may - result in one, early large shlib preventing the loading of later, - smaller shlibs' symbols, it allows us to issue one informational - message. The alternative, to issue a message for each shlib whose - symbols aren't loaded, could be a big annoyance where the threshold - is exceeded due to a very large number of shlibs. */ -static int pa64_solib_st_size_threshold_exceeded; - -/* When adding fields, be sure to clear them in _initialize_pa64_solib. */ -typedef struct - { - CORE_ADDR dld_flags_addr; - LONGEST dld_flags; - struct bfd_section *dyninfo_sect; - int have_read_dld_descriptor; - int is_valid; - CORE_ADDR load_map; - CORE_ADDR load_map_addr; - struct load_module_desc dld_desc; - } -dld_cache_t; - -static dld_cache_t dld_cache; - -static void pa64_sharedlibrary_info_command (char *, int); - -static void pa64_solib_sharedlibrary_command (char *, int); - -static void *pa64_target_read_memory (void *, CORE_ADDR, size_t, int); - -static int read_dld_descriptor (struct target_ops *, int readsyms); - -static int read_dynamic_info (asection *, dld_cache_t *); - -static void add_to_solist (int, char *, int, struct load_module_desc *, - CORE_ADDR, struct target_ops *); - -/* When examining the shared library for debugging information we have to - look for HP debug symbols, stabs and dwarf2 debug symbols. */ -static char *pa64_debug_section_names[] = { - ".debug_header", ".debug_gntt", ".debug_lntt", ".debug_slt", ".debug_vt", - ".stabs", ".stabstr", ".debug_info", ".debug_abbrev", ".debug_aranges", - ".debug_macinfo", ".debug_line", ".debug_loc", ".debug_pubnames", - ".debug_str", NULL -}; - -/* Return a ballbark figure for the amount of memory GDB will need to - allocate to read in the debug symbols from FILENAME. */ -static LONGEST -pa64_solib_sizeof_symbol_table (char *filename) -{ - bfd *abfd; - int i; - int desc; - char *absolute_name; - LONGEST st_size = (LONGEST) 0; - asection *sect; - - /* We believe that filename was handed to us by the dynamic linker, and - is therefore always an absolute path. */ - desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename, - O_RDONLY | O_BINARY, 0, &absolute_name); - if (desc < 0) - { - perror_with_name (filename); - } - filename = absolute_name; - - abfd = bfd_fdopenr (filename, gnutarget, desc); - if (!abfd) - { - close (desc); - make_cleanup (xfree, filename); - error (_("\"%s\": can't open to read symbols: %s."), filename, - bfd_errmsg (bfd_get_error ())); - } - - if (!bfd_check_format (abfd, bfd_object)) - { - bfd_close (abfd); - make_cleanup (xfree, filename); - error (_("\"%s\": can't read symbols: %s."), filename, - bfd_errmsg (bfd_get_error ())); - } - - /* Sum the sizes of the various sections that compose debug info. */ - for (i = 0; pa64_debug_section_names[i] != NULL; i++) - { - asection *sect; - - sect = bfd_get_section_by_name (abfd, pa64_debug_section_names[i]); - if (sect) - st_size += (LONGEST)bfd_section_size (abfd, sect); - } - - bfd_close (abfd); - xfree (filename); - - /* Unfortunately, just summing the sizes of various debug info - sections isn't a very accurate measurement of how much heap - space the debugger will need to hold them. It also doesn't - account for space needed by linker (aka "minimal") symbols. - - Anecdotal evidence suggests that just summing the sizes of - debug-info-related sections understates the heap space needed - to represent it internally by about an order of magnitude. - - Since it's not exactly brain surgery we're doing here, rather - than attempt to more accurately measure the size of a shlib's - symbol table in GDB's heap, we'll just apply a 10x fudge- - factor to the debug info sections' size-sum. No, this doesn't - account for minimal symbols in non-debuggable shlibs. But it - all roughly washes out in the end. */ - return st_size * (LONGEST) 10; -} - -/* Add a shared library to the objfile list and load its symbols into - GDB's symbol table. */ -static void -pa64_solib_add_solib_objfile (struct so_list *so, char *name, int from_tty, - CORE_ADDR text_addr) -{ - bfd *tmp_bfd; - asection *sec; - struct hppa_objfile_private *obj_private; - struct section_addr_info *section_addrs; - struct cleanup *my_cleanups; - - /* We need the BFD so that we can look at its sections. We open up the - file temporarily, then close it when we are done. */ - tmp_bfd = bfd_openr (name, gnutarget); - if (tmp_bfd == NULL) - { - perror_with_name (name); - return; - } - - if (!bfd_check_format (tmp_bfd, bfd_object)) - { - bfd_close (tmp_bfd); - error (_("\"%s\" is not an object file: %s"), name, - bfd_errmsg (bfd_get_error ())); - } - - - /* Undo some braindamage from symfile.c. - - First, symfile.c will subtract the VMA of the first .text section - in the shared library that it finds. Undo that. */ - sec = bfd_get_section_by_name (tmp_bfd, ".text"); - text_addr += bfd_section_vma (tmp_bfd, sec); - - /* Now find the true lowest section in the shared library. */ - sec = NULL; - bfd_map_over_sections (tmp_bfd, find_lowest_section, &sec); - - if (sec) - { - /* Subtract out the VMA of the lowest section. */ - text_addr -= bfd_section_vma (tmp_bfd, sec); - - /* ??? Add back in the filepos of that lowest section. */ - text_addr += sec->filepos; - } - - section_addrs = alloc_section_addr_info (bfd_count_sections (tmp_bfd)); - my_cleanups = make_cleanup (xfree, section_addrs); - - /* We are done with the temporary bfd. Get rid of it and make sure - nobody else can us it. */ - bfd_close (tmp_bfd); - tmp_bfd = NULL; - - /* Now let the generic code load up symbols for this library. */ - section_addrs->other[0].addr = text_addr; - section_addrs->other[0].name = ".text"; - so->objfile = symbol_file_add (name, from_tty, section_addrs, 0, OBJF_SHARED); - so->abfd = so->objfile->obfd; - - /* Mark this as a shared library and save private data. */ - so->objfile->flags |= OBJF_SHARED; - - obj_private = (struct hppa_objfile_private *) - objfile_data (so->objfile, hppa_objfile_priv_data); - if (obj_private == NULL) - { - obj_private = (struct hppa_objfile_private *) - obstack_alloc (&so->objfile->objfile_obstack, - sizeof (struct hppa_objfile_private)); - set_objfile_data (so->objfile, hppa_objfile_priv_data, obj_private); - obj_private->unwind_info = NULL; - obj_private->so_info = NULL; - } - - obj_private->so_info = so; - obj_private->dp = so->pa64_solib_desc.linkage_ptr; - do_cleanups (my_cleanups); -} - -/* Load debugging information for a shared library. TARGET may be - NULL if we are not attaching to a process or reading a core file. */ - -static void -pa64_solib_load_symbols (struct so_list *so, char *name, int from_tty, - CORE_ADDR text_addr, struct target_ops *target) -{ - struct section_table *p; - asection *sec; - int status; - char buf[4]; - CORE_ADDR presumed_data_start; - - if (text_addr == 0) - text_addr = so->pa64_solib_desc.text_base; - - pa64_solib_add_solib_objfile (so, name, from_tty, text_addr); - - /* Now we need to build a section table for this library since - we might be debugging a core file from a dynamically linked - executable in which the libraries were not privately mapped. */ - if (build_section_table (so->abfd, - &so->sections, - &so->sections_end)) - { - error (_("Unable to build section table for shared library\n.")); - return; - } - - (so->objfile->section_offsets)->offsets[SECT_OFF_TEXT (so->objfile)] - = so->pa64_solib_desc.text_base; - (so->objfile->section_offsets)->offsets[SECT_OFF_DATA (so->objfile)] - = so->pa64_solib_desc.data_base; - - /* Relocate all the sections based on where they got loaded. */ - for (p = so->sections; p < so->sections_end; p++) - { - if (p->the_bfd_section->flags & SEC_CODE) - { - p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile)); - p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile)); - } - else if (p->the_bfd_section->flags & SEC_DATA) - { - p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile)); - p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile)); - } - } - - /* Now see if we need to map in the text and data for this shared - library (for example debugging a core file which does not use - private shared libraries.). - - Carefully peek at the first text address in the library. If the - read succeeds, then the libraries were privately mapped and were - included in the core dump file. - - If the peek failed, then the libraries were not privately mapped - and are not in the core file, we'll have to read them in ourselves. */ - status = target_read_memory (text_addr, buf, 4); - if (status != 0) - { - int new, old; - - new = so->sections_end - so->sections; - - old = target_resize_to_sections (target, new); - - /* Copy over the old data before it gets clobbered. */ - memcpy ((char *) (target->to_sections + old), - so->sections, - ((sizeof (struct section_table)) * new)); - } -} - - -/* Add symbols from shared libraries into the symtab list, unless the - size threshold specified by auto_solib_limit (in megabytes) would - be exceeded. */ - -void -pa64_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms) -{ - struct minimal_symbol *msymbol; - CORE_ADDR addr; - asection *shlib_info; - int status; - unsigned int dld_flags; - char buf[4], *re_err; - int threshold_warning_given = 0; - int dll_index; - struct load_module_desc dll_desc; - char *dll_path; - - /* First validate our arguments. */ - if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL) - { - error (_("Invalid regexp: %s"), re_err); - } - - /* If we're debugging a core file, or have attached to a running - process, then pa64_solib_create_inferior_hook will not have been - called. - - We need to first determine if we're dealing with a dynamically - linked executable. If not, then return without an error or warning. - - We also need to examine __dld_flags to determine if the shared - library list is valid and to determine if the libraries have been - privately mapped. */ - if (symfile_objfile == NULL) - return; - - /* First see if the objfile was dynamically linked. */ - shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic"); - if (!shlib_info) - return; - - /* It's got a .dynamic section, make sure it's not empty. */ - if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) - return; - - /* Read in the load map pointer if we have not done so already. */ - if (! dld_cache.have_read_dld_descriptor) - if (! read_dld_descriptor (target, readsyms)) - return; - - /* If the libraries were not mapped private, warn the user. */ - if ((dld_cache.dld_flags & DT_HP_DEBUG_PRIVATE) == 0) - warning (_("\ -The shared libraries were not privately mapped; setting a\n\ -breakpoint in a shared library will not work until you rerun the program.")); - - /* For each shaerd library, add it to the shared library list. */ - for (dll_index = 1; ; dll_index++) - { - /* Read in the load module descriptor. */ - if (dlgetmodinfo (dll_index, &dll_desc, sizeof (dll_desc), - pa64_target_read_memory, 0, dld_cache.load_map) - == 0) - return; - - /* Get the name of the shared library. */ - dll_path = (char *)dlgetname (&dll_desc, sizeof (dll_desc), - pa64_target_read_memory, - 0, dld_cache.load_map); - - if (!dll_path) - error (_("pa64_solib_add, unable to read shared library path.")); - - add_to_solist (from_tty, dll_path, readsyms, &dll_desc, 0, target); - } -} - - -/* This hook gets called just before the first instruction in the - inferior process is executed. - - This is our opportunity to set magic flags in the inferior so - that GDB can be notified when a shared library is mapped in and - to tell the dynamic linker that a private copy of the library is - needed (so GDB can set breakpoints in the library). - - We need to set two flag bits in this routine. - - DT_HP_DEBUG_PRIVATE to indicate that shared libraries should be - mapped private. - - DT_HP_DEBUG_CALLBACK to indicate that we want the dynamic linker - to call the breakpoint routine for significant events. */ - -void -pa64_solib_create_inferior_hook (void) -{ - struct minimal_symbol *msymbol; - unsigned int dld_flags, status; - asection *shlib_info, *interp_sect; - char buf[4]; - struct objfile *objfile; - CORE_ADDR anaddr; - - /* First, remove all the solib event breakpoints. Their addresses - may have changed since the last time we ran the program. */ - remove_solib_event_breakpoints (); - - if (symfile_objfile == NULL) - return; - - /* First see if the objfile was dynamically linked. */ - shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic"); - if (!shlib_info) - return; - - /* It's got a .dynamic section, make sure it's not empty. */ - if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) - return; - - /* Read in the .dynamic section. */ - if (! read_dynamic_info (shlib_info, &dld_cache)) - error (_("Unable to read the .dynamic section.")); - - /* Turn on the flags we care about. */ - dld_cache.dld_flags |= DT_HP_DEBUG_PRIVATE; - dld_cache.dld_flags |= DT_HP_DEBUG_CALLBACK; - status = target_write_memory (dld_cache.dld_flags_addr, - (char *) &dld_cache.dld_flags, - sizeof (dld_cache.dld_flags)); - if (status != 0) - error (_("Unable to modify dynamic linker flags.")); - - /* Now we have to create a shared library breakpoint in the dynamic - linker. This can be somewhat tricky since the symbol is inside - the dynamic linker (for which we do not have symbols or a base - load address! Luckily I wrote this code for solib.c years ago. */ - interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); - if (interp_sect) - { - unsigned int interp_sect_size; - char *buf; - CORE_ADDR load_addr; - bfd *tmp_bfd; - CORE_ADDR sym_addr = 0; - - /* Read the contents of the .interp section into a local buffer; - the contents specify the dynamic linker this program uses. */ - interp_sect_size = bfd_section_size (exec_bfd, interp_sect); - buf = alloca (interp_sect_size); - bfd_get_section_contents (exec_bfd, interp_sect, - buf, 0, interp_sect_size); - - /* Now we need to figure out where the dynamic linker was - loaded so that we can load its symbols and place a breakpoint - in the dynamic linker itself. - - This address is stored on the stack. However, I've been unable - to find any magic formula to find it for Solaris (appears to - be trivial on GNU/Linux). Therefore, we have to try an alternate - mechanism to find the dynamic linker's base address. */ - tmp_bfd = bfd_openr (buf, gnutarget); - if (tmp_bfd == NULL) - goto get_out; - - /* 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); - bfd_close (tmp_bfd); - goto get_out; - } - - /* We find the dynamic linker's base address by examining the - current pc (which point at the entry point for the dynamic - linker) and subtracting the offset of the entry point. - - Also note the breakpoint is the second instruction in the - routine. */ - load_addr = read_pc () - tmp_bfd->start_address; - sym_addr = bfd_lookup_symbol (tmp_bfd, "__dld_break"); - sym_addr = load_addr + sym_addr + 4; - - /* Create the shared library breakpoint. */ - { - struct breakpoint *b - = create_solib_event_breakpoint (sym_addr); - - /* The breakpoint is actually hard-coded into the dynamic linker, - so we don't need to actually insert a breakpoint instruction - there. In fact, the dynamic linker's code is immutable, even to - ttrace, so we shouldn't even try to do that. For cases like - this, we have "permanent" breakpoints. */ - make_breakpoint_permanent (b); - } - - /* We're done with the temporary bfd. */ - bfd_close (tmp_bfd); - } - -get_out: - /* Wipe out all knowledge of old shared libraries since their - mapping can change from one exec to another! */ - while (so_list_head) - { - struct so_list *temp; - - temp = so_list_head; - xfree (so_list_head); - so_list_head = temp->next; - } - clear_symtab_users (); -} - -/* This operation removes the "hook" between GDB and the dynamic linker, - which causes the dld to notify GDB of shared library events. - - After this operation completes, the dld will no longer notify GDB of - shared library events. To resume notifications, GDB must call - pa64_solib_create_inferior_hook. - - This operation does not remove any knowledge of shared libraries - of which GDB may already have been notified. */ - -void -pa64_solib_remove_inferior_hook (int pid) -{ - /* Turn off the DT_HP_DEBUG_CALLBACK bit in the dynamic linker flags. */ - dld_cache.dld_flags &= ~DT_HP_DEBUG_CALLBACK; - target_write_memory (dld_cache.dld_flags_addr, - (char *)&dld_cache.dld_flags, - sizeof (dld_cache.dld_flags)); -} - -/* This function creates a breakpoint on the dynamic linker hook, which - is called when e.g., a shl_load or shl_unload call is made. This - breakpoint will only trigger when a shl_load call is made. - - If filename is NULL, then loads of any dll will be caught. Else, - only loads of the file whose pathname is the string contained by - filename will be caught. - - Undefined behaviour is guaranteed if this function is called before - pa64_solib_create_inferior_hook. */ - -void -pa64_solib_create_catch_load_hook (int pid, int tempflag, char *filename, - char *cond_string) -{ - create_solib_load_event_breakpoint ("", tempflag, filename, cond_string); -} - -/* This function creates a breakpoint on the dynamic linker hook, which - is called when e.g., a shl_load or shl_unload call is made. This - breakpoint will only trigger when a shl_unload call is made. - - If filename is NULL, then unloads of any dll will be caught. Else, - only unloads of the file whose pathname is the string contained by - filename will be caught. - - Undefined behaviour is guaranteed if this function is called before - pa64_solib_create_inferior_hook. */ - -void -pa64_solib_create_catch_unload_hook (int pid, int tempflag, char *filename, - char *cond_string) -{ - create_solib_unload_event_breakpoint ("", tempflag, filename, cond_string); -} - -/* Return nonzero if the dynamic linker has reproted that a library - has been loaded. */ - -int -pa64_solib_have_load_event (int pid) -{ - CORE_ADDR event_kind; - - event_kind = read_register (HPPA_ARG0_REGNUM); - return (event_kind == DLD_CB_LOAD); -} - -/* Return nonzero if the dynamic linker has reproted that a library - has been unloaded. */ -int -pa64_solib_have_unload_event (int pid) -{ - CORE_ADDR event_kind; - - event_kind = read_register (HPPA_ARG0_REGNUM); - return (event_kind == DLD_CB_UNLOAD); -} - -/* Return a pointer to a string indicating the pathname of the most - recently loaded library. - - The caller is reposible for copying the string before the inferior is - restarted. */ - -char * -pa64_solib_loaded_library_pathname (int pid) -{ - static char dll_path[MAXPATHLEN]; - CORE_ADDR dll_path_addr = read_register (HPPA_ARG3_REGNUM); - read_memory_string (dll_path_addr, dll_path, MAXPATHLEN); - return dll_path; -} - -/* Return a pointer to a string indicating the pathname of the most - recently unloaded library. - - The caller is reposible for copying the string before the inferior is - restarted. */ - -char * -pa64_solib_unloaded_library_pathname (int pid) -{ - static char dll_path[MAXPATHLEN]; - CORE_ADDR dll_path_addr = read_register (HPPA_ARG3_REGNUM); - read_memory_string (dll_path_addr, dll_path, MAXPATHLEN); - return dll_path; -} - -/* Return nonzero if PC is an address inside the dynamic linker. */ - -int -pa64_solib_in_dynamic_linker (int pid, CORE_ADDR pc) -{ - asection *shlib_info; - - if (symfile_objfile == NULL) - return 0; - - if (!dld_cache.have_read_dld_descriptor) - if (!read_dld_descriptor (¤t_target, auto_solib_add)) - return 0; - - return (pc >= dld_cache.dld_desc.text_base - && pc < dld_cache.dld_desc.text_base + dld_cache.dld_desc.text_size); -} - - -/* Return the GOT value for the shared library in which ADDR belongs. If - ADDR isn't in any known shared library, return zero. */ - -CORE_ADDR -pa64_solib_get_got_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = so_list_head; - CORE_ADDR got_value = 0; - - while (so_list) - { - if (so_list->pa64_solib_desc.text_base <= addr - && ((so_list->pa64_solib_desc.text_base - + so_list->pa64_solib_desc.text_size) - > addr)) - { - got_value = so_list->pa64_solib_desc.linkage_ptr; - break; - } - so_list = so_list->next; - } - return got_value; -} - -/* Return the address of the handle of the shared library in which ADDR - belongs. If ADDR isn't in any known shared library, return zero. - - This function is used in hppa_fix_call_dummy in hppa-tdep.c. */ - -CORE_ADDR -pa64_solib_get_solib_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = so_list_head; - CORE_ADDR retval = 0; - - while (so_list) - { - if (so_list->pa64_solib_desc.text_base <= addr - && ((so_list->pa64_solib_desc.text_base - + so_list->pa64_solib_desc.text_size) - > addr)) - { - retval = so_list->pa64_solib_desc_addr; - break; - } - so_list = so_list->next; - } - return retval; -} - -/* Dump information about all the currently loaded shared libraries. */ - -static void -pa64_sharedlibrary_info_command (char *ignore, int from_tty) -{ - struct so_list *so_list = so_list_head; - - if (exec_bfd == NULL) - { - printf_unfiltered ("No executable file.\n"); - return; - } - - if (so_list == NULL) - { - printf_unfiltered ("No shared libraries loaded at this time.\n"); - return; - } - - printf_unfiltered ("Shared Object Libraries\n"); - printf_unfiltered (" %-19s%-19s%-19s%-19s\n", - " text start", " text end", - " data start", " data end"); - while (so_list) - { - unsigned int flags; - - printf_unfiltered ("%s", so_list->name); - if (so_list->objfile == NULL) - printf_unfiltered (" (symbols not loaded)"); - if (so_list->loaded == 0) - printf_unfiltered (" (shared library unloaded)"); - printf_unfiltered (" %-18s", - hex_string_custom (so_list->pa64_solib_desc.linkage_ptr, 16)); - printf_unfiltered ("\n"); - printf_unfiltered ("%-18s", - hex_string_custom (so_list->pa64_solib_desc.text_base, 16)); - printf_unfiltered (" %-18s", - hex_string_custom ((so_list->pa64_solib_desc.text_base - + so_list->pa64_solib_desc.text_size), 16)); - printf_unfiltered (" %-18s", - hex_string_custom (so_list->pa64_solib_desc.data_base, 16)); - printf_unfiltered (" %-18s\n", - hex_string_custom ((so_list->pa64_solib_desc.data_base - + so_list->pa64_solib_desc.data_size), 16)); - so_list = so_list->next; - } -} - -/* Load up one or more shared libraries as directed by the user. */ - -static void -pa64_solib_sharedlibrary_command (char *args, int from_tty) -{ - dont_repeat (); - pa64_solib_add (args, from_tty, (struct target_ops *) 0, 1); -} - -/* Return the name of the shared library containing ADDR or NULL if ADDR - is not contained in any known shared library. */ - -char * -pa64_solib_address (CORE_ADDR addr) -{ - struct so_list *so = so_list_head; - - while (so) - { - /* Is this address within this shlib's text range? If so, - return the shlib's name. */ - if (addr >= so->pa64_solib_desc.text_base - && addr < (so->pa64_solib_desc.text_base - | so->pa64_solib_desc.text_size)) - return so->name; - - /* Nope, keep looking... */ - so = so->next; - } - - /* No, we couldn't prove that the address is within a shlib. */ - return NULL; -} - -/* We are killing the inferior and restarting the program. */ - -void -pa64_solib_restart (void) -{ - struct so_list *sl = so_list_head; - - /* Before the shlib info vanishes, use it to disable any breakpoints - that may still be active in those shlibs. */ - disable_breakpoints_in_shlibs (0); - - /* Discard all the shlib descriptors. */ - while (sl) - { - struct so_list *next_sl = sl->next; - xfree (sl); - sl = next_sl; - } - so_list_head = NULL; - - pa64_solib_total_st_size = (LONGEST) 0; - pa64_solib_st_size_threshold_exceeded = 0; - - dld_cache.is_valid = 0; - dld_cache.have_read_dld_descriptor = 0; - dld_cache.dld_flags_addr = 0; - dld_cache.load_map = 0; - dld_cache.load_map_addr = 0; - dld_cache.dld_desc.data_base = 0; - dld_cache.dld_flags = 0; - dld_cache.dyninfo_sect = 0; -} - -void -_initialize_pa64_solib (void) -{ - add_com ("sharedlibrary", class_files, pa64_solib_sharedlibrary_command, - _("Load shared object library symbols for files matching REGEXP.")); - add_info ("sharedlibrary", pa64_sharedlibrary_info_command, - _("Status of loaded shared object libraries.")); - - add_setshow_boolean_cmd ("auto-solib-add", class_support, - &auto_solib_add, _("\ -Set autoloading of shared library symbols."), _("\ -Show autoloading of shared library symbols."), _("\ -If \"on\", symbols from all shared object libraries will be loaded\n\ -automatically when the inferior begins execution, when the dynamic linker\n\ -informs gdb that a new library has been loaded, or when attaching to the\n\ -inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'."), - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_zinteger_cmd ("auto-solib-limit", class_support, - &auto_solib_limit, _("\ -Set threshold (in Mb) for autoloading shared library symbols."), _("\ -Show threshold (in Mb) for autoloading shared library symbols."), _("\ -When shared library autoloading is enabled, new libraries will be loaded\n\ -only until the total size of shared library symbols exceeds this\n\ -threshold in megabytes. Is ignored when using `sharedlibrary'."), - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how - much data space a process can use. We ought to be reading - MAXDSIZ and setting auto_solib_limit to some large fraction of - that value. If not that, we maybe ought to be setting it smaller - than the default for MAXDSIZ (that being 64Mb, I believe). - However, [1] this threshold is only crudely approximated rather - than actually measured, and [2] 50 Mbytes is too small for - debugging gdb itself. Thus, the arbitrary 100 figure. */ - auto_solib_limit = 100; /* Megabytes */ - - pa64_solib_restart (); -} - -/* Get some HPUX-specific data from a shared lib. */ -CORE_ADDR -pa64_solib_thread_start_addr (struct so_list *so) -{ - return so->pa64_solib_desc.tls_start_addr; -} - -/* Read the dynamic linker's internal shared library descriptor. - - This must happen after dld starts running, so we can't do it in - read_dynamic_info. Record the fact that we have loaded the - descriptor. If the library is archive bound, then return zero, else - return nonzero. */ - -static int -read_dld_descriptor (struct target_ops *target, int readsyms) -{ - char *dll_path; - asection *dyninfo_sect; - - /* If necessary call read_dynamic_info to extract the contents of the - .dynamic section from the shared library. */ - if (!dld_cache.is_valid) - { - if (symfile_objfile == NULL) - error (_("No object file symbols.")); - - dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd, - ".dynamic"); - if (!dyninfo_sect) - { - return 0; - } - - if (!read_dynamic_info (dyninfo_sect, &dld_cache)) - error (_("Unable to read in .dynamic section information.")); - } - - /* Read the load map pointer. */ - if (target_read_memory (dld_cache.load_map_addr, - (char*) &dld_cache.load_map, - sizeof(dld_cache.load_map)) - != 0) - { - error (_("Error while reading in load map pointer.")); - } - - /* Read in the dld load module descriptor */ - if (dlgetmodinfo (-1, - &dld_cache.dld_desc, - sizeof(dld_cache.dld_desc), - pa64_target_read_memory, - 0, - dld_cache.load_map) - == 0) - { - error (_("Error trying to get information about dynamic linker.")); - } - - /* Indicate that we have loaded the dld descriptor. */ - dld_cache.have_read_dld_descriptor = 1; - - /* Add dld.sl to the list of known shared libraries so that we can - do unwind, etc. - - ?!? This may not be correct. Consider of dld.sl contains symbols - which are also referenced/defined by the user program or some user - shared library. We need to make absolutely sure that we do not - pollute the namespace from GDB's point of view. */ - dll_path = dlgetname (&dld_cache.dld_desc, - sizeof(dld_cache.dld_desc), - pa64_target_read_memory, - 0, - dld_cache.load_map); - add_to_solist(0, dll_path, readsyms, &dld_cache.dld_desc, 0, target); - - return 1; -} - -/* Read the .dynamic section and extract the information of interest, - which is stored in dld_cache. The routine elf_locate_base in solib.c - was used as a model for this. */ - -static int -read_dynamic_info (asection *dyninfo_sect, dld_cache_t *dld_cache_p) -{ - char *buf; - char *bufend; - CORE_ADDR dyninfo_addr; - int dyninfo_sect_size; - CORE_ADDR entry_addr; - - /* Read in .dynamic section, silently ignore errors. */ - dyninfo_addr = bfd_section_vma (symfile_objfile->obfd, dyninfo_sect); - 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; - - /* Scan the .dynamic section and record the items of interest. - In particular, DT_HP_DLD_FLAGS */ - for (bufend = buf + dyninfo_sect_size, entry_addr = dyninfo_addr; - buf < bufend; - buf += sizeof (Elf64_Dyn), entry_addr += sizeof (Elf64_Dyn)) - { - Elf64_Dyn *x_dynp = (Elf64_Dyn*)buf; - Elf64_Sxword dyn_tag; - CORE_ADDR dyn_ptr; - char *pbuf; - - pbuf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT); - dyn_tag = bfd_h_get_64 (symfile_objfile->obfd, - (bfd_byte*) &x_dynp->d_tag); - - /* We can't use a switch here because dyn_tag is 64 bits and HP's - lame comiler does not handle 64bit items in switch statements. */ - if (dyn_tag == DT_NULL) - break; - else if (dyn_tag == DT_HP_DLD_FLAGS) - { - /* Set dld_flags_addr and dld_flags in *dld_cache_p */ - dld_cache_p->dld_flags_addr = entry_addr + offsetof(Elf64_Dyn, d_un); - if (target_read_memory (dld_cache_p->dld_flags_addr, - (char*) &dld_cache_p->dld_flags, - sizeof(dld_cache_p->dld_flags)) - != 0) - { - error (_("Error while reading in .dynamic section of the program.")); - } - } - else if (dyn_tag == DT_HP_LOAD_MAP) - { - /* Dld will place the address of the load map at load_map_addr - after it starts running. */ - if (target_read_memory (entry_addr + offsetof(Elf64_Dyn, - d_un.d_ptr), - (char*) &dld_cache_p->load_map_addr, - sizeof(dld_cache_p->load_map_addr)) - != 0) - { - error (_("Error while reading in .dynamic section of the program.")); - } - } - else - { - /* tag is not of interest */ - } - } - - /* Record other information and set is_valid to 1. */ - dld_cache_p->dyninfo_sect = dyninfo_sect; - - /* Verify that we read in required info. These fields are re-set to zero - in pa64_solib_restart. */ - - if (dld_cache_p->dld_flags_addr != 0 && dld_cache_p->load_map_addr != 0) - dld_cache_p->is_valid = 1; - else - return 0; - - return 1; -} - -/* Wrapper for target_read_memory to make dlgetmodinfo happy. */ - -static void * -pa64_target_read_memory (void *buffer, CORE_ADDR ptr, size_t bufsiz, int ident) -{ - if (target_read_memory (ptr, buffer, bufsiz) != 0) - return 0; - return buffer; -} - -/* Called from handle_dynlink_load_event and pa64_solib_add to add - a shared library to so_list_head list and possibly to read in the - debug information for the library. - - If load_module_desc_p is NULL, then the load module descriptor must - be read from the inferior process at the address load_module_desc_addr. */ - -static void -add_to_solist (int from_tty, char *dll_path, int readsyms, - struct load_module_desc *load_module_desc_p, - CORE_ADDR load_module_desc_addr, struct target_ops *target) -{ - struct so_list *new_so, *so_list_tail; - int pa64_solib_st_size_threshhold_exceeded; - LONGEST st_size; - - if (symfile_objfile == NULL) - return; - - so_list_tail = so_list_head; - /* Find the end of the list of shared objects. */ - while (so_list_tail && so_list_tail->next) - { - if (strcmp (so_list_tail->name, dll_path) == 0) - return; - so_list_tail = so_list_tail->next; - } - - if (so_list_tail && strcmp (so_list_tail->name, dll_path) == 0) - return; - - /* Add the shared library to the so_list_head list */ - new_so = (struct so_list *) xmalloc (sizeof (struct so_list)); - memset ((char *)new_so, 0, sizeof (struct so_list)); - if (so_list_head == NULL) - { - so_list_head = new_so; - so_list_tail = new_so; - } - else - { - so_list_tail->next = new_so; - so_list_tail = new_so; - } - - /* Initialize the new_so */ - if (load_module_desc_p) - { - new_so->pa64_solib_desc = *load_module_desc_p; - } - else - { - if (target_read_memory (load_module_desc_addr, - (char*) &new_so->pa64_solib_desc, - sizeof(struct load_module_desc)) - != 0) - { - error (_("Error while reading in dynamic library %s"), dll_path); - } - } - - new_so->pa64_solib_desc_addr = load_module_desc_addr; - new_so->loaded = 1; - new_so->name = obsavestring (dll_path, strlen(dll_path), - &symfile_objfile->objfile_obstack); - - /* If we are not going to load the library, tell the user if we - haven't already and return. */ - - st_size = pa64_solib_sizeof_symbol_table (dll_path); - pa64_solib_st_size_threshhold_exceeded = - !from_tty - && readsyms - && ( (st_size + pa64_solib_total_st_size) - > (auto_solib_limit * (LONGEST) (1024 * 1024))); - if (pa64_solib_st_size_threshhold_exceeded) - { - pa64_solib_add_solib_objfile (new_so, dll_path, from_tty, 1); - return; - } - - /* Now read in debug info. */ - pa64_solib_total_st_size += st_size; - - /* This fills in new_so->objfile, among others. */ - pa64_solib_load_symbols (new_so, - dll_path, - from_tty, - 0, - target); - return; -} - - -/* - LOCAL FUNCTION - - bfd_lookup_symbol -- lookup the value for a specific symbol - - SYNOPSIS - - 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. - - Note that 0 is specifically allowed as an error return (no - such symbol). - */ - -static CORE_ADDR -bfd_lookup_symbol (bfd *abfd, char *symname) -{ - unsigned int storage_needed; - asymbol *sym; - asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; - struct cleanup *back_to; - CORE_ADDR symaddr = 0; - - storage_needed = bfd_get_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (xfree, symbol_table); - number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - if (strcmp (sym->name, symname) == 0) - { - /* Bfd symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - return (symaddr); -} - |