1130803Smarcel/* Handle HP ELF shared libraries for GDB, the GNU Debugger. 2130803Smarcel 3130803Smarcel Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, 4130803Smarcel Inc. 5130803Smarcel 6130803Smarcel This file is part of GDB. 7130803Smarcel 8130803Smarcel This program is free software; you can redistribute it and/or modify 9130803Smarcel it under the terms of the GNU General Public License as published by 10130803Smarcel the Free Software Foundation; either version 2 of the License, or 11130803Smarcel (at your option) any later version. 12130803Smarcel 13130803Smarcel This program is distributed in the hope that it will be useful, 14130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 15130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130803Smarcel GNU General Public License for more details. 17130803Smarcel 18130803Smarcel You should have received a copy of the GNU General Public License 19130803Smarcel along with this program; if not, write to the Free Software 20130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 21130803Smarcel Boston, MA 02111-1307, USA. 22130803Smarcel 23130803Smarcel HP in their infinite stupidity choose not to use standard ELF dynamic 24130803Smarcel linker interfaces. They also choose not to make their ELF dymamic 25130803Smarcel linker interfaces compatible with the SOM dynamic linker. The 26130803Smarcel net result is we can not use either of the existing somsolib.c or 27130803Smarcel solib.c. What a crock. 28130803Smarcel 29130803Smarcel Even more disgusting. This file depends on functions provided only 30130803Smarcel in certain PA64 libraries. Thus this file is supposed to only be 31130803Smarcel used native. When will HP ever learn that they need to provide the 32130803Smarcel same functionality in all their libraries! */ 33130803Smarcel 34130803Smarcel#include <dlfcn.h> 35130803Smarcel#include <elf.h> 36130803Smarcel#include <elf_hp.h> 37130803Smarcel 38130803Smarcel#include "defs.h" 39130803Smarcel 40130803Smarcel#include "frame.h" 41130803Smarcel#include "bfd.h" 42130803Smarcel#include "libhppa.h" 43130803Smarcel#include "gdbcore.h" 44130803Smarcel#include "symtab.h" 45130803Smarcel#include "breakpoint.h" 46130803Smarcel#include "symfile.h" 47130803Smarcel#include "objfiles.h" 48130803Smarcel#include "inferior.h" 49130803Smarcel#include "gdb-stabs.h" 50130803Smarcel#include "gdb_stat.h" 51130803Smarcel#include "gdbcmd.h" 52130803Smarcel#include "language.h" 53130803Smarcel#include "regcache.h" 54130803Smarcel#include "exec.h" 55130803Smarcel 56130803Smarcel#include <fcntl.h> 57130803Smarcel 58130803Smarcel#ifndef O_BINARY 59130803Smarcel#define O_BINARY 0 60130803Smarcel#endif 61130803Smarcel 62130803Smarcelstatic CORE_ADDR bfd_lookup_symbol (bfd *, char *); 63130803Smarcel/* This lives in hppa-tdep.c. */ 64130803Smarcelextern struct unwind_table_entry *find_unwind_entry (CORE_ADDR pc); 65130803Smarcel 66130803Smarcel/* These ought to be defined in some public interface, but aren't. They 67130803Smarcel identify dynamic linker events. */ 68130803Smarcel#define DLD_CB_LOAD 1 69130803Smarcel#define DLD_CB_UNLOAD 0 70130803Smarcel 71130803Smarcel/* A structure to keep track of all the known shared objects. */ 72130803Smarcelstruct so_list 73130803Smarcel { 74130803Smarcel bfd *abfd; 75130803Smarcel char *name; 76130803Smarcel struct so_list *next; 77130803Smarcel struct objfile *objfile; 78130803Smarcel CORE_ADDR pa64_solib_desc_addr; 79130803Smarcel struct load_module_desc pa64_solib_desc; 80130803Smarcel struct section_table *sections; 81130803Smarcel struct section_table *sections_end; 82130803Smarcel int loaded; 83130803Smarcel }; 84130803Smarcel 85130803Smarcelstatic struct so_list *so_list_head; 86130803Smarcel 87130803Smarcel/* This is the cumulative size in bytes of the symbol tables of all 88130803Smarcel shared objects on the so_list_head list. (When we say size, here 89130803Smarcel we mean of the information before it is brought into memory and 90130803Smarcel potentially expanded by GDB.) When adding a new shlib, this value 91130803Smarcel is compared against a threshold size, held by auto_solib_limit (in 92130803Smarcel megabytes). If adding symbols for the new shlib would cause the 93130803Smarcel total size to exceed the threshold, then the new shlib's symbols 94130803Smarcel are not loaded. */ 95130803Smarcelstatic LONGEST pa64_solib_total_st_size; 96130803Smarcel 97130803Smarcel/* When the threshold is reached for any shlib, we refuse to add 98130803Smarcel symbols for subsequent shlibs, even if those shlibs' symbols would 99130803Smarcel be small enough to fit under the threshold. Although this may 100130803Smarcel result in one, early large shlib preventing the loading of later, 101130803Smarcel smaller shlibs' symbols, it allows us to issue one informational 102130803Smarcel message. The alternative, to issue a message for each shlib whose 103130803Smarcel symbols aren't loaded, could be a big annoyance where the threshold 104130803Smarcel is exceeded due to a very large number of shlibs. */ 105130803Smarcelstatic int pa64_solib_st_size_threshold_exceeded; 106130803Smarcel 107130803Smarcel/* When adding fields, be sure to clear them in _initialize_pa64_solib. */ 108130803Smarceltypedef struct 109130803Smarcel { 110130803Smarcel CORE_ADDR dld_flags_addr; 111130803Smarcel LONGEST dld_flags; 112130803Smarcel struct bfd_section *dyninfo_sect; 113130803Smarcel int have_read_dld_descriptor; 114130803Smarcel int is_valid; 115130803Smarcel CORE_ADDR load_map; 116130803Smarcel CORE_ADDR load_map_addr; 117130803Smarcel struct load_module_desc dld_desc; 118130803Smarcel } 119130803Smarceldld_cache_t; 120130803Smarcel 121130803Smarcelstatic dld_cache_t dld_cache; 122130803Smarcel 123130803Smarcelstatic void pa64_sharedlibrary_info_command (char *, int); 124130803Smarcel 125130803Smarcelstatic void pa64_solib_sharedlibrary_command (char *, int); 126130803Smarcel 127130803Smarcelstatic void *pa64_target_read_memory (void *, CORE_ADDR, size_t, int); 128130803Smarcel 129130803Smarcelstatic int read_dld_descriptor (struct target_ops *, int readsyms); 130130803Smarcel 131130803Smarcelstatic int read_dynamic_info (asection *, dld_cache_t *); 132130803Smarcel 133130803Smarcelstatic void add_to_solist (int, char *, int, struct load_module_desc *, 134130803Smarcel CORE_ADDR, struct target_ops *); 135130803Smarcel 136130803Smarcel/* When examining the shared library for debugging information we have to 137130803Smarcel look for HP debug symbols, stabs and dwarf2 debug symbols. */ 138130803Smarcelstatic char *pa64_debug_section_names[] = { 139130803Smarcel ".debug_header", ".debug_gntt", ".debug_lntt", ".debug_slt", ".debug_vt", 140130803Smarcel ".stabs", ".stabstr", ".debug_info", ".debug_abbrev", ".debug_aranges", 141130803Smarcel ".debug_macinfo", ".debug_line", ".debug_loc", ".debug_pubnames", 142130803Smarcel ".debug_str", NULL 143130803Smarcel}; 144130803Smarcel 145130803Smarcel/* Return a ballbark figure for the amount of memory GDB will need to 146130803Smarcel allocate to read in the debug symbols from FILENAME. */ 147130803Smarcelstatic LONGEST 148130803Smarcelpa64_solib_sizeof_symbol_table (char *filename) 149130803Smarcel{ 150130803Smarcel bfd *abfd; 151130803Smarcel int i; 152130803Smarcel int desc; 153130803Smarcel char *absolute_name; 154130803Smarcel LONGEST st_size = (LONGEST) 0; 155130803Smarcel asection *sect; 156130803Smarcel 157130803Smarcel /* We believe that filename was handed to us by the dynamic linker, and 158130803Smarcel is therefore always an absolute path. */ 159130803Smarcel desc = openp (getenv ("PATH"), 1, filename, O_RDONLY | O_BINARY, 160130803Smarcel 0, &absolute_name); 161130803Smarcel if (desc < 0) 162130803Smarcel { 163130803Smarcel perror_with_name (filename); 164130803Smarcel } 165130803Smarcel filename = absolute_name; 166130803Smarcel 167130803Smarcel abfd = bfd_fdopenr (filename, gnutarget, desc); 168130803Smarcel if (!abfd) 169130803Smarcel { 170130803Smarcel close (desc); 171130803Smarcel make_cleanup (xfree, filename); 172130803Smarcel error ("\"%s\": can't open to read symbols: %s.", filename, 173130803Smarcel bfd_errmsg (bfd_get_error ())); 174130803Smarcel } 175130803Smarcel 176130803Smarcel if (!bfd_check_format (abfd, bfd_object)) 177130803Smarcel { 178130803Smarcel bfd_close (abfd); 179130803Smarcel make_cleanup (xfree, filename); 180130803Smarcel error ("\"%s\": can't read symbols: %s.", filename, 181130803Smarcel bfd_errmsg (bfd_get_error ())); 182130803Smarcel } 183130803Smarcel 184130803Smarcel /* Sum the sizes of the various sections that compose debug info. */ 185130803Smarcel for (i = 0; pa64_debug_section_names[i] != NULL; i++) 186130803Smarcel { 187130803Smarcel asection *sect; 188130803Smarcel 189130803Smarcel sect = bfd_get_section_by_name (abfd, pa64_debug_section_names[i]); 190130803Smarcel if (sect) 191130803Smarcel st_size += (LONGEST)bfd_section_size (abfd, sect); 192130803Smarcel } 193130803Smarcel 194130803Smarcel bfd_close (abfd); 195130803Smarcel xfree (filename); 196130803Smarcel 197130803Smarcel /* Unfortunately, just summing the sizes of various debug info 198130803Smarcel sections isn't a very accurate measurement of how much heap 199130803Smarcel space the debugger will need to hold them. It also doesn't 200130803Smarcel account for space needed by linker (aka "minimal") symbols. 201130803Smarcel 202130803Smarcel Anecdotal evidence suggests that just summing the sizes of 203130803Smarcel debug-info-related sections understates the heap space needed 204130803Smarcel to represent it internally by about an order of magnitude. 205130803Smarcel 206130803Smarcel Since it's not exactly brain surgery we're doing here, rather 207130803Smarcel than attempt to more accurately measure the size of a shlib's 208130803Smarcel symbol table in GDB's heap, we'll just apply a 10x fudge- 209130803Smarcel factor to the debug info sections' size-sum. No, this doesn't 210130803Smarcel account for minimal symbols in non-debuggable shlibs. But it 211130803Smarcel all roughly washes out in the end. */ 212130803Smarcel return st_size * (LONGEST) 10; 213130803Smarcel} 214130803Smarcel 215130803Smarcel/* Add a shared library to the objfile list and load its symbols into 216130803Smarcel GDB's symbol table. */ 217130803Smarcelstatic void 218130803Smarcelpa64_solib_add_solib_objfile (struct so_list *so, char *name, int from_tty, 219130803Smarcel CORE_ADDR text_addr) 220130803Smarcel{ 221130803Smarcel bfd *tmp_bfd; 222130803Smarcel asection *sec; 223130803Smarcel obj_private_data_t *obj_private; 224130803Smarcel struct section_addr_info *section_addrs; 225130803Smarcel struct cleanup *my_cleanups; 226130803Smarcel 227130803Smarcel /* We need the BFD so that we can look at its sections. We open up the 228130803Smarcel file temporarily, then close it when we are done. */ 229130803Smarcel tmp_bfd = bfd_openr (name, gnutarget); 230130803Smarcel if (tmp_bfd == NULL) 231130803Smarcel { 232130803Smarcel perror_with_name (name); 233130803Smarcel return; 234130803Smarcel } 235130803Smarcel 236130803Smarcel if (!bfd_check_format (tmp_bfd, bfd_object)) 237130803Smarcel { 238130803Smarcel bfd_close (tmp_bfd); 239130803Smarcel error ("\"%s\" is not an object file: %s", name, 240130803Smarcel bfd_errmsg (bfd_get_error ())); 241130803Smarcel } 242130803Smarcel 243130803Smarcel 244130803Smarcel /* Undo some braindamage from symfile.c. 245130803Smarcel 246130803Smarcel First, symfile.c will subtract the VMA of the first .text section 247130803Smarcel in the shared library that it finds. Undo that. */ 248130803Smarcel sec = bfd_get_section_by_name (tmp_bfd, ".text"); 249130803Smarcel text_addr += bfd_section_vma (tmp_bfd, sec); 250130803Smarcel 251130803Smarcel /* Now find the true lowest section in the shared library. */ 252130803Smarcel sec = NULL; 253130803Smarcel bfd_map_over_sections (tmp_bfd, find_lowest_section, &sec); 254130803Smarcel 255130803Smarcel if (sec) 256130803Smarcel { 257130803Smarcel /* Subtract out the VMA of the lowest section. */ 258130803Smarcel text_addr -= bfd_section_vma (tmp_bfd, sec); 259130803Smarcel 260130803Smarcel /* ??? Add back in the filepos of that lowest section. */ 261130803Smarcel text_addr += sec->filepos; 262130803Smarcel } 263130803Smarcel 264130803Smarcel section_addrs = alloc_section_addr_info (bfd_count_sections (tmp_bfd)); 265130803Smarcel my_cleanups = make_cleanup (xfree, section_addrs); 266130803Smarcel 267130803Smarcel /* We are done with the temporary bfd. Get rid of it and make sure 268130803Smarcel nobody else can us it. */ 269130803Smarcel bfd_close (tmp_bfd); 270130803Smarcel tmp_bfd = NULL; 271130803Smarcel 272130803Smarcel /* Now let the generic code load up symbols for this library. */ 273130803Smarcel section_addrs->other[0].addr = text_addr; 274130803Smarcel section_addrs->other[0].name = ".text"; 275130803Smarcel so->objfile = symbol_file_add (name, from_tty, section_addrs, 0, OBJF_SHARED); 276130803Smarcel so->abfd = so->objfile->obfd; 277130803Smarcel 278130803Smarcel /* Mark this as a shared library and save private data. */ 279130803Smarcel so->objfile->flags |= OBJF_SHARED; 280130803Smarcel 281130803Smarcel if (so->objfile->obj_private == NULL) 282130803Smarcel { 283130803Smarcel obj_private = (obj_private_data_t *) 284130803Smarcel obstack_alloc (&so->objfile->objfile_obstack, 285130803Smarcel sizeof (obj_private_data_t)); 286130803Smarcel obj_private->unwind_info = NULL; 287130803Smarcel obj_private->so_info = NULL; 288130803Smarcel so->objfile->obj_private = obj_private; 289130803Smarcel } 290130803Smarcel 291130803Smarcel obj_private = (obj_private_data_t *) so->objfile->obj_private; 292130803Smarcel obj_private->so_info = so; 293130803Smarcel obj_private->dp = so->pa64_solib_desc.linkage_ptr; 294130803Smarcel do_cleanups (my_cleanups); 295130803Smarcel} 296130803Smarcel 297130803Smarcel/* Load debugging information for a shared library. TARGET may be 298130803Smarcel NULL if we are not attaching to a process or reading a core file. */ 299130803Smarcel 300130803Smarcelstatic void 301130803Smarcelpa64_solib_load_symbols (struct so_list *so, char *name, int from_tty, 302130803Smarcel CORE_ADDR text_addr, struct target_ops *target) 303130803Smarcel{ 304130803Smarcel struct section_table *p; 305130803Smarcel asection *sec; 306130803Smarcel int status; 307130803Smarcel char buf[4]; 308130803Smarcel CORE_ADDR presumed_data_start; 309130803Smarcel 310130803Smarcel if (text_addr == 0) 311130803Smarcel text_addr = so->pa64_solib_desc.text_base; 312130803Smarcel 313130803Smarcel pa64_solib_add_solib_objfile (so, name, from_tty, text_addr); 314130803Smarcel 315130803Smarcel /* Now we need to build a section table for this library since 316130803Smarcel we might be debugging a core file from a dynamically linked 317130803Smarcel executable in which the libraries were not privately mapped. */ 318130803Smarcel if (build_section_table (so->abfd, 319130803Smarcel &so->sections, 320130803Smarcel &so->sections_end)) 321130803Smarcel { 322130803Smarcel error ("Unable to build section table for shared library\n."); 323130803Smarcel return; 324130803Smarcel } 325130803Smarcel 326130803Smarcel (so->objfile->section_offsets)->offsets[SECT_OFF_TEXT (so->objfile)] 327130803Smarcel = so->pa64_solib_desc.text_base; 328130803Smarcel (so->objfile->section_offsets)->offsets[SECT_OFF_DATA (so->objfile)] 329130803Smarcel = so->pa64_solib_desc.data_base; 330130803Smarcel 331130803Smarcel /* Relocate all the sections based on where they got loaded. */ 332130803Smarcel for (p = so->sections; p < so->sections_end; p++) 333130803Smarcel { 334130803Smarcel if (p->the_bfd_section->flags & SEC_CODE) 335130803Smarcel { 336130803Smarcel p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile)); 337130803Smarcel p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile)); 338130803Smarcel } 339130803Smarcel else if (p->the_bfd_section->flags & SEC_DATA) 340130803Smarcel { 341130803Smarcel p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile)); 342130803Smarcel p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile)); 343130803Smarcel } 344130803Smarcel } 345130803Smarcel 346130803Smarcel /* Now see if we need to map in the text and data for this shared 347130803Smarcel library (for example debugging a core file which does not use 348130803Smarcel private shared libraries.). 349130803Smarcel 350130803Smarcel Carefully peek at the first text address in the library. If the 351130803Smarcel read succeeds, then the libraries were privately mapped and were 352130803Smarcel included in the core dump file. 353130803Smarcel 354130803Smarcel If the peek failed, then the libraries were not privately mapped 355130803Smarcel and are not in the core file, we'll have to read them in ourselves. */ 356130803Smarcel status = target_read_memory (text_addr, buf, 4); 357130803Smarcel if (status != 0) 358130803Smarcel { 359130803Smarcel int new, old; 360130803Smarcel 361130803Smarcel new = so->sections_end - so->sections; 362130803Smarcel 363130803Smarcel old = target_resize_to_sections (target, new); 364130803Smarcel 365130803Smarcel /* Copy over the old data before it gets clobbered. */ 366130803Smarcel memcpy ((char *) (target->to_sections + old), 367130803Smarcel so->sections, 368130803Smarcel ((sizeof (struct section_table)) * new)); 369130803Smarcel } 370130803Smarcel} 371130803Smarcel 372130803Smarcel 373130803Smarcel/* Add symbols from shared libraries into the symtab list, unless the 374130803Smarcel size threshold specified by auto_solib_limit (in megabytes) would 375130803Smarcel be exceeded. */ 376130803Smarcel 377130803Smarcelvoid 378130803Smarcelpa64_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms) 379130803Smarcel{ 380130803Smarcel struct minimal_symbol *msymbol; 381130803Smarcel CORE_ADDR addr; 382130803Smarcel asection *shlib_info; 383130803Smarcel int status; 384130803Smarcel unsigned int dld_flags; 385130803Smarcel char buf[4], *re_err; 386130803Smarcel int threshold_warning_given = 0; 387130803Smarcel int dll_index; 388130803Smarcel struct load_module_desc dll_desc; 389130803Smarcel char *dll_path; 390130803Smarcel 391130803Smarcel /* First validate our arguments. */ 392130803Smarcel if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL) 393130803Smarcel { 394130803Smarcel error ("Invalid regexp: %s", re_err); 395130803Smarcel } 396130803Smarcel 397130803Smarcel /* If we're debugging a core file, or have attached to a running 398130803Smarcel process, then pa64_solib_create_inferior_hook will not have been 399130803Smarcel called. 400130803Smarcel 401130803Smarcel We need to first determine if we're dealing with a dynamically 402130803Smarcel linked executable. If not, then return without an error or warning. 403130803Smarcel 404130803Smarcel We also need to examine __dld_flags to determine if the shared library 405130803Smarcel list is valid and to determine if the libraries have been privately 406130803Smarcel mapped. */ 407130803Smarcel if (symfile_objfile == NULL) 408130803Smarcel return; 409130803Smarcel 410130803Smarcel /* First see if the objfile was dynamically linked. */ 411130803Smarcel shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic"); 412130803Smarcel if (!shlib_info) 413130803Smarcel return; 414130803Smarcel 415130803Smarcel /* It's got a .dynamic section, make sure it's not empty. */ 416130803Smarcel if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) 417130803Smarcel return; 418130803Smarcel 419130803Smarcel /* Read in the load map pointer if we have not done so already. */ 420130803Smarcel if (! dld_cache.have_read_dld_descriptor) 421130803Smarcel if (! read_dld_descriptor (target, readsyms)) 422130803Smarcel return; 423130803Smarcel 424130803Smarcel /* If the libraries were not mapped private, warn the user. */ 425130803Smarcel if ((dld_cache.dld_flags & DT_HP_DEBUG_PRIVATE) == 0) 426130803Smarcel warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n"); 427130803Smarcel 428130803Smarcel /* For each shaerd library, add it to the shared library list. */ 429130803Smarcel for (dll_index = 1; ; dll_index++) 430130803Smarcel { 431130803Smarcel /* Read in the load module descriptor. */ 432130803Smarcel if (dlgetmodinfo (dll_index, &dll_desc, sizeof (dll_desc), 433130803Smarcel pa64_target_read_memory, 0, dld_cache.load_map) 434130803Smarcel == 0) 435130803Smarcel return; 436130803Smarcel 437130803Smarcel /* Get the name of the shared library. */ 438130803Smarcel dll_path = (char *)dlgetname (&dll_desc, sizeof (dll_desc), 439130803Smarcel pa64_target_read_memory, 440130803Smarcel 0, dld_cache.load_map); 441130803Smarcel 442130803Smarcel if (!dll_path) 443130803Smarcel error ("pa64_solib_add, unable to read shared library path."); 444130803Smarcel 445130803Smarcel add_to_solist (from_tty, dll_path, readsyms, &dll_desc, 0, target); 446130803Smarcel } 447130803Smarcel} 448130803Smarcel 449130803Smarcel 450130803Smarcel/* This hook gets called just before the first instruction in the 451130803Smarcel inferior process is executed. 452130803Smarcel 453130803Smarcel This is our opportunity to set magic flags in the inferior so 454130803Smarcel that GDB can be notified when a shared library is mapped in and 455130803Smarcel to tell the dynamic linker that a private copy of the library is 456130803Smarcel needed (so GDB can set breakpoints in the library). 457130803Smarcel 458130803Smarcel We need to set two flag bits in this routine. 459130803Smarcel 460130803Smarcel DT_HP_DEBUG_PRIVATE to indicate that shared libraries should be 461130803Smarcel mapped private. 462130803Smarcel 463130803Smarcel DT_HP_DEBUG_CALLBACK to indicate that we want the dynamic linker to 464130803Smarcel call the breakpoint routine for significant events. */ 465130803Smarcel 466130803Smarcelvoid 467130803Smarcelpa64_solib_create_inferior_hook (void) 468130803Smarcel{ 469130803Smarcel struct minimal_symbol *msymbol; 470130803Smarcel unsigned int dld_flags, status; 471130803Smarcel asection *shlib_info, *interp_sect; 472130803Smarcel char buf[4]; 473130803Smarcel struct objfile *objfile; 474130803Smarcel CORE_ADDR anaddr; 475130803Smarcel 476130803Smarcel /* First, remove all the solib event breakpoints. Their addresses 477130803Smarcel may have changed since the last time we ran the program. */ 478130803Smarcel remove_solib_event_breakpoints (); 479130803Smarcel 480130803Smarcel if (symfile_objfile == NULL) 481130803Smarcel return; 482130803Smarcel 483130803Smarcel /* First see if the objfile was dynamically linked. */ 484130803Smarcel shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic"); 485130803Smarcel if (!shlib_info) 486130803Smarcel return; 487130803Smarcel 488130803Smarcel /* It's got a .dynamic section, make sure it's not empty. */ 489130803Smarcel if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) 490130803Smarcel return; 491130803Smarcel 492130803Smarcel /* Read in the .dynamic section. */ 493130803Smarcel if (! read_dynamic_info (shlib_info, &dld_cache)) 494130803Smarcel error ("Unable to read the .dynamic section."); 495130803Smarcel 496130803Smarcel /* Turn on the flags we care about. */ 497130803Smarcel dld_cache.dld_flags |= DT_HP_DEBUG_PRIVATE; 498130803Smarcel dld_cache.dld_flags |= DT_HP_DEBUG_CALLBACK; 499130803Smarcel status = target_write_memory (dld_cache.dld_flags_addr, 500130803Smarcel (char *) &dld_cache.dld_flags, 501130803Smarcel sizeof (dld_cache.dld_flags)); 502130803Smarcel if (status != 0) 503130803Smarcel error ("Unable to modify dynamic linker flags."); 504130803Smarcel 505130803Smarcel /* Now we have to create a shared library breakpoint in the dynamic 506130803Smarcel linker. This can be somewhat tricky since the symbol is inside 507130803Smarcel the dynamic linker (for which we do not have symbols or a base 508130803Smarcel load address! Luckily I wrote this code for solib.c years ago. */ 509130803Smarcel interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); 510130803Smarcel if (interp_sect) 511130803Smarcel { 512130803Smarcel unsigned int interp_sect_size; 513130803Smarcel char *buf; 514130803Smarcel CORE_ADDR load_addr; 515130803Smarcel bfd *tmp_bfd; 516130803Smarcel CORE_ADDR sym_addr = 0; 517130803Smarcel 518130803Smarcel /* Read the contents of the .interp section into a local buffer; 519130803Smarcel the contents specify the dynamic linker this program uses. */ 520130803Smarcel interp_sect_size = bfd_section_size (exec_bfd, interp_sect); 521130803Smarcel buf = alloca (interp_sect_size); 522130803Smarcel bfd_get_section_contents (exec_bfd, interp_sect, 523130803Smarcel buf, 0, interp_sect_size); 524130803Smarcel 525130803Smarcel /* Now we need to figure out where the dynamic linker was 526130803Smarcel loaded so that we can load its symbols and place a breakpoint 527130803Smarcel in the dynamic linker itself. 528130803Smarcel 529130803Smarcel This address is stored on the stack. However, I've been unable 530130803Smarcel to find any magic formula to find it for Solaris (appears to 531130803Smarcel be trivial on GNU/Linux). Therefore, we have to try an alternate 532130803Smarcel mechanism to find the dynamic linker's base address. */ 533130803Smarcel tmp_bfd = bfd_openr (buf, gnutarget); 534130803Smarcel if (tmp_bfd == NULL) 535130803Smarcel goto get_out; 536130803Smarcel 537130803Smarcel /* Make sure the dynamic linker's really a useful object. */ 538130803Smarcel if (!bfd_check_format (tmp_bfd, bfd_object)) 539130803Smarcel { 540130803Smarcel warning ("Unable to grok dynamic linker %s as an object file", buf); 541130803Smarcel bfd_close (tmp_bfd); 542130803Smarcel goto get_out; 543130803Smarcel } 544130803Smarcel 545130803Smarcel /* We find the dynamic linker's base address by examining the 546130803Smarcel current pc (which point at the entry point for the dynamic 547130803Smarcel linker) and subtracting the offset of the entry point. 548130803Smarcel 549130803Smarcel Also note the breakpoint is the second instruction in the 550130803Smarcel routine. */ 551130803Smarcel load_addr = read_pc () - tmp_bfd->start_address; 552130803Smarcel sym_addr = bfd_lookup_symbol (tmp_bfd, "__dld_break"); 553130803Smarcel sym_addr = load_addr + sym_addr + 4; 554130803Smarcel 555130803Smarcel /* Create the shared library breakpoint. */ 556130803Smarcel { 557130803Smarcel struct breakpoint *b 558130803Smarcel = create_solib_event_breakpoint (sym_addr); 559130803Smarcel 560130803Smarcel /* The breakpoint is actually hard-coded into the dynamic linker, 561130803Smarcel so we don't need to actually insert a breakpoint instruction 562130803Smarcel there. In fact, the dynamic linker's code is immutable, even to 563130803Smarcel ttrace, so we shouldn't even try to do that. For cases like 564130803Smarcel this, we have "permanent" breakpoints. */ 565130803Smarcel make_breakpoint_permanent (b); 566130803Smarcel } 567130803Smarcel 568130803Smarcel /* We're done with the temporary bfd. */ 569130803Smarcel bfd_close (tmp_bfd); 570130803Smarcel } 571130803Smarcel 572130803Smarcelget_out: 573130803Smarcel /* Wipe out all knowledge of old shared libraries since their 574130803Smarcel mapping can change from one exec to another! */ 575130803Smarcel while (so_list_head) 576130803Smarcel { 577130803Smarcel struct so_list *temp; 578130803Smarcel 579130803Smarcel temp = so_list_head; 580130803Smarcel xfree (so_list_head); 581130803Smarcel so_list_head = temp->next; 582130803Smarcel } 583130803Smarcel clear_symtab_users (); 584130803Smarcel} 585130803Smarcel 586130803Smarcel/* This operation removes the "hook" between GDB and the dynamic linker, 587130803Smarcel which causes the dld to notify GDB of shared library events. 588130803Smarcel 589130803Smarcel After this operation completes, the dld will no longer notify GDB of 590130803Smarcel shared library events. To resume notifications, GDB must call 591130803Smarcel pa64_solib_create_inferior_hook. 592130803Smarcel 593130803Smarcel This operation does not remove any knowledge of shared libraries which 594130803Smarcel GDB may already have been notified of. */ 595130803Smarcel 596130803Smarcelvoid 597130803Smarcelpa64_solib_remove_inferior_hook (int pid) 598130803Smarcel{ 599130803Smarcel /* Turn off the DT_HP_DEBUG_CALLBACK bit in the dynamic linker flags. */ 600130803Smarcel dld_cache.dld_flags &= ~DT_HP_DEBUG_CALLBACK; 601130803Smarcel target_write_memory (dld_cache.dld_flags_addr, 602130803Smarcel (char *)&dld_cache.dld_flags, 603130803Smarcel sizeof (dld_cache.dld_flags)); 604130803Smarcel} 605130803Smarcel 606130803Smarcel/* This function creates a breakpoint on the dynamic linker hook, which 607130803Smarcel is called when e.g., a shl_load or shl_unload call is made. This 608130803Smarcel breakpoint will only trigger when a shl_load call is made. 609130803Smarcel 610130803Smarcel If filename is NULL, then loads of any dll will be caught. Else, 611130803Smarcel only loads of the file whose pathname is the string contained by 612130803Smarcel filename will be caught. 613130803Smarcel 614130803Smarcel Undefined behaviour is guaranteed if this function is called before 615130803Smarcel pa64_solib_create_inferior_hook. */ 616130803Smarcel 617130803Smarcelvoid 618130803Smarcelpa64_solib_create_catch_load_hook (int pid, int tempflag, char *filename, 619130803Smarcel char *cond_string) 620130803Smarcel{ 621130803Smarcel create_solib_load_event_breakpoint ("", tempflag, filename, cond_string); 622130803Smarcel} 623130803Smarcel 624130803Smarcel/* This function creates a breakpoint on the dynamic linker hook, which 625130803Smarcel is called when e.g., a shl_load or shl_unload call is made. This 626130803Smarcel breakpoint will only trigger when a shl_unload call is made. 627130803Smarcel 628130803Smarcel If filename is NULL, then unloads of any dll will be caught. Else, 629130803Smarcel only unloads of the file whose pathname is the string contained by 630130803Smarcel filename will be caught. 631130803Smarcel 632130803Smarcel Undefined behaviour is guaranteed if this function is called before 633130803Smarcel pa64_solib_create_inferior_hook. */ 634130803Smarcel 635130803Smarcelvoid 636130803Smarcelpa64_solib_create_catch_unload_hook (int pid, int tempflag, char *filename, 637130803Smarcel char *cond_string) 638130803Smarcel{ 639130803Smarcel create_solib_unload_event_breakpoint ("", tempflag, filename, cond_string); 640130803Smarcel} 641130803Smarcel 642130803Smarcel/* Return nonzero if the dynamic linker has reproted that a library 643130803Smarcel has been loaded. */ 644130803Smarcel 645130803Smarcelint 646130803Smarcelpa64_solib_have_load_event (int pid) 647130803Smarcel{ 648130803Smarcel CORE_ADDR event_kind; 649130803Smarcel 650130803Smarcel event_kind = read_register (ARG0_REGNUM); 651130803Smarcel return (event_kind == DLD_CB_LOAD); 652130803Smarcel} 653130803Smarcel 654130803Smarcel/* Return nonzero if the dynamic linker has reproted that a library 655130803Smarcel has been unloaded. */ 656130803Smarcelint 657130803Smarcelpa64_solib_have_unload_event (int pid) 658130803Smarcel{ 659130803Smarcel CORE_ADDR event_kind; 660130803Smarcel 661130803Smarcel event_kind = read_register (ARG0_REGNUM); 662130803Smarcel return (event_kind == DLD_CB_UNLOAD); 663130803Smarcel} 664130803Smarcel 665130803Smarcel/* Return a pointer to a string indicating the pathname of the most 666130803Smarcel recently loaded library. 667130803Smarcel 668130803Smarcel The caller is reposible for copying the string before the inferior is 669130803Smarcel restarted. */ 670130803Smarcel 671130803Smarcelchar * 672130803Smarcelpa64_solib_loaded_library_pathname (int pid) 673130803Smarcel{ 674130803Smarcel static char dll_path[MAXPATHLEN]; 675130803Smarcel CORE_ADDR dll_path_addr = read_register (ARG3_REGNUM); 676130803Smarcel read_memory_string (dll_path_addr, dll_path, MAXPATHLEN); 677130803Smarcel return dll_path; 678130803Smarcel} 679130803Smarcel 680130803Smarcel/* Return a pointer to a string indicating the pathname of the most 681130803Smarcel recently unloaded library. 682130803Smarcel 683130803Smarcel The caller is reposible for copying the string before the inferior is 684130803Smarcel restarted. */ 685130803Smarcel 686130803Smarcelchar * 687130803Smarcelpa64_solib_unloaded_library_pathname (int pid) 688130803Smarcel{ 689130803Smarcel static char dll_path[MAXPATHLEN]; 690130803Smarcel CORE_ADDR dll_path_addr = read_register (ARG3_REGNUM); 691130803Smarcel read_memory_string (dll_path_addr, dll_path, MAXPATHLEN); 692130803Smarcel return dll_path; 693130803Smarcel} 694130803Smarcel 695130803Smarcel/* Return nonzero if PC is an address inside the dynamic linker. */ 696130803Smarcel 697130803Smarcelint 698130803Smarcelpa64_solib_in_dynamic_linker (int pid, CORE_ADDR pc) 699130803Smarcel{ 700130803Smarcel asection *shlib_info; 701130803Smarcel 702130803Smarcel if (symfile_objfile == NULL) 703130803Smarcel return 0; 704130803Smarcel 705130803Smarcel if (!dld_cache.have_read_dld_descriptor) 706130803Smarcel if (!read_dld_descriptor (¤t_target, auto_solib_add)) 707130803Smarcel return 0; 708130803Smarcel 709130803Smarcel return (pc >= dld_cache.dld_desc.text_base 710130803Smarcel && pc < dld_cache.dld_desc.text_base + dld_cache.dld_desc.text_size); 711130803Smarcel} 712130803Smarcel 713130803Smarcel 714130803Smarcel/* Return the GOT value for the shared library in which ADDR belongs. If 715130803Smarcel ADDR isn't in any known shared library, return zero. */ 716130803Smarcel 717130803SmarcelCORE_ADDR 718130803Smarcelpa64_solib_get_got_by_pc (CORE_ADDR addr) 719130803Smarcel{ 720130803Smarcel struct so_list *so_list = so_list_head; 721130803Smarcel CORE_ADDR got_value = 0; 722130803Smarcel 723130803Smarcel while (so_list) 724130803Smarcel { 725130803Smarcel if (so_list->pa64_solib_desc.text_base <= addr 726130803Smarcel && ((so_list->pa64_solib_desc.text_base 727130803Smarcel + so_list->pa64_solib_desc.text_size) 728130803Smarcel > addr)) 729130803Smarcel { 730130803Smarcel got_value = so_list->pa64_solib_desc.linkage_ptr; 731130803Smarcel break; 732130803Smarcel } 733130803Smarcel so_list = so_list->next; 734130803Smarcel } 735130803Smarcel return got_value; 736130803Smarcel} 737130803Smarcel 738130803Smarcel/* Return the address of the handle of the shared library in which ADDR 739130803Smarcel belongs. If ADDR isn't in any known shared library, return zero. 740130803Smarcel 741130803Smarcel This function is used in hppa_fix_call_dummy in hppa-tdep.c. */ 742130803Smarcel 743130803SmarcelCORE_ADDR 744130803Smarcelpa64_solib_get_solib_by_pc (CORE_ADDR addr) 745130803Smarcel{ 746130803Smarcel struct so_list *so_list = so_list_head; 747130803Smarcel CORE_ADDR retval = 0; 748130803Smarcel 749130803Smarcel while (so_list) 750130803Smarcel { 751130803Smarcel if (so_list->pa64_solib_desc.text_base <= addr 752130803Smarcel && ((so_list->pa64_solib_desc.text_base 753130803Smarcel + so_list->pa64_solib_desc.text_size) 754130803Smarcel > addr)) 755130803Smarcel { 756130803Smarcel retval = so_list->pa64_solib_desc_addr; 757130803Smarcel break; 758130803Smarcel } 759130803Smarcel so_list = so_list->next; 760130803Smarcel } 761130803Smarcel return retval; 762130803Smarcel} 763130803Smarcel 764130803Smarcel/* Dump information about all the currently loaded shared libraries. */ 765130803Smarcel 766130803Smarcelstatic void 767130803Smarcelpa64_sharedlibrary_info_command (char *ignore, int from_tty) 768130803Smarcel{ 769130803Smarcel struct so_list *so_list = so_list_head; 770130803Smarcel 771130803Smarcel if (exec_bfd == NULL) 772130803Smarcel { 773130803Smarcel printf_unfiltered ("No executable file.\n"); 774130803Smarcel return; 775130803Smarcel } 776130803Smarcel 777130803Smarcel if (so_list == NULL) 778130803Smarcel { 779130803Smarcel printf_unfiltered ("No shared libraries loaded at this time.\n"); 780130803Smarcel return; 781130803Smarcel } 782130803Smarcel 783130803Smarcel printf_unfiltered ("Shared Object Libraries\n"); 784130803Smarcel printf_unfiltered (" %-19s%-19s%-19s%-19s\n", 785130803Smarcel " text start", " text end", 786130803Smarcel " data start", " data end"); 787130803Smarcel while (so_list) 788130803Smarcel { 789130803Smarcel unsigned int flags; 790130803Smarcel 791130803Smarcel printf_unfiltered ("%s", so_list->name); 792130803Smarcel if (so_list->objfile == NULL) 793130803Smarcel printf_unfiltered (" (symbols not loaded)"); 794130803Smarcel if (so_list->loaded == 0) 795130803Smarcel printf_unfiltered (" (shared library unloaded)"); 796130803Smarcel printf_unfiltered (" %-18s", 797130803Smarcel local_hex_string_custom (so_list->pa64_solib_desc.linkage_ptr, 798130803Smarcel "016l")); 799130803Smarcel printf_unfiltered ("\n"); 800130803Smarcel printf_unfiltered ("%-18s", 801130803Smarcel local_hex_string_custom (so_list->pa64_solib_desc.text_base, 802130803Smarcel "016l")); 803130803Smarcel printf_unfiltered (" %-18s", 804130803Smarcel local_hex_string_custom ((so_list->pa64_solib_desc.text_base 805130803Smarcel + so_list->pa64_solib_desc.text_size), 806130803Smarcel "016l")); 807130803Smarcel printf_unfiltered (" %-18s", 808130803Smarcel local_hex_string_custom (so_list->pa64_solib_desc.data_base, 809130803Smarcel "016l")); 810130803Smarcel printf_unfiltered (" %-18s\n", 811130803Smarcel local_hex_string_custom ((so_list->pa64_solib_desc.data_base 812130803Smarcel + so_list->pa64_solib_desc.data_size), 813130803Smarcel "016l")); 814130803Smarcel so_list = so_list->next; 815130803Smarcel } 816130803Smarcel} 817130803Smarcel 818130803Smarcel/* Load up one or more shared libraries as directed by the user. */ 819130803Smarcel 820130803Smarcelstatic void 821130803Smarcelpa64_solib_sharedlibrary_command (char *args, int from_tty) 822130803Smarcel{ 823130803Smarcel dont_repeat (); 824130803Smarcel pa64_solib_add (args, from_tty, (struct target_ops *) 0, 1); 825130803Smarcel} 826130803Smarcel 827130803Smarcel/* Return the name of the shared library containing ADDR or NULL if ADDR 828130803Smarcel is not contained in any known shared library. */ 829130803Smarcel 830130803Smarcelchar * 831130803Smarcelpa64_solib_address (CORE_ADDR addr) 832130803Smarcel{ 833130803Smarcel struct so_list *so = so_list_head; 834130803Smarcel 835130803Smarcel while (so) 836130803Smarcel { 837130803Smarcel /* Is this address within this shlib's text range? If so, 838130803Smarcel return the shlib's name. */ 839130803Smarcel if (addr >= so->pa64_solib_desc.text_base 840130803Smarcel && addr < (so->pa64_solib_desc.text_base 841130803Smarcel | so->pa64_solib_desc.text_size)) 842130803Smarcel return so->name; 843130803Smarcel 844130803Smarcel /* Nope, keep looking... */ 845130803Smarcel so = so->next; 846130803Smarcel } 847130803Smarcel 848130803Smarcel /* No, we couldn't prove that the address is within a shlib. */ 849130803Smarcel return NULL; 850130803Smarcel} 851130803Smarcel 852130803Smarcel/* We are killing the inferior and restarting the program. */ 853130803Smarcel 854130803Smarcelvoid 855130803Smarcelpa64_solib_restart (void) 856130803Smarcel{ 857130803Smarcel struct so_list *sl = so_list_head; 858130803Smarcel 859130803Smarcel /* Before the shlib info vanishes, use it to disable any breakpoints 860130803Smarcel that may still be active in those shlibs. */ 861130803Smarcel disable_breakpoints_in_shlibs (0); 862130803Smarcel 863130803Smarcel /* Discard all the shlib descriptors. */ 864130803Smarcel while (sl) 865130803Smarcel { 866130803Smarcel struct so_list *next_sl = sl->next; 867130803Smarcel xfree (sl); 868130803Smarcel sl = next_sl; 869130803Smarcel } 870130803Smarcel so_list_head = NULL; 871130803Smarcel 872130803Smarcel pa64_solib_total_st_size = (LONGEST) 0; 873130803Smarcel pa64_solib_st_size_threshold_exceeded = 0; 874130803Smarcel 875130803Smarcel dld_cache.is_valid = 0; 876130803Smarcel dld_cache.have_read_dld_descriptor = 0; 877130803Smarcel dld_cache.dld_flags_addr = 0; 878130803Smarcel dld_cache.load_map = 0; 879130803Smarcel dld_cache.load_map_addr = 0; 880130803Smarcel dld_cache.dld_desc.data_base = 0; 881130803Smarcel dld_cache.dld_flags = 0; 882130803Smarcel dld_cache.dyninfo_sect = 0; 883130803Smarcel} 884130803Smarcel 885130803Smarcelvoid 886130803Smarcel_initialize_pa64_solib (void) 887130803Smarcel{ 888130803Smarcel add_com ("sharedlibrary", class_files, pa64_solib_sharedlibrary_command, 889130803Smarcel "Load shared object library symbols for files matching REGEXP."); 890130803Smarcel add_info ("sharedlibrary", pa64_sharedlibrary_info_command, 891130803Smarcel "Status of loaded shared object libraries."); 892130803Smarcel 893130803Smarcel add_show_from_set 894130803Smarcel (add_set_cmd ("auto-solib-add", class_support, var_boolean, 895130803Smarcel (char *) &auto_solib_add, 896130803Smarcel "Set autoloading of shared library symbols.\n\ 897130803SmarcelIf \"on\", symbols from all shared object libraries will be loaded\n\ 898130803Smarcelautomatically when the inferior begins execution, when the dynamic linker\n\ 899130803Smarcelinforms gdb that a new library has been loaded, or when attaching to the\n\ 900130803Smarcelinferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'.", 901130803Smarcel &setlist), 902130803Smarcel &showlist); 903130803Smarcel 904130803Smarcel add_show_from_set 905130803Smarcel (add_set_cmd ("auto-solib-limit", class_support, var_zinteger, 906130803Smarcel (char *) &auto_solib_limit, 907130803Smarcel "Set threshold (in Mb) for autoloading shared library symbols.\n\ 908130803SmarcelWhen shared library autoloading is enabled, new libraries will be loaded\n\ 909130803Smarcelonly until the total size of shared library symbols exceeds this\n\ 910130803Smarcelthreshold in megabytes. Is ignored when using `sharedlibrary'.", 911130803Smarcel &setlist), 912130803Smarcel &showlist); 913130803Smarcel 914130803Smarcel /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how 915130803Smarcel much data space a process can use. We ought to be reading 916130803Smarcel MAXDSIZ and setting auto_solib_limit to some large fraction of 917130803Smarcel that value. If not that, we maybe ought to be setting it smaller 918130803Smarcel than the default for MAXDSIZ (that being 64Mb, I believe). 919130803Smarcel However, [1] this threshold is only crudely approximated rather 920130803Smarcel than actually measured, and [2] 50 Mbytes is too small for 921130803Smarcel debugging gdb itself. Thus, the arbitrary 100 figure. */ 922130803Smarcel auto_solib_limit = 100; /* Megabytes */ 923130803Smarcel 924130803Smarcel pa64_solib_restart (); 925130803Smarcel} 926130803Smarcel 927130803Smarcel/* Get some HPUX-specific data from a shared lib. */ 928130803SmarcelCORE_ADDR 929130803Smarcelso_lib_thread_start_addr (struct so_list *so) 930130803Smarcel{ 931130803Smarcel return so->pa64_solib_desc.tls_start_addr; 932130803Smarcel} 933130803Smarcel 934130803Smarcel/* Read the dynamic linker's internal shared library descriptor. 935130803Smarcel 936130803Smarcel This must happen after dld starts running, so we can't do it in 937130803Smarcel read_dynamic_info. Record the fact that we have loaded the 938130803Smarcel descriptor. If the library is archive bound, then return zero, else 939130803Smarcel return nonzero. */ 940130803Smarcel 941130803Smarcelstatic int 942130803Smarcelread_dld_descriptor (struct target_ops *target, int readsyms) 943130803Smarcel{ 944130803Smarcel char *dll_path; 945130803Smarcel asection *dyninfo_sect; 946130803Smarcel 947130803Smarcel /* If necessary call read_dynamic_info to extract the contents of the 948130803Smarcel .dynamic section from the shared library. */ 949130803Smarcel if (!dld_cache.is_valid) 950130803Smarcel { 951130803Smarcel if (symfile_objfile == NULL) 952130803Smarcel error ("No object file symbols."); 953130803Smarcel 954130803Smarcel dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd, 955130803Smarcel ".dynamic"); 956130803Smarcel if (!dyninfo_sect) 957130803Smarcel { 958130803Smarcel return 0; 959130803Smarcel } 960130803Smarcel 961130803Smarcel if (!read_dynamic_info (dyninfo_sect, &dld_cache)) 962130803Smarcel error ("Unable to read in .dynamic section information."); 963130803Smarcel } 964130803Smarcel 965130803Smarcel /* Read the load map pointer. */ 966130803Smarcel if (target_read_memory (dld_cache.load_map_addr, 967130803Smarcel (char*) &dld_cache.load_map, 968130803Smarcel sizeof(dld_cache.load_map)) 969130803Smarcel != 0) 970130803Smarcel { 971130803Smarcel error ("Error while reading in load map pointer."); 972130803Smarcel } 973130803Smarcel 974130803Smarcel /* Read in the dld load module descriptor */ 975130803Smarcel if (dlgetmodinfo (-1, 976130803Smarcel &dld_cache.dld_desc, 977130803Smarcel sizeof(dld_cache.dld_desc), 978130803Smarcel pa64_target_read_memory, 979130803Smarcel 0, 980130803Smarcel dld_cache.load_map) 981130803Smarcel == 0) 982130803Smarcel { 983130803Smarcel error ("Error trying to get information about dynamic linker."); 984130803Smarcel } 985130803Smarcel 986130803Smarcel /* Indicate that we have loaded the dld descriptor. */ 987130803Smarcel dld_cache.have_read_dld_descriptor = 1; 988130803Smarcel 989130803Smarcel /* Add dld.sl to the list of known shared libraries so that we can 990130803Smarcel do unwind, etc. 991130803Smarcel 992130803Smarcel ?!? This may not be correct. Consider of dld.sl contains symbols 993130803Smarcel which are also referenced/defined by the user program or some user 994130803Smarcel shared library. We need to make absolutely sure that we do not 995130803Smarcel pollute the namespace from GDB's point of view. */ 996130803Smarcel dll_path = dlgetname (&dld_cache.dld_desc, 997130803Smarcel sizeof(dld_cache.dld_desc), 998130803Smarcel pa64_target_read_memory, 999130803Smarcel 0, 1000130803Smarcel dld_cache.load_map); 1001130803Smarcel add_to_solist(0, dll_path, readsyms, &dld_cache.dld_desc, 0, target); 1002130803Smarcel 1003130803Smarcel return 1; 1004130803Smarcel} 1005130803Smarcel 1006130803Smarcel/* Read the .dynamic section and extract the information of interest, 1007130803Smarcel which is stored in dld_cache. The routine elf_locate_base in solib.c 1008130803Smarcel was used as a model for this. */ 1009130803Smarcel 1010130803Smarcelstatic int 1011130803Smarcelread_dynamic_info (asection *dyninfo_sect, dld_cache_t *dld_cache_p) 1012130803Smarcel{ 1013130803Smarcel char *buf; 1014130803Smarcel char *bufend; 1015130803Smarcel CORE_ADDR dyninfo_addr; 1016130803Smarcel int dyninfo_sect_size; 1017130803Smarcel CORE_ADDR entry_addr; 1018130803Smarcel 1019130803Smarcel /* Read in .dynamic section, silently ignore errors. */ 1020130803Smarcel dyninfo_addr = bfd_section_vma (symfile_objfile->obfd, dyninfo_sect); 1021130803Smarcel dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect); 1022130803Smarcel buf = alloca (dyninfo_sect_size); 1023130803Smarcel if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size)) 1024130803Smarcel return 0; 1025130803Smarcel 1026130803Smarcel /* Scan the .dynamic section and record the items of interest. 1027130803Smarcel In particular, DT_HP_DLD_FLAGS */ 1028130803Smarcel for (bufend = buf + dyninfo_sect_size, entry_addr = dyninfo_addr; 1029130803Smarcel buf < bufend; 1030130803Smarcel buf += sizeof (Elf64_Dyn), entry_addr += sizeof (Elf64_Dyn)) 1031130803Smarcel { 1032130803Smarcel Elf64_Dyn *x_dynp = (Elf64_Dyn*)buf; 1033130803Smarcel Elf64_Sxword dyn_tag; 1034130803Smarcel CORE_ADDR dyn_ptr; 1035130803Smarcel char *pbuf; 1036130803Smarcel 1037130803Smarcel pbuf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT); 1038130803Smarcel dyn_tag = bfd_h_get_64 (symfile_objfile->obfd, 1039130803Smarcel (bfd_byte*) &x_dynp->d_tag); 1040130803Smarcel 1041130803Smarcel /* We can't use a switch here because dyn_tag is 64 bits and HP's 1042130803Smarcel lame comiler does not handle 64bit items in switch statements. */ 1043130803Smarcel if (dyn_tag == DT_NULL) 1044130803Smarcel break; 1045130803Smarcel else if (dyn_tag == DT_HP_DLD_FLAGS) 1046130803Smarcel { 1047130803Smarcel /* Set dld_flags_addr and dld_flags in *dld_cache_p */ 1048130803Smarcel dld_cache_p->dld_flags_addr = entry_addr + offsetof(Elf64_Dyn, d_un); 1049130803Smarcel if (target_read_memory (dld_cache_p->dld_flags_addr, 1050130803Smarcel (char*) &dld_cache_p->dld_flags, 1051130803Smarcel sizeof(dld_cache_p->dld_flags)) 1052130803Smarcel != 0) 1053130803Smarcel { 1054130803Smarcel error ("Error while reading in .dynamic section of the program."); 1055130803Smarcel } 1056130803Smarcel } 1057130803Smarcel else if (dyn_tag == DT_HP_LOAD_MAP) 1058130803Smarcel { 1059130803Smarcel /* Dld will place the address of the load map at load_map_addr 1060130803Smarcel after it starts running. */ 1061130803Smarcel if (target_read_memory (entry_addr + offsetof(Elf64_Dyn, 1062130803Smarcel d_un.d_ptr), 1063130803Smarcel (char*) &dld_cache_p->load_map_addr, 1064130803Smarcel sizeof(dld_cache_p->load_map_addr)) 1065130803Smarcel != 0) 1066130803Smarcel { 1067130803Smarcel error ("Error while reading in .dynamic section of the program."); 1068130803Smarcel } 1069130803Smarcel } 1070130803Smarcel else 1071130803Smarcel { 1072130803Smarcel /* tag is not of interest */ 1073130803Smarcel } 1074130803Smarcel } 1075130803Smarcel 1076130803Smarcel /* Record other information and set is_valid to 1. */ 1077130803Smarcel dld_cache_p->dyninfo_sect = dyninfo_sect; 1078130803Smarcel 1079130803Smarcel /* Verify that we read in required info. These fields are re-set to zero 1080130803Smarcel in pa64_solib_restart. */ 1081130803Smarcel 1082130803Smarcel if (dld_cache_p->dld_flags_addr != 0 && dld_cache_p->load_map_addr != 0) 1083130803Smarcel dld_cache_p->is_valid = 1; 1084130803Smarcel else 1085130803Smarcel return 0; 1086130803Smarcel 1087130803Smarcel return 1; 1088130803Smarcel} 1089130803Smarcel 1090130803Smarcel/* Wrapper for target_read_memory to make dlgetmodinfo happy. */ 1091130803Smarcel 1092130803Smarcelstatic void * 1093130803Smarcelpa64_target_read_memory (void *buffer, CORE_ADDR ptr, size_t bufsiz, int ident) 1094130803Smarcel{ 1095130803Smarcel if (target_read_memory (ptr, buffer, bufsiz) != 0) 1096130803Smarcel return 0; 1097130803Smarcel return buffer; 1098130803Smarcel} 1099130803Smarcel 1100130803Smarcel/* Called from handle_dynlink_load_event and pa64_solib_add to add 1101130803Smarcel a shared library to so_list_head list and possibly to read in the 1102130803Smarcel debug information for the library. 1103130803Smarcel 1104130803Smarcel If load_module_desc_p is NULL, then the load module descriptor must 1105130803Smarcel be read from the inferior process at the address load_module_desc_addr. */ 1106130803Smarcel 1107130803Smarcelstatic void 1108130803Smarceladd_to_solist (int from_tty, char *dll_path, int readsyms, 1109130803Smarcel struct load_module_desc *load_module_desc_p, 1110130803Smarcel CORE_ADDR load_module_desc_addr, struct target_ops *target) 1111130803Smarcel{ 1112130803Smarcel struct so_list *new_so, *so_list_tail; 1113130803Smarcel int pa64_solib_st_size_threshhold_exceeded; 1114130803Smarcel LONGEST st_size; 1115130803Smarcel 1116130803Smarcel if (symfile_objfile == NULL) 1117130803Smarcel return; 1118130803Smarcel 1119130803Smarcel so_list_tail = so_list_head; 1120130803Smarcel /* Find the end of the list of shared objects. */ 1121130803Smarcel while (so_list_tail && so_list_tail->next) 1122130803Smarcel { 1123130803Smarcel if (strcmp (so_list_tail->name, dll_path) == 0) 1124130803Smarcel return; 1125130803Smarcel so_list_tail = so_list_tail->next; 1126130803Smarcel } 1127130803Smarcel 1128130803Smarcel if (so_list_tail && strcmp (so_list_tail->name, dll_path) == 0) 1129130803Smarcel return; 1130130803Smarcel 1131130803Smarcel /* Add the shared library to the so_list_head list */ 1132130803Smarcel new_so = (struct so_list *) xmalloc (sizeof (struct so_list)); 1133130803Smarcel memset ((char *)new_so, 0, sizeof (struct so_list)); 1134130803Smarcel if (so_list_head == NULL) 1135130803Smarcel { 1136130803Smarcel so_list_head = new_so; 1137130803Smarcel so_list_tail = new_so; 1138130803Smarcel } 1139130803Smarcel else 1140130803Smarcel { 1141130803Smarcel so_list_tail->next = new_so; 1142130803Smarcel so_list_tail = new_so; 1143130803Smarcel } 1144130803Smarcel 1145130803Smarcel /* Initialize the new_so */ 1146130803Smarcel if (load_module_desc_p) 1147130803Smarcel { 1148130803Smarcel new_so->pa64_solib_desc = *load_module_desc_p; 1149130803Smarcel } 1150130803Smarcel else 1151130803Smarcel { 1152130803Smarcel if (target_read_memory (load_module_desc_addr, 1153130803Smarcel (char*) &new_so->pa64_solib_desc, 1154130803Smarcel sizeof(struct load_module_desc)) 1155130803Smarcel != 0) 1156130803Smarcel { 1157130803Smarcel error ("Error while reading in dynamic library %s", dll_path); 1158130803Smarcel } 1159130803Smarcel } 1160130803Smarcel 1161130803Smarcel new_so->pa64_solib_desc_addr = load_module_desc_addr; 1162130803Smarcel new_so->loaded = 1; 1163130803Smarcel new_so->name = obsavestring (dll_path, strlen(dll_path), 1164130803Smarcel &symfile_objfile->objfile_obstack); 1165130803Smarcel 1166130803Smarcel /* If we are not going to load the library, tell the user if we 1167130803Smarcel haven't already and return. */ 1168130803Smarcel 1169130803Smarcel st_size = pa64_solib_sizeof_symbol_table (dll_path); 1170130803Smarcel pa64_solib_st_size_threshhold_exceeded = 1171130803Smarcel !from_tty 1172130803Smarcel && readsyms 1173130803Smarcel && ( (st_size + pa64_solib_total_st_size) 1174130803Smarcel > (auto_solib_limit * (LONGEST) (1024 * 1024))); 1175130803Smarcel if (pa64_solib_st_size_threshhold_exceeded) 1176130803Smarcel { 1177130803Smarcel pa64_solib_add_solib_objfile (new_so, dll_path, from_tty, 1); 1178130803Smarcel return; 1179130803Smarcel } 1180130803Smarcel 1181130803Smarcel /* Now read in debug info. */ 1182130803Smarcel pa64_solib_total_st_size += st_size; 1183130803Smarcel 1184130803Smarcel /* This fills in new_so->objfile, among others. */ 1185130803Smarcel pa64_solib_load_symbols (new_so, 1186130803Smarcel dll_path, 1187130803Smarcel from_tty, 1188130803Smarcel 0, 1189130803Smarcel target); 1190130803Smarcel return; 1191130803Smarcel} 1192130803Smarcel 1193130803Smarcel 1194130803Smarcel/* 1195130803Smarcel LOCAL FUNCTION 1196130803Smarcel 1197130803Smarcel bfd_lookup_symbol -- lookup the value for a specific symbol 1198130803Smarcel 1199130803Smarcel SYNOPSIS 1200130803Smarcel 1201130803Smarcel CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname) 1202130803Smarcel 1203130803Smarcel DESCRIPTION 1204130803Smarcel 1205130803Smarcel An expensive way to lookup the value of a single symbol for 1206130803Smarcel bfd's that are only temporary anyway. This is used by the 1207130803Smarcel shared library support to find the address of the debugger 1208130803Smarcel interface structures in the shared library. 1209130803Smarcel 1210130803Smarcel Note that 0 is specifically allowed as an error return (no 1211130803Smarcel such symbol). 1212130803Smarcel */ 1213130803Smarcel 1214130803Smarcelstatic CORE_ADDR 1215130803Smarcelbfd_lookup_symbol (bfd *abfd, char *symname) 1216130803Smarcel{ 1217130803Smarcel unsigned int storage_needed; 1218130803Smarcel asymbol *sym; 1219130803Smarcel asymbol **symbol_table; 1220130803Smarcel unsigned int number_of_symbols; 1221130803Smarcel unsigned int i; 1222130803Smarcel struct cleanup *back_to; 1223130803Smarcel CORE_ADDR symaddr = 0; 1224130803Smarcel 1225130803Smarcel storage_needed = bfd_get_symtab_upper_bound (abfd); 1226130803Smarcel 1227130803Smarcel if (storage_needed > 0) 1228130803Smarcel { 1229130803Smarcel symbol_table = (asymbol **) xmalloc (storage_needed); 1230130803Smarcel back_to = make_cleanup (xfree, symbol_table); 1231130803Smarcel number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); 1232130803Smarcel 1233130803Smarcel for (i = 0; i < number_of_symbols; i++) 1234130803Smarcel { 1235130803Smarcel sym = *symbol_table++; 1236130803Smarcel if (strcmp (sym->name, symname) == 0) 1237130803Smarcel { 1238130803Smarcel /* Bfd symbols are section relative. */ 1239130803Smarcel symaddr = sym->value + sym->section->vma; 1240130803Smarcel break; 1241130803Smarcel } 1242130803Smarcel } 1243130803Smarcel do_cleanups (back_to); 1244130803Smarcel } 1245130803Smarcel return (symaddr); 1246130803Smarcel} 1247130803Smarcel 1248