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 (&current_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