1b725ae77Skettenis /* Handle HP ELF shared libraries for GDB, the GNU Debugger.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation,
4b725ae77Skettenis Inc.
5b725ae77Skettenis
6b725ae77Skettenis This file is part of GDB.
7b725ae77Skettenis
8b725ae77Skettenis This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis it under the terms of the GNU General Public License as published by
10b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis (at your option) any later version.
12b725ae77Skettenis
13b725ae77Skettenis This program is distributed in the hope that it will be useful,
14b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16b725ae77Skettenis GNU General Public License for more details.
17b725ae77Skettenis
18b725ae77Skettenis You should have received a copy of the GNU General Public License
19b725ae77Skettenis along with this program; if not, write to the Free Software
20b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis Boston, MA 02111-1307, USA.
22b725ae77Skettenis
23b725ae77Skettenis HP in their infinite stupidity choose not to use standard ELF dynamic
24b725ae77Skettenis linker interfaces. They also choose not to make their ELF dymamic
25b725ae77Skettenis linker interfaces compatible with the SOM dynamic linker. The
26b725ae77Skettenis net result is we can not use either of the existing somsolib.c or
27b725ae77Skettenis solib.c. What a crock.
28b725ae77Skettenis
29b725ae77Skettenis Even more disgusting. This file depends on functions provided only
30b725ae77Skettenis in certain PA64 libraries. Thus this file is supposed to only be
31b725ae77Skettenis used native. When will HP ever learn that they need to provide the
32b725ae77Skettenis same functionality in all their libraries! */
33b725ae77Skettenis
34b725ae77Skettenis #include <dlfcn.h>
35b725ae77Skettenis #include <elf.h>
36b725ae77Skettenis #include <elf_hp.h>
37b725ae77Skettenis
38b725ae77Skettenis #include "defs.h"
39b725ae77Skettenis
40b725ae77Skettenis #include "frame.h"
41b725ae77Skettenis #include "bfd.h"
42b725ae77Skettenis #include "libhppa.h"
43b725ae77Skettenis #include "gdbcore.h"
44b725ae77Skettenis #include "symtab.h"
45b725ae77Skettenis #include "breakpoint.h"
46b725ae77Skettenis #include "symfile.h"
47b725ae77Skettenis #include "objfiles.h"
48b725ae77Skettenis #include "inferior.h"
49b725ae77Skettenis #include "gdb-stabs.h"
50b725ae77Skettenis #include "gdb_stat.h"
51b725ae77Skettenis #include "gdbcmd.h"
52b725ae77Skettenis #include "language.h"
53b725ae77Skettenis #include "regcache.h"
54b725ae77Skettenis #include "exec.h"
55*11efff7fSkettenis #include "hppa-tdep.h"
56b725ae77Skettenis
57b725ae77Skettenis #include <fcntl.h>
58b725ae77Skettenis
59b725ae77Skettenis #ifndef O_BINARY
60b725ae77Skettenis #define O_BINARY 0
61b725ae77Skettenis #endif
62b725ae77Skettenis
63b725ae77Skettenis static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
64b725ae77Skettenis /* This lives in hppa-tdep.c. */
65b725ae77Skettenis extern struct unwind_table_entry *find_unwind_entry (CORE_ADDR pc);
66b725ae77Skettenis
67b725ae77Skettenis /* These ought to be defined in some public interface, but aren't. They
68b725ae77Skettenis identify dynamic linker events. */
69b725ae77Skettenis #define DLD_CB_LOAD 1
70b725ae77Skettenis #define DLD_CB_UNLOAD 0
71b725ae77Skettenis
72b725ae77Skettenis /* A structure to keep track of all the known shared objects. */
73b725ae77Skettenis struct so_list
74b725ae77Skettenis {
75b725ae77Skettenis bfd *abfd;
76b725ae77Skettenis char *name;
77b725ae77Skettenis struct so_list *next;
78b725ae77Skettenis struct objfile *objfile;
79b725ae77Skettenis CORE_ADDR pa64_solib_desc_addr;
80b725ae77Skettenis struct load_module_desc pa64_solib_desc;
81b725ae77Skettenis struct section_table *sections;
82b725ae77Skettenis struct section_table *sections_end;
83b725ae77Skettenis int loaded;
84b725ae77Skettenis };
85b725ae77Skettenis
86b725ae77Skettenis static struct so_list *so_list_head;
87b725ae77Skettenis
88b725ae77Skettenis /* This is the cumulative size in bytes of the symbol tables of all
89b725ae77Skettenis shared objects on the so_list_head list. (When we say size, here
90b725ae77Skettenis we mean of the information before it is brought into memory and
91b725ae77Skettenis potentially expanded by GDB.) When adding a new shlib, this value
92b725ae77Skettenis is compared against a threshold size, held by auto_solib_limit (in
93b725ae77Skettenis megabytes). If adding symbols for the new shlib would cause the
94b725ae77Skettenis total size to exceed the threshold, then the new shlib's symbols
95b725ae77Skettenis are not loaded. */
96b725ae77Skettenis static LONGEST pa64_solib_total_st_size;
97b725ae77Skettenis
98b725ae77Skettenis /* When the threshold is reached for any shlib, we refuse to add
99b725ae77Skettenis symbols for subsequent shlibs, even if those shlibs' symbols would
100b725ae77Skettenis be small enough to fit under the threshold. Although this may
101b725ae77Skettenis result in one, early large shlib preventing the loading of later,
102b725ae77Skettenis smaller shlibs' symbols, it allows us to issue one informational
103b725ae77Skettenis message. The alternative, to issue a message for each shlib whose
104b725ae77Skettenis symbols aren't loaded, could be a big annoyance where the threshold
105b725ae77Skettenis is exceeded due to a very large number of shlibs. */
106b725ae77Skettenis static int pa64_solib_st_size_threshold_exceeded;
107b725ae77Skettenis
108b725ae77Skettenis /* When adding fields, be sure to clear them in _initialize_pa64_solib. */
109b725ae77Skettenis typedef struct
110b725ae77Skettenis {
111b725ae77Skettenis CORE_ADDR dld_flags_addr;
112b725ae77Skettenis LONGEST dld_flags;
113b725ae77Skettenis struct bfd_section *dyninfo_sect;
114b725ae77Skettenis int have_read_dld_descriptor;
115b725ae77Skettenis int is_valid;
116b725ae77Skettenis CORE_ADDR load_map;
117b725ae77Skettenis CORE_ADDR load_map_addr;
118b725ae77Skettenis struct load_module_desc dld_desc;
119b725ae77Skettenis }
120b725ae77Skettenis dld_cache_t;
121b725ae77Skettenis
122b725ae77Skettenis static dld_cache_t dld_cache;
123b725ae77Skettenis
124b725ae77Skettenis static void pa64_sharedlibrary_info_command (char *, int);
125b725ae77Skettenis
126b725ae77Skettenis static void pa64_solib_sharedlibrary_command (char *, int);
127b725ae77Skettenis
128b725ae77Skettenis static void *pa64_target_read_memory (void *, CORE_ADDR, size_t, int);
129b725ae77Skettenis
130b725ae77Skettenis static int read_dld_descriptor (struct target_ops *, int readsyms);
131b725ae77Skettenis
132b725ae77Skettenis static int read_dynamic_info (asection *, dld_cache_t *);
133b725ae77Skettenis
134b725ae77Skettenis static void add_to_solist (int, char *, int, struct load_module_desc *,
135b725ae77Skettenis CORE_ADDR, struct target_ops *);
136b725ae77Skettenis
137b725ae77Skettenis /* When examining the shared library for debugging information we have to
138b725ae77Skettenis look for HP debug symbols, stabs and dwarf2 debug symbols. */
139b725ae77Skettenis static char *pa64_debug_section_names[] = {
140b725ae77Skettenis ".debug_header", ".debug_gntt", ".debug_lntt", ".debug_slt", ".debug_vt",
141b725ae77Skettenis ".stabs", ".stabstr", ".debug_info", ".debug_abbrev", ".debug_aranges",
142b725ae77Skettenis ".debug_macinfo", ".debug_line", ".debug_loc", ".debug_pubnames",
143b725ae77Skettenis ".debug_str", NULL
144b725ae77Skettenis };
145b725ae77Skettenis
146b725ae77Skettenis /* Return a ballbark figure for the amount of memory GDB will need to
147b725ae77Skettenis allocate to read in the debug symbols from FILENAME. */
148b725ae77Skettenis static LONGEST
pa64_solib_sizeof_symbol_table(char * filename)149b725ae77Skettenis pa64_solib_sizeof_symbol_table (char *filename)
150b725ae77Skettenis {
151b725ae77Skettenis bfd *abfd;
152b725ae77Skettenis int i;
153b725ae77Skettenis int desc;
154b725ae77Skettenis char *absolute_name;
155b725ae77Skettenis LONGEST st_size = (LONGEST) 0;
156b725ae77Skettenis asection *sect;
157b725ae77Skettenis
158b725ae77Skettenis /* We believe that filename was handed to us by the dynamic linker, and
159b725ae77Skettenis is therefore always an absolute path. */
160*11efff7fSkettenis desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
161*11efff7fSkettenis O_RDONLY | O_BINARY, 0, &absolute_name);
162b725ae77Skettenis if (desc < 0)
163b725ae77Skettenis {
164b725ae77Skettenis perror_with_name (filename);
165b725ae77Skettenis }
166b725ae77Skettenis filename = absolute_name;
167b725ae77Skettenis
168b725ae77Skettenis abfd = bfd_fdopenr (filename, gnutarget, desc);
169b725ae77Skettenis if (!abfd)
170b725ae77Skettenis {
171b725ae77Skettenis close (desc);
172b725ae77Skettenis make_cleanup (xfree, filename);
173b725ae77Skettenis error ("\"%s\": can't open to read symbols: %s.", filename,
174b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
175b725ae77Skettenis }
176b725ae77Skettenis
177b725ae77Skettenis if (!bfd_check_format (abfd, bfd_object))
178b725ae77Skettenis {
179b725ae77Skettenis bfd_close (abfd);
180b725ae77Skettenis make_cleanup (xfree, filename);
181b725ae77Skettenis error ("\"%s\": can't read symbols: %s.", filename,
182b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
183b725ae77Skettenis }
184b725ae77Skettenis
185b725ae77Skettenis /* Sum the sizes of the various sections that compose debug info. */
186b725ae77Skettenis for (i = 0; pa64_debug_section_names[i] != NULL; i++)
187b725ae77Skettenis {
188b725ae77Skettenis asection *sect;
189b725ae77Skettenis
190b725ae77Skettenis sect = bfd_get_section_by_name (abfd, pa64_debug_section_names[i]);
191b725ae77Skettenis if (sect)
192b725ae77Skettenis st_size += (LONGEST)bfd_section_size (abfd, sect);
193b725ae77Skettenis }
194b725ae77Skettenis
195b725ae77Skettenis bfd_close (abfd);
196b725ae77Skettenis xfree (filename);
197b725ae77Skettenis
198b725ae77Skettenis /* Unfortunately, just summing the sizes of various debug info
199b725ae77Skettenis sections isn't a very accurate measurement of how much heap
200b725ae77Skettenis space the debugger will need to hold them. It also doesn't
201b725ae77Skettenis account for space needed by linker (aka "minimal") symbols.
202b725ae77Skettenis
203b725ae77Skettenis Anecdotal evidence suggests that just summing the sizes of
204b725ae77Skettenis debug-info-related sections understates the heap space needed
205b725ae77Skettenis to represent it internally by about an order of magnitude.
206b725ae77Skettenis
207b725ae77Skettenis Since it's not exactly brain surgery we're doing here, rather
208b725ae77Skettenis than attempt to more accurately measure the size of a shlib's
209b725ae77Skettenis symbol table in GDB's heap, we'll just apply a 10x fudge-
210b725ae77Skettenis factor to the debug info sections' size-sum. No, this doesn't
211b725ae77Skettenis account for minimal symbols in non-debuggable shlibs. But it
212b725ae77Skettenis all roughly washes out in the end. */
213b725ae77Skettenis return st_size * (LONGEST) 10;
214b725ae77Skettenis }
215b725ae77Skettenis
216b725ae77Skettenis /* Add a shared library to the objfile list and load its symbols into
217b725ae77Skettenis GDB's symbol table. */
218b725ae77Skettenis static void
pa64_solib_add_solib_objfile(struct so_list * so,char * name,int from_tty,CORE_ADDR text_addr)219b725ae77Skettenis pa64_solib_add_solib_objfile (struct so_list *so, char *name, int from_tty,
220b725ae77Skettenis CORE_ADDR text_addr)
221b725ae77Skettenis {
222b725ae77Skettenis bfd *tmp_bfd;
223b725ae77Skettenis asection *sec;
224*11efff7fSkettenis struct hppa_objfile_private *obj_private;
225b725ae77Skettenis struct section_addr_info *section_addrs;
226b725ae77Skettenis struct cleanup *my_cleanups;
227b725ae77Skettenis
228b725ae77Skettenis /* We need the BFD so that we can look at its sections. We open up the
229b725ae77Skettenis file temporarily, then close it when we are done. */
230b725ae77Skettenis tmp_bfd = bfd_openr (name, gnutarget);
231b725ae77Skettenis if (tmp_bfd == NULL)
232b725ae77Skettenis {
233b725ae77Skettenis perror_with_name (name);
234b725ae77Skettenis return;
235b725ae77Skettenis }
236b725ae77Skettenis
237b725ae77Skettenis if (!bfd_check_format (tmp_bfd, bfd_object))
238b725ae77Skettenis {
239b725ae77Skettenis bfd_close (tmp_bfd);
240b725ae77Skettenis error ("\"%s\" is not an object file: %s", name,
241b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
242b725ae77Skettenis }
243b725ae77Skettenis
244b725ae77Skettenis
245b725ae77Skettenis /* Undo some braindamage from symfile.c.
246b725ae77Skettenis
247b725ae77Skettenis First, symfile.c will subtract the VMA of the first .text section
248b725ae77Skettenis in the shared library that it finds. Undo that. */
249b725ae77Skettenis sec = bfd_get_section_by_name (tmp_bfd, ".text");
250b725ae77Skettenis text_addr += bfd_section_vma (tmp_bfd, sec);
251b725ae77Skettenis
252b725ae77Skettenis /* Now find the true lowest section in the shared library. */
253b725ae77Skettenis sec = NULL;
254b725ae77Skettenis bfd_map_over_sections (tmp_bfd, find_lowest_section, &sec);
255b725ae77Skettenis
256b725ae77Skettenis if (sec)
257b725ae77Skettenis {
258b725ae77Skettenis /* Subtract out the VMA of the lowest section. */
259b725ae77Skettenis text_addr -= bfd_section_vma (tmp_bfd, sec);
260b725ae77Skettenis
261b725ae77Skettenis /* ??? Add back in the filepos of that lowest section. */
262b725ae77Skettenis text_addr += sec->filepos;
263b725ae77Skettenis }
264b725ae77Skettenis
265b725ae77Skettenis section_addrs = alloc_section_addr_info (bfd_count_sections (tmp_bfd));
266b725ae77Skettenis my_cleanups = make_cleanup (xfree, section_addrs);
267b725ae77Skettenis
268b725ae77Skettenis /* We are done with the temporary bfd. Get rid of it and make sure
269b725ae77Skettenis nobody else can us it. */
270b725ae77Skettenis bfd_close (tmp_bfd);
271b725ae77Skettenis tmp_bfd = NULL;
272b725ae77Skettenis
273b725ae77Skettenis /* Now let the generic code load up symbols for this library. */
274b725ae77Skettenis section_addrs->other[0].addr = text_addr;
275b725ae77Skettenis section_addrs->other[0].name = ".text";
276b725ae77Skettenis so->objfile = symbol_file_add (name, from_tty, section_addrs, 0, OBJF_SHARED);
277b725ae77Skettenis so->abfd = so->objfile->obfd;
278b725ae77Skettenis
279b725ae77Skettenis /* Mark this as a shared library and save private data. */
280b725ae77Skettenis so->objfile->flags |= OBJF_SHARED;
281b725ae77Skettenis
282*11efff7fSkettenis obj_private = (struct hppa_objfile_private *)
283*11efff7fSkettenis objfile_data (so->objfile, hppa_objfile_priv_data);
284*11efff7fSkettenis if (obj_private == NULL)
285b725ae77Skettenis {
286*11efff7fSkettenis obj_private = (struct hppa_objfile_private *)
287b725ae77Skettenis obstack_alloc (&so->objfile->objfile_obstack,
288*11efff7fSkettenis sizeof (struct hppa_objfile_private));
289*11efff7fSkettenis set_objfile_data (so->objfile, hppa_objfile_priv_data, obj_private);
290b725ae77Skettenis obj_private->unwind_info = NULL;
291b725ae77Skettenis obj_private->so_info = NULL;
292b725ae77Skettenis }
293b725ae77Skettenis
294b725ae77Skettenis obj_private->so_info = so;
295b725ae77Skettenis obj_private->dp = so->pa64_solib_desc.linkage_ptr;
296b725ae77Skettenis do_cleanups (my_cleanups);
297b725ae77Skettenis }
298b725ae77Skettenis
299b725ae77Skettenis /* Load debugging information for a shared library. TARGET may be
300b725ae77Skettenis NULL if we are not attaching to a process or reading a core file. */
301b725ae77Skettenis
302b725ae77Skettenis static void
pa64_solib_load_symbols(struct so_list * so,char * name,int from_tty,CORE_ADDR text_addr,struct target_ops * target)303b725ae77Skettenis pa64_solib_load_symbols (struct so_list *so, char *name, int from_tty,
304b725ae77Skettenis CORE_ADDR text_addr, struct target_ops *target)
305b725ae77Skettenis {
306b725ae77Skettenis struct section_table *p;
307b725ae77Skettenis asection *sec;
308b725ae77Skettenis int status;
309b725ae77Skettenis char buf[4];
310b725ae77Skettenis CORE_ADDR presumed_data_start;
311b725ae77Skettenis
312b725ae77Skettenis if (text_addr == 0)
313b725ae77Skettenis text_addr = so->pa64_solib_desc.text_base;
314b725ae77Skettenis
315b725ae77Skettenis pa64_solib_add_solib_objfile (so, name, from_tty, text_addr);
316b725ae77Skettenis
317b725ae77Skettenis /* Now we need to build a section table for this library since
318b725ae77Skettenis we might be debugging a core file from a dynamically linked
319b725ae77Skettenis executable in which the libraries were not privately mapped. */
320b725ae77Skettenis if (build_section_table (so->abfd,
321b725ae77Skettenis &so->sections,
322b725ae77Skettenis &so->sections_end))
323b725ae77Skettenis {
324b725ae77Skettenis error ("Unable to build section table for shared library\n.");
325b725ae77Skettenis return;
326b725ae77Skettenis }
327b725ae77Skettenis
328b725ae77Skettenis (so->objfile->section_offsets)->offsets[SECT_OFF_TEXT (so->objfile)]
329b725ae77Skettenis = so->pa64_solib_desc.text_base;
330b725ae77Skettenis (so->objfile->section_offsets)->offsets[SECT_OFF_DATA (so->objfile)]
331b725ae77Skettenis = so->pa64_solib_desc.data_base;
332b725ae77Skettenis
333b725ae77Skettenis /* Relocate all the sections based on where they got loaded. */
334b725ae77Skettenis for (p = so->sections; p < so->sections_end; p++)
335b725ae77Skettenis {
336b725ae77Skettenis if (p->the_bfd_section->flags & SEC_CODE)
337b725ae77Skettenis {
338b725ae77Skettenis p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
339b725ae77Skettenis p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
340b725ae77Skettenis }
341b725ae77Skettenis else if (p->the_bfd_section->flags & SEC_DATA)
342b725ae77Skettenis {
343b725ae77Skettenis p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
344b725ae77Skettenis p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
345b725ae77Skettenis }
346b725ae77Skettenis }
347b725ae77Skettenis
348b725ae77Skettenis /* Now see if we need to map in the text and data for this shared
349b725ae77Skettenis library (for example debugging a core file which does not use
350b725ae77Skettenis private shared libraries.).
351b725ae77Skettenis
352b725ae77Skettenis Carefully peek at the first text address in the library. If the
353b725ae77Skettenis read succeeds, then the libraries were privately mapped and were
354b725ae77Skettenis included in the core dump file.
355b725ae77Skettenis
356b725ae77Skettenis If the peek failed, then the libraries were not privately mapped
357b725ae77Skettenis and are not in the core file, we'll have to read them in ourselves. */
358b725ae77Skettenis status = target_read_memory (text_addr, buf, 4);
359b725ae77Skettenis if (status != 0)
360b725ae77Skettenis {
361b725ae77Skettenis int new, old;
362b725ae77Skettenis
363b725ae77Skettenis new = so->sections_end - so->sections;
364b725ae77Skettenis
365b725ae77Skettenis old = target_resize_to_sections (target, new);
366b725ae77Skettenis
367b725ae77Skettenis /* Copy over the old data before it gets clobbered. */
368b725ae77Skettenis memcpy ((char *) (target->to_sections + old),
369b725ae77Skettenis so->sections,
370b725ae77Skettenis ((sizeof (struct section_table)) * new));
371b725ae77Skettenis }
372b725ae77Skettenis }
373b725ae77Skettenis
374b725ae77Skettenis
375b725ae77Skettenis /* Add symbols from shared libraries into the symtab list, unless the
376b725ae77Skettenis size threshold specified by auto_solib_limit (in megabytes) would
377b725ae77Skettenis be exceeded. */
378b725ae77Skettenis
379b725ae77Skettenis void
pa64_solib_add(char * arg_string,int from_tty,struct target_ops * target,int readsyms)380b725ae77Skettenis pa64_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
381b725ae77Skettenis {
382b725ae77Skettenis struct minimal_symbol *msymbol;
383b725ae77Skettenis CORE_ADDR addr;
384b725ae77Skettenis asection *shlib_info;
385b725ae77Skettenis int status;
386b725ae77Skettenis unsigned int dld_flags;
387b725ae77Skettenis char buf[4], *re_err;
388b725ae77Skettenis int threshold_warning_given = 0;
389b725ae77Skettenis int dll_index;
390b725ae77Skettenis struct load_module_desc dll_desc;
391b725ae77Skettenis char *dll_path;
392b725ae77Skettenis
393b725ae77Skettenis /* First validate our arguments. */
394b725ae77Skettenis if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
395b725ae77Skettenis {
396b725ae77Skettenis error ("Invalid regexp: %s", re_err);
397b725ae77Skettenis }
398b725ae77Skettenis
399b725ae77Skettenis /* If we're debugging a core file, or have attached to a running
400b725ae77Skettenis process, then pa64_solib_create_inferior_hook will not have been
401b725ae77Skettenis called.
402b725ae77Skettenis
403b725ae77Skettenis We need to first determine if we're dealing with a dynamically
404b725ae77Skettenis linked executable. If not, then return without an error or warning.
405b725ae77Skettenis
406b725ae77Skettenis We also need to examine __dld_flags to determine if the shared library
407b725ae77Skettenis list is valid and to determine if the libraries have been privately
408b725ae77Skettenis mapped. */
409b725ae77Skettenis if (symfile_objfile == NULL)
410b725ae77Skettenis return;
411b725ae77Skettenis
412b725ae77Skettenis /* First see if the objfile was dynamically linked. */
413b725ae77Skettenis shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic");
414b725ae77Skettenis if (!shlib_info)
415b725ae77Skettenis return;
416b725ae77Skettenis
417b725ae77Skettenis /* It's got a .dynamic section, make sure it's not empty. */
418b725ae77Skettenis if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
419b725ae77Skettenis return;
420b725ae77Skettenis
421b725ae77Skettenis /* Read in the load map pointer if we have not done so already. */
422b725ae77Skettenis if (! dld_cache.have_read_dld_descriptor)
423b725ae77Skettenis if (! read_dld_descriptor (target, readsyms))
424b725ae77Skettenis return;
425b725ae77Skettenis
426b725ae77Skettenis /* If the libraries were not mapped private, warn the user. */
427b725ae77Skettenis if ((dld_cache.dld_flags & DT_HP_DEBUG_PRIVATE) == 0)
428b725ae77Skettenis warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
429b725ae77Skettenis
430b725ae77Skettenis /* For each shaerd library, add it to the shared library list. */
431b725ae77Skettenis for (dll_index = 1; ; dll_index++)
432b725ae77Skettenis {
433b725ae77Skettenis /* Read in the load module descriptor. */
434b725ae77Skettenis if (dlgetmodinfo (dll_index, &dll_desc, sizeof (dll_desc),
435b725ae77Skettenis pa64_target_read_memory, 0, dld_cache.load_map)
436b725ae77Skettenis == 0)
437b725ae77Skettenis return;
438b725ae77Skettenis
439b725ae77Skettenis /* Get the name of the shared library. */
440b725ae77Skettenis dll_path = (char *)dlgetname (&dll_desc, sizeof (dll_desc),
441b725ae77Skettenis pa64_target_read_memory,
442b725ae77Skettenis 0, dld_cache.load_map);
443b725ae77Skettenis
444b725ae77Skettenis if (!dll_path)
445b725ae77Skettenis error ("pa64_solib_add, unable to read shared library path.");
446b725ae77Skettenis
447b725ae77Skettenis add_to_solist (from_tty, dll_path, readsyms, &dll_desc, 0, target);
448b725ae77Skettenis }
449b725ae77Skettenis }
450b725ae77Skettenis
451b725ae77Skettenis
452b725ae77Skettenis /* This hook gets called just before the first instruction in the
453b725ae77Skettenis inferior process is executed.
454b725ae77Skettenis
455b725ae77Skettenis This is our opportunity to set magic flags in the inferior so
456b725ae77Skettenis that GDB can be notified when a shared library is mapped in and
457b725ae77Skettenis to tell the dynamic linker that a private copy of the library is
458b725ae77Skettenis needed (so GDB can set breakpoints in the library).
459b725ae77Skettenis
460b725ae77Skettenis We need to set two flag bits in this routine.
461b725ae77Skettenis
462b725ae77Skettenis DT_HP_DEBUG_PRIVATE to indicate that shared libraries should be
463b725ae77Skettenis mapped private.
464b725ae77Skettenis
465b725ae77Skettenis DT_HP_DEBUG_CALLBACK to indicate that we want the dynamic linker to
466b725ae77Skettenis call the breakpoint routine for significant events. */
467b725ae77Skettenis
468b725ae77Skettenis void
pa64_solib_create_inferior_hook(void)469b725ae77Skettenis pa64_solib_create_inferior_hook (void)
470b725ae77Skettenis {
471b725ae77Skettenis struct minimal_symbol *msymbol;
472b725ae77Skettenis unsigned int dld_flags, status;
473b725ae77Skettenis asection *shlib_info, *interp_sect;
474b725ae77Skettenis char buf[4];
475b725ae77Skettenis struct objfile *objfile;
476b725ae77Skettenis CORE_ADDR anaddr;
477b725ae77Skettenis
478b725ae77Skettenis /* First, remove all the solib event breakpoints. Their addresses
479b725ae77Skettenis may have changed since the last time we ran the program. */
480b725ae77Skettenis remove_solib_event_breakpoints ();
481b725ae77Skettenis
482b725ae77Skettenis if (symfile_objfile == NULL)
483b725ae77Skettenis return;
484b725ae77Skettenis
485b725ae77Skettenis /* First see if the objfile was dynamically linked. */
486b725ae77Skettenis shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic");
487b725ae77Skettenis if (!shlib_info)
488b725ae77Skettenis return;
489b725ae77Skettenis
490b725ae77Skettenis /* It's got a .dynamic section, make sure it's not empty. */
491b725ae77Skettenis if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
492b725ae77Skettenis return;
493b725ae77Skettenis
494b725ae77Skettenis /* Read in the .dynamic section. */
495b725ae77Skettenis if (! read_dynamic_info (shlib_info, &dld_cache))
496b725ae77Skettenis error ("Unable to read the .dynamic section.");
497b725ae77Skettenis
498b725ae77Skettenis /* Turn on the flags we care about. */
499b725ae77Skettenis dld_cache.dld_flags |= DT_HP_DEBUG_PRIVATE;
500b725ae77Skettenis dld_cache.dld_flags |= DT_HP_DEBUG_CALLBACK;
501b725ae77Skettenis status = target_write_memory (dld_cache.dld_flags_addr,
502b725ae77Skettenis (char *) &dld_cache.dld_flags,
503b725ae77Skettenis sizeof (dld_cache.dld_flags));
504b725ae77Skettenis if (status != 0)
505b725ae77Skettenis error ("Unable to modify dynamic linker flags.");
506b725ae77Skettenis
507b725ae77Skettenis /* Now we have to create a shared library breakpoint in the dynamic
508b725ae77Skettenis linker. This can be somewhat tricky since the symbol is inside
509b725ae77Skettenis the dynamic linker (for which we do not have symbols or a base
510b725ae77Skettenis load address! Luckily I wrote this code for solib.c years ago. */
511b725ae77Skettenis interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
512b725ae77Skettenis if (interp_sect)
513b725ae77Skettenis {
514b725ae77Skettenis unsigned int interp_sect_size;
515b725ae77Skettenis char *buf;
516b725ae77Skettenis CORE_ADDR load_addr;
517b725ae77Skettenis bfd *tmp_bfd;
518b725ae77Skettenis CORE_ADDR sym_addr = 0;
519b725ae77Skettenis
520b725ae77Skettenis /* Read the contents of the .interp section into a local buffer;
521b725ae77Skettenis the contents specify the dynamic linker this program uses. */
522b725ae77Skettenis interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
523b725ae77Skettenis buf = alloca (interp_sect_size);
524b725ae77Skettenis bfd_get_section_contents (exec_bfd, interp_sect,
525b725ae77Skettenis buf, 0, interp_sect_size);
526b725ae77Skettenis
527b725ae77Skettenis /* Now we need to figure out where the dynamic linker was
528b725ae77Skettenis loaded so that we can load its symbols and place a breakpoint
529b725ae77Skettenis in the dynamic linker itself.
530b725ae77Skettenis
531b725ae77Skettenis This address is stored on the stack. However, I've been unable
532b725ae77Skettenis to find any magic formula to find it for Solaris (appears to
533b725ae77Skettenis be trivial on GNU/Linux). Therefore, we have to try an alternate
534b725ae77Skettenis mechanism to find the dynamic linker's base address. */
535b725ae77Skettenis tmp_bfd = bfd_openr (buf, gnutarget);
536b725ae77Skettenis if (tmp_bfd == NULL)
537b725ae77Skettenis goto get_out;
538b725ae77Skettenis
539b725ae77Skettenis /* Make sure the dynamic linker's really a useful object. */
540b725ae77Skettenis if (!bfd_check_format (tmp_bfd, bfd_object))
541b725ae77Skettenis {
542b725ae77Skettenis warning ("Unable to grok dynamic linker %s as an object file", buf);
543b725ae77Skettenis bfd_close (tmp_bfd);
544b725ae77Skettenis goto get_out;
545b725ae77Skettenis }
546b725ae77Skettenis
547b725ae77Skettenis /* We find the dynamic linker's base address by examining the
548b725ae77Skettenis current pc (which point at the entry point for the dynamic
549b725ae77Skettenis linker) and subtracting the offset of the entry point.
550b725ae77Skettenis
551b725ae77Skettenis Also note the breakpoint is the second instruction in the
552b725ae77Skettenis routine. */
553b725ae77Skettenis load_addr = read_pc () - tmp_bfd->start_address;
554b725ae77Skettenis sym_addr = bfd_lookup_symbol (tmp_bfd, "__dld_break");
555b725ae77Skettenis sym_addr = load_addr + sym_addr + 4;
556b725ae77Skettenis
557b725ae77Skettenis /* Create the shared library breakpoint. */
558b725ae77Skettenis {
559b725ae77Skettenis struct breakpoint *b
560b725ae77Skettenis = create_solib_event_breakpoint (sym_addr);
561b725ae77Skettenis
562b725ae77Skettenis /* The breakpoint is actually hard-coded into the dynamic linker,
563b725ae77Skettenis so we don't need to actually insert a breakpoint instruction
564b725ae77Skettenis there. In fact, the dynamic linker's code is immutable, even to
565b725ae77Skettenis ttrace, so we shouldn't even try to do that. For cases like
566b725ae77Skettenis this, we have "permanent" breakpoints. */
567b725ae77Skettenis make_breakpoint_permanent (b);
568b725ae77Skettenis }
569b725ae77Skettenis
570b725ae77Skettenis /* We're done with the temporary bfd. */
571b725ae77Skettenis bfd_close (tmp_bfd);
572b725ae77Skettenis }
573b725ae77Skettenis
574b725ae77Skettenis get_out:
575b725ae77Skettenis /* Wipe out all knowledge of old shared libraries since their
576b725ae77Skettenis mapping can change from one exec to another! */
577b725ae77Skettenis while (so_list_head)
578b725ae77Skettenis {
579b725ae77Skettenis struct so_list *temp;
580b725ae77Skettenis
581b725ae77Skettenis temp = so_list_head;
582b725ae77Skettenis xfree (so_list_head);
583b725ae77Skettenis so_list_head = temp->next;
584b725ae77Skettenis }
585b725ae77Skettenis clear_symtab_users ();
586b725ae77Skettenis }
587b725ae77Skettenis
588b725ae77Skettenis /* This operation removes the "hook" between GDB and the dynamic linker,
589b725ae77Skettenis which causes the dld to notify GDB of shared library events.
590b725ae77Skettenis
591b725ae77Skettenis After this operation completes, the dld will no longer notify GDB of
592b725ae77Skettenis shared library events. To resume notifications, GDB must call
593b725ae77Skettenis pa64_solib_create_inferior_hook.
594b725ae77Skettenis
595b725ae77Skettenis This operation does not remove any knowledge of shared libraries which
596b725ae77Skettenis GDB may already have been notified of. */
597b725ae77Skettenis
598b725ae77Skettenis void
pa64_solib_remove_inferior_hook(int pid)599b725ae77Skettenis pa64_solib_remove_inferior_hook (int pid)
600b725ae77Skettenis {
601b725ae77Skettenis /* Turn off the DT_HP_DEBUG_CALLBACK bit in the dynamic linker flags. */
602b725ae77Skettenis dld_cache.dld_flags &= ~DT_HP_DEBUG_CALLBACK;
603b725ae77Skettenis target_write_memory (dld_cache.dld_flags_addr,
604b725ae77Skettenis (char *)&dld_cache.dld_flags,
605b725ae77Skettenis sizeof (dld_cache.dld_flags));
606b725ae77Skettenis }
607b725ae77Skettenis
608b725ae77Skettenis /* This function creates a breakpoint on the dynamic linker hook, which
609b725ae77Skettenis is called when e.g., a shl_load or shl_unload call is made. This
610b725ae77Skettenis breakpoint will only trigger when a shl_load call is made.
611b725ae77Skettenis
612b725ae77Skettenis If filename is NULL, then loads of any dll will be caught. Else,
613b725ae77Skettenis only loads of the file whose pathname is the string contained by
614b725ae77Skettenis filename will be caught.
615b725ae77Skettenis
616b725ae77Skettenis Undefined behaviour is guaranteed if this function is called before
617b725ae77Skettenis pa64_solib_create_inferior_hook. */
618b725ae77Skettenis
619b725ae77Skettenis void
pa64_solib_create_catch_load_hook(int pid,int tempflag,char * filename,char * cond_string)620b725ae77Skettenis pa64_solib_create_catch_load_hook (int pid, int tempflag, char *filename,
621b725ae77Skettenis char *cond_string)
622b725ae77Skettenis {
623b725ae77Skettenis create_solib_load_event_breakpoint ("", tempflag, filename, cond_string);
624b725ae77Skettenis }
625b725ae77Skettenis
626b725ae77Skettenis /* This function creates a breakpoint on the dynamic linker hook, which
627b725ae77Skettenis is called when e.g., a shl_load or shl_unload call is made. This
628b725ae77Skettenis breakpoint will only trigger when a shl_unload call is made.
629b725ae77Skettenis
630b725ae77Skettenis If filename is NULL, then unloads of any dll will be caught. Else,
631b725ae77Skettenis only unloads of the file whose pathname is the string contained by
632b725ae77Skettenis filename will be caught.
633b725ae77Skettenis
634b725ae77Skettenis Undefined behaviour is guaranteed if this function is called before
635b725ae77Skettenis pa64_solib_create_inferior_hook. */
636b725ae77Skettenis
637b725ae77Skettenis void
pa64_solib_create_catch_unload_hook(int pid,int tempflag,char * filename,char * cond_string)638b725ae77Skettenis pa64_solib_create_catch_unload_hook (int pid, int tempflag, char *filename,
639b725ae77Skettenis char *cond_string)
640b725ae77Skettenis {
641b725ae77Skettenis create_solib_unload_event_breakpoint ("", tempflag, filename, cond_string);
642b725ae77Skettenis }
643b725ae77Skettenis
644b725ae77Skettenis /* Return nonzero if the dynamic linker has reproted that a library
645b725ae77Skettenis has been loaded. */
646b725ae77Skettenis
647b725ae77Skettenis int
pa64_solib_have_load_event(int pid)648b725ae77Skettenis pa64_solib_have_load_event (int pid)
649b725ae77Skettenis {
650b725ae77Skettenis CORE_ADDR event_kind;
651b725ae77Skettenis
652*11efff7fSkettenis event_kind = read_register (HPPA_ARG0_REGNUM);
653b725ae77Skettenis return (event_kind == DLD_CB_LOAD);
654b725ae77Skettenis }
655b725ae77Skettenis
656b725ae77Skettenis /* Return nonzero if the dynamic linker has reproted that a library
657b725ae77Skettenis has been unloaded. */
658b725ae77Skettenis int
pa64_solib_have_unload_event(int pid)659b725ae77Skettenis pa64_solib_have_unload_event (int pid)
660b725ae77Skettenis {
661b725ae77Skettenis CORE_ADDR event_kind;
662b725ae77Skettenis
663*11efff7fSkettenis event_kind = read_register (HPPA_ARG0_REGNUM);
664b725ae77Skettenis return (event_kind == DLD_CB_UNLOAD);
665b725ae77Skettenis }
666b725ae77Skettenis
667b725ae77Skettenis /* Return a pointer to a string indicating the pathname of the most
668b725ae77Skettenis recently loaded library.
669b725ae77Skettenis
670b725ae77Skettenis The caller is reposible for copying the string before the inferior is
671b725ae77Skettenis restarted. */
672b725ae77Skettenis
673b725ae77Skettenis char *
pa64_solib_loaded_library_pathname(int pid)674b725ae77Skettenis pa64_solib_loaded_library_pathname (int pid)
675b725ae77Skettenis {
676b725ae77Skettenis static char dll_path[MAXPATHLEN];
677*11efff7fSkettenis CORE_ADDR dll_path_addr = read_register (HPPA_ARG3_REGNUM);
678b725ae77Skettenis read_memory_string (dll_path_addr, dll_path, MAXPATHLEN);
679b725ae77Skettenis return dll_path;
680b725ae77Skettenis }
681b725ae77Skettenis
682b725ae77Skettenis /* Return a pointer to a string indicating the pathname of the most
683b725ae77Skettenis recently unloaded library.
684b725ae77Skettenis
685b725ae77Skettenis The caller is reposible for copying the string before the inferior is
686b725ae77Skettenis restarted. */
687b725ae77Skettenis
688b725ae77Skettenis char *
pa64_solib_unloaded_library_pathname(int pid)689b725ae77Skettenis pa64_solib_unloaded_library_pathname (int pid)
690b725ae77Skettenis {
691b725ae77Skettenis static char dll_path[MAXPATHLEN];
692*11efff7fSkettenis CORE_ADDR dll_path_addr = read_register (HPPA_ARG3_REGNUM);
693b725ae77Skettenis read_memory_string (dll_path_addr, dll_path, MAXPATHLEN);
694b725ae77Skettenis return dll_path;
695b725ae77Skettenis }
696b725ae77Skettenis
697b725ae77Skettenis /* Return nonzero if PC is an address inside the dynamic linker. */
698b725ae77Skettenis
699b725ae77Skettenis int
pa64_solib_in_dynamic_linker(int pid,CORE_ADDR pc)700b725ae77Skettenis pa64_solib_in_dynamic_linker (int pid, CORE_ADDR pc)
701b725ae77Skettenis {
702b725ae77Skettenis asection *shlib_info;
703b725ae77Skettenis
704b725ae77Skettenis if (symfile_objfile == NULL)
705b725ae77Skettenis return 0;
706b725ae77Skettenis
707b725ae77Skettenis if (!dld_cache.have_read_dld_descriptor)
708b725ae77Skettenis if (!read_dld_descriptor (¤t_target, auto_solib_add))
709b725ae77Skettenis return 0;
710b725ae77Skettenis
711b725ae77Skettenis return (pc >= dld_cache.dld_desc.text_base
712b725ae77Skettenis && pc < dld_cache.dld_desc.text_base + dld_cache.dld_desc.text_size);
713b725ae77Skettenis }
714b725ae77Skettenis
715b725ae77Skettenis
716b725ae77Skettenis /* Return the GOT value for the shared library in which ADDR belongs. If
717b725ae77Skettenis ADDR isn't in any known shared library, return zero. */
718b725ae77Skettenis
719b725ae77Skettenis CORE_ADDR
pa64_solib_get_got_by_pc(CORE_ADDR addr)720b725ae77Skettenis pa64_solib_get_got_by_pc (CORE_ADDR addr)
721b725ae77Skettenis {
722b725ae77Skettenis struct so_list *so_list = so_list_head;
723b725ae77Skettenis CORE_ADDR got_value = 0;
724b725ae77Skettenis
725b725ae77Skettenis while (so_list)
726b725ae77Skettenis {
727b725ae77Skettenis if (so_list->pa64_solib_desc.text_base <= addr
728b725ae77Skettenis && ((so_list->pa64_solib_desc.text_base
729b725ae77Skettenis + so_list->pa64_solib_desc.text_size)
730b725ae77Skettenis > addr))
731b725ae77Skettenis {
732b725ae77Skettenis got_value = so_list->pa64_solib_desc.linkage_ptr;
733b725ae77Skettenis break;
734b725ae77Skettenis }
735b725ae77Skettenis so_list = so_list->next;
736b725ae77Skettenis }
737b725ae77Skettenis return got_value;
738b725ae77Skettenis }
739b725ae77Skettenis
740b725ae77Skettenis /* Return the address of the handle of the shared library in which ADDR
741b725ae77Skettenis belongs. If ADDR isn't in any known shared library, return zero.
742b725ae77Skettenis
743b725ae77Skettenis This function is used in hppa_fix_call_dummy in hppa-tdep.c. */
744b725ae77Skettenis
745b725ae77Skettenis CORE_ADDR
pa64_solib_get_solib_by_pc(CORE_ADDR addr)746b725ae77Skettenis pa64_solib_get_solib_by_pc (CORE_ADDR addr)
747b725ae77Skettenis {
748b725ae77Skettenis struct so_list *so_list = so_list_head;
749b725ae77Skettenis CORE_ADDR retval = 0;
750b725ae77Skettenis
751b725ae77Skettenis while (so_list)
752b725ae77Skettenis {
753b725ae77Skettenis if (so_list->pa64_solib_desc.text_base <= addr
754b725ae77Skettenis && ((so_list->pa64_solib_desc.text_base
755b725ae77Skettenis + so_list->pa64_solib_desc.text_size)
756b725ae77Skettenis > addr))
757b725ae77Skettenis {
758b725ae77Skettenis retval = so_list->pa64_solib_desc_addr;
759b725ae77Skettenis break;
760b725ae77Skettenis }
761b725ae77Skettenis so_list = so_list->next;
762b725ae77Skettenis }
763b725ae77Skettenis return retval;
764b725ae77Skettenis }
765b725ae77Skettenis
766b725ae77Skettenis /* Dump information about all the currently loaded shared libraries. */
767b725ae77Skettenis
768b725ae77Skettenis static void
pa64_sharedlibrary_info_command(char * ignore,int from_tty)769b725ae77Skettenis pa64_sharedlibrary_info_command (char *ignore, int from_tty)
770b725ae77Skettenis {
771b725ae77Skettenis struct so_list *so_list = so_list_head;
772b725ae77Skettenis
773b725ae77Skettenis if (exec_bfd == NULL)
774b725ae77Skettenis {
775b725ae77Skettenis printf_unfiltered ("No executable file.\n");
776b725ae77Skettenis return;
777b725ae77Skettenis }
778b725ae77Skettenis
779b725ae77Skettenis if (so_list == NULL)
780b725ae77Skettenis {
781b725ae77Skettenis printf_unfiltered ("No shared libraries loaded at this time.\n");
782b725ae77Skettenis return;
783b725ae77Skettenis }
784b725ae77Skettenis
785b725ae77Skettenis printf_unfiltered ("Shared Object Libraries\n");
786b725ae77Skettenis printf_unfiltered (" %-19s%-19s%-19s%-19s\n",
787b725ae77Skettenis " text start", " text end",
788b725ae77Skettenis " data start", " data end");
789b725ae77Skettenis while (so_list)
790b725ae77Skettenis {
791b725ae77Skettenis unsigned int flags;
792b725ae77Skettenis
793b725ae77Skettenis printf_unfiltered ("%s", so_list->name);
794b725ae77Skettenis if (so_list->objfile == NULL)
795b725ae77Skettenis printf_unfiltered (" (symbols not loaded)");
796b725ae77Skettenis if (so_list->loaded == 0)
797b725ae77Skettenis printf_unfiltered (" (shared library unloaded)");
798b725ae77Skettenis printf_unfiltered (" %-18s",
799*11efff7fSkettenis hex_string_custom (so_list->pa64_solib_desc.linkage_ptr, 16));
800b725ae77Skettenis printf_unfiltered ("\n");
801b725ae77Skettenis printf_unfiltered ("%-18s",
802*11efff7fSkettenis hex_string_custom (so_list->pa64_solib_desc.text_base, 16));
803b725ae77Skettenis printf_unfiltered (" %-18s",
804*11efff7fSkettenis hex_string_custom ((so_list->pa64_solib_desc.text_base
805*11efff7fSkettenis + so_list->pa64_solib_desc.text_size), 16));
806b725ae77Skettenis printf_unfiltered (" %-18s",
807*11efff7fSkettenis hex_string_custom (so_list->pa64_solib_desc.data_base, 16));
808b725ae77Skettenis printf_unfiltered (" %-18s\n",
809*11efff7fSkettenis hex_string_custom ((so_list->pa64_solib_desc.data_base
810*11efff7fSkettenis + so_list->pa64_solib_desc.data_size), 16));
811b725ae77Skettenis so_list = so_list->next;
812b725ae77Skettenis }
813b725ae77Skettenis }
814b725ae77Skettenis
815b725ae77Skettenis /* Load up one or more shared libraries as directed by the user. */
816b725ae77Skettenis
817b725ae77Skettenis static void
pa64_solib_sharedlibrary_command(char * args,int from_tty)818b725ae77Skettenis pa64_solib_sharedlibrary_command (char *args, int from_tty)
819b725ae77Skettenis {
820b725ae77Skettenis dont_repeat ();
821b725ae77Skettenis pa64_solib_add (args, from_tty, (struct target_ops *) 0, 1);
822b725ae77Skettenis }
823b725ae77Skettenis
824b725ae77Skettenis /* Return the name of the shared library containing ADDR or NULL if ADDR
825b725ae77Skettenis is not contained in any known shared library. */
826b725ae77Skettenis
827b725ae77Skettenis char *
pa64_solib_address(CORE_ADDR addr)828b725ae77Skettenis pa64_solib_address (CORE_ADDR addr)
829b725ae77Skettenis {
830b725ae77Skettenis struct so_list *so = so_list_head;
831b725ae77Skettenis
832b725ae77Skettenis while (so)
833b725ae77Skettenis {
834b725ae77Skettenis /* Is this address within this shlib's text range? If so,
835b725ae77Skettenis return the shlib's name. */
836b725ae77Skettenis if (addr >= so->pa64_solib_desc.text_base
837b725ae77Skettenis && addr < (so->pa64_solib_desc.text_base
838b725ae77Skettenis | so->pa64_solib_desc.text_size))
839b725ae77Skettenis return so->name;
840b725ae77Skettenis
841b725ae77Skettenis /* Nope, keep looking... */
842b725ae77Skettenis so = so->next;
843b725ae77Skettenis }
844b725ae77Skettenis
845b725ae77Skettenis /* No, we couldn't prove that the address is within a shlib. */
846b725ae77Skettenis return NULL;
847b725ae77Skettenis }
848b725ae77Skettenis
849b725ae77Skettenis /* We are killing the inferior and restarting the program. */
850b725ae77Skettenis
851b725ae77Skettenis void
pa64_solib_restart(void)852b725ae77Skettenis pa64_solib_restart (void)
853b725ae77Skettenis {
854b725ae77Skettenis struct so_list *sl = so_list_head;
855b725ae77Skettenis
856b725ae77Skettenis /* Before the shlib info vanishes, use it to disable any breakpoints
857b725ae77Skettenis that may still be active in those shlibs. */
858b725ae77Skettenis disable_breakpoints_in_shlibs (0);
859b725ae77Skettenis
860b725ae77Skettenis /* Discard all the shlib descriptors. */
861b725ae77Skettenis while (sl)
862b725ae77Skettenis {
863b725ae77Skettenis struct so_list *next_sl = sl->next;
864b725ae77Skettenis xfree (sl);
865b725ae77Skettenis sl = next_sl;
866b725ae77Skettenis }
867b725ae77Skettenis so_list_head = NULL;
868b725ae77Skettenis
869b725ae77Skettenis pa64_solib_total_st_size = (LONGEST) 0;
870b725ae77Skettenis pa64_solib_st_size_threshold_exceeded = 0;
871b725ae77Skettenis
872b725ae77Skettenis dld_cache.is_valid = 0;
873b725ae77Skettenis dld_cache.have_read_dld_descriptor = 0;
874b725ae77Skettenis dld_cache.dld_flags_addr = 0;
875b725ae77Skettenis dld_cache.load_map = 0;
876b725ae77Skettenis dld_cache.load_map_addr = 0;
877b725ae77Skettenis dld_cache.dld_desc.data_base = 0;
878b725ae77Skettenis dld_cache.dld_flags = 0;
879b725ae77Skettenis dld_cache.dyninfo_sect = 0;
880b725ae77Skettenis }
881b725ae77Skettenis
882b725ae77Skettenis void
_initialize_pa64_solib(void)883b725ae77Skettenis _initialize_pa64_solib (void)
884b725ae77Skettenis {
885b725ae77Skettenis add_com ("sharedlibrary", class_files, pa64_solib_sharedlibrary_command,
886b725ae77Skettenis "Load shared object library symbols for files matching REGEXP.");
887b725ae77Skettenis add_info ("sharedlibrary", pa64_sharedlibrary_info_command,
888b725ae77Skettenis "Status of loaded shared object libraries.");
889b725ae77Skettenis
890*11efff7fSkettenis deprecated_add_show_from_set
891b725ae77Skettenis (add_set_cmd ("auto-solib-add", class_support, var_boolean,
892b725ae77Skettenis (char *) &auto_solib_add,
893b725ae77Skettenis "Set autoloading of shared library symbols.\n\
894b725ae77Skettenis If \"on\", symbols from all shared object libraries will be loaded\n\
895b725ae77Skettenis automatically when the inferior begins execution, when the dynamic linker\n\
896b725ae77Skettenis informs gdb that a new library has been loaded, or when attaching to the\n\
897b725ae77Skettenis inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
898b725ae77Skettenis &setlist),
899b725ae77Skettenis &showlist);
900b725ae77Skettenis
901*11efff7fSkettenis deprecated_add_show_from_set
902b725ae77Skettenis (add_set_cmd ("auto-solib-limit", class_support, var_zinteger,
903b725ae77Skettenis (char *) &auto_solib_limit,
904b725ae77Skettenis "Set threshold (in Mb) for autoloading shared library symbols.\n\
905b725ae77Skettenis When shared library autoloading is enabled, new libraries will be loaded\n\
906b725ae77Skettenis only until the total size of shared library symbols exceeds this\n\
907b725ae77Skettenis threshold in megabytes. Is ignored when using `sharedlibrary'.",
908b725ae77Skettenis &setlist),
909b725ae77Skettenis &showlist);
910b725ae77Skettenis
911b725ae77Skettenis /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how
912b725ae77Skettenis much data space a process can use. We ought to be reading
913b725ae77Skettenis MAXDSIZ and setting auto_solib_limit to some large fraction of
914b725ae77Skettenis that value. If not that, we maybe ought to be setting it smaller
915b725ae77Skettenis than the default for MAXDSIZ (that being 64Mb, I believe).
916b725ae77Skettenis However, [1] this threshold is only crudely approximated rather
917b725ae77Skettenis than actually measured, and [2] 50 Mbytes is too small for
918b725ae77Skettenis debugging gdb itself. Thus, the arbitrary 100 figure. */
919b725ae77Skettenis auto_solib_limit = 100; /* Megabytes */
920b725ae77Skettenis
921b725ae77Skettenis pa64_solib_restart ();
922b725ae77Skettenis }
923b725ae77Skettenis
924b725ae77Skettenis /* Get some HPUX-specific data from a shared lib. */
925b725ae77Skettenis CORE_ADDR
so_lib_thread_start_addr(struct so_list * so)926b725ae77Skettenis so_lib_thread_start_addr (struct so_list *so)
927b725ae77Skettenis {
928b725ae77Skettenis return so->pa64_solib_desc.tls_start_addr;
929b725ae77Skettenis }
930b725ae77Skettenis
931b725ae77Skettenis /* Read the dynamic linker's internal shared library descriptor.
932b725ae77Skettenis
933b725ae77Skettenis This must happen after dld starts running, so we can't do it in
934b725ae77Skettenis read_dynamic_info. Record the fact that we have loaded the
935b725ae77Skettenis descriptor. If the library is archive bound, then return zero, else
936b725ae77Skettenis return nonzero. */
937b725ae77Skettenis
938b725ae77Skettenis static int
read_dld_descriptor(struct target_ops * target,int readsyms)939b725ae77Skettenis read_dld_descriptor (struct target_ops *target, int readsyms)
940b725ae77Skettenis {
941b725ae77Skettenis char *dll_path;
942b725ae77Skettenis asection *dyninfo_sect;
943b725ae77Skettenis
944b725ae77Skettenis /* If necessary call read_dynamic_info to extract the contents of the
945b725ae77Skettenis .dynamic section from the shared library. */
946b725ae77Skettenis if (!dld_cache.is_valid)
947b725ae77Skettenis {
948b725ae77Skettenis if (symfile_objfile == NULL)
949b725ae77Skettenis error ("No object file symbols.");
950b725ae77Skettenis
951b725ae77Skettenis dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd,
952b725ae77Skettenis ".dynamic");
953b725ae77Skettenis if (!dyninfo_sect)
954b725ae77Skettenis {
955b725ae77Skettenis return 0;
956b725ae77Skettenis }
957b725ae77Skettenis
958b725ae77Skettenis if (!read_dynamic_info (dyninfo_sect, &dld_cache))
959b725ae77Skettenis error ("Unable to read in .dynamic section information.");
960b725ae77Skettenis }
961b725ae77Skettenis
962b725ae77Skettenis /* Read the load map pointer. */
963b725ae77Skettenis if (target_read_memory (dld_cache.load_map_addr,
964b725ae77Skettenis (char*) &dld_cache.load_map,
965b725ae77Skettenis sizeof(dld_cache.load_map))
966b725ae77Skettenis != 0)
967b725ae77Skettenis {
968b725ae77Skettenis error ("Error while reading in load map pointer.");
969b725ae77Skettenis }
970b725ae77Skettenis
971b725ae77Skettenis /* Read in the dld load module descriptor */
972b725ae77Skettenis if (dlgetmodinfo (-1,
973b725ae77Skettenis &dld_cache.dld_desc,
974b725ae77Skettenis sizeof(dld_cache.dld_desc),
975b725ae77Skettenis pa64_target_read_memory,
976b725ae77Skettenis 0,
977b725ae77Skettenis dld_cache.load_map)
978b725ae77Skettenis == 0)
979b725ae77Skettenis {
980b725ae77Skettenis error ("Error trying to get information about dynamic linker.");
981b725ae77Skettenis }
982b725ae77Skettenis
983b725ae77Skettenis /* Indicate that we have loaded the dld descriptor. */
984b725ae77Skettenis dld_cache.have_read_dld_descriptor = 1;
985b725ae77Skettenis
986b725ae77Skettenis /* Add dld.sl to the list of known shared libraries so that we can
987b725ae77Skettenis do unwind, etc.
988b725ae77Skettenis
989b725ae77Skettenis ?!? This may not be correct. Consider of dld.sl contains symbols
990b725ae77Skettenis which are also referenced/defined by the user program or some user
991b725ae77Skettenis shared library. We need to make absolutely sure that we do not
992b725ae77Skettenis pollute the namespace from GDB's point of view. */
993b725ae77Skettenis dll_path = dlgetname (&dld_cache.dld_desc,
994b725ae77Skettenis sizeof(dld_cache.dld_desc),
995b725ae77Skettenis pa64_target_read_memory,
996b725ae77Skettenis 0,
997b725ae77Skettenis dld_cache.load_map);
998b725ae77Skettenis add_to_solist(0, dll_path, readsyms, &dld_cache.dld_desc, 0, target);
999b725ae77Skettenis
1000b725ae77Skettenis return 1;
1001b725ae77Skettenis }
1002b725ae77Skettenis
1003b725ae77Skettenis /* Read the .dynamic section and extract the information of interest,
1004b725ae77Skettenis which is stored in dld_cache. The routine elf_locate_base in solib.c
1005b725ae77Skettenis was used as a model for this. */
1006b725ae77Skettenis
1007b725ae77Skettenis static int
read_dynamic_info(asection * dyninfo_sect,dld_cache_t * dld_cache_p)1008b725ae77Skettenis read_dynamic_info (asection *dyninfo_sect, dld_cache_t *dld_cache_p)
1009b725ae77Skettenis {
1010b725ae77Skettenis char *buf;
1011b725ae77Skettenis char *bufend;
1012b725ae77Skettenis CORE_ADDR dyninfo_addr;
1013b725ae77Skettenis int dyninfo_sect_size;
1014b725ae77Skettenis CORE_ADDR entry_addr;
1015b725ae77Skettenis
1016b725ae77Skettenis /* Read in .dynamic section, silently ignore errors. */
1017b725ae77Skettenis dyninfo_addr = bfd_section_vma (symfile_objfile->obfd, dyninfo_sect);
1018b725ae77Skettenis dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
1019b725ae77Skettenis buf = alloca (dyninfo_sect_size);
1020b725ae77Skettenis if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
1021b725ae77Skettenis return 0;
1022b725ae77Skettenis
1023b725ae77Skettenis /* Scan the .dynamic section and record the items of interest.
1024b725ae77Skettenis In particular, DT_HP_DLD_FLAGS */
1025b725ae77Skettenis for (bufend = buf + dyninfo_sect_size, entry_addr = dyninfo_addr;
1026b725ae77Skettenis buf < bufend;
1027b725ae77Skettenis buf += sizeof (Elf64_Dyn), entry_addr += sizeof (Elf64_Dyn))
1028b725ae77Skettenis {
1029b725ae77Skettenis Elf64_Dyn *x_dynp = (Elf64_Dyn*)buf;
1030b725ae77Skettenis Elf64_Sxword dyn_tag;
1031b725ae77Skettenis CORE_ADDR dyn_ptr;
1032b725ae77Skettenis char *pbuf;
1033b725ae77Skettenis
1034b725ae77Skettenis pbuf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
1035b725ae77Skettenis dyn_tag = bfd_h_get_64 (symfile_objfile->obfd,
1036b725ae77Skettenis (bfd_byte*) &x_dynp->d_tag);
1037b725ae77Skettenis
1038b725ae77Skettenis /* We can't use a switch here because dyn_tag is 64 bits and HP's
1039b725ae77Skettenis lame comiler does not handle 64bit items in switch statements. */
1040b725ae77Skettenis if (dyn_tag == DT_NULL)
1041b725ae77Skettenis break;
1042b725ae77Skettenis else if (dyn_tag == DT_HP_DLD_FLAGS)
1043b725ae77Skettenis {
1044b725ae77Skettenis /* Set dld_flags_addr and dld_flags in *dld_cache_p */
1045b725ae77Skettenis dld_cache_p->dld_flags_addr = entry_addr + offsetof(Elf64_Dyn, d_un);
1046b725ae77Skettenis if (target_read_memory (dld_cache_p->dld_flags_addr,
1047b725ae77Skettenis (char*) &dld_cache_p->dld_flags,
1048b725ae77Skettenis sizeof(dld_cache_p->dld_flags))
1049b725ae77Skettenis != 0)
1050b725ae77Skettenis {
1051b725ae77Skettenis error ("Error while reading in .dynamic section of the program.");
1052b725ae77Skettenis }
1053b725ae77Skettenis }
1054b725ae77Skettenis else if (dyn_tag == DT_HP_LOAD_MAP)
1055b725ae77Skettenis {
1056b725ae77Skettenis /* Dld will place the address of the load map at load_map_addr
1057b725ae77Skettenis after it starts running. */
1058b725ae77Skettenis if (target_read_memory (entry_addr + offsetof(Elf64_Dyn,
1059b725ae77Skettenis d_un.d_ptr),
1060b725ae77Skettenis (char*) &dld_cache_p->load_map_addr,
1061b725ae77Skettenis sizeof(dld_cache_p->load_map_addr))
1062b725ae77Skettenis != 0)
1063b725ae77Skettenis {
1064b725ae77Skettenis error ("Error while reading in .dynamic section of the program.");
1065b725ae77Skettenis }
1066b725ae77Skettenis }
1067b725ae77Skettenis else
1068b725ae77Skettenis {
1069b725ae77Skettenis /* tag is not of interest */
1070b725ae77Skettenis }
1071b725ae77Skettenis }
1072b725ae77Skettenis
1073b725ae77Skettenis /* Record other information and set is_valid to 1. */
1074b725ae77Skettenis dld_cache_p->dyninfo_sect = dyninfo_sect;
1075b725ae77Skettenis
1076b725ae77Skettenis /* Verify that we read in required info. These fields are re-set to zero
1077b725ae77Skettenis in pa64_solib_restart. */
1078b725ae77Skettenis
1079b725ae77Skettenis if (dld_cache_p->dld_flags_addr != 0 && dld_cache_p->load_map_addr != 0)
1080b725ae77Skettenis dld_cache_p->is_valid = 1;
1081b725ae77Skettenis else
1082b725ae77Skettenis return 0;
1083b725ae77Skettenis
1084b725ae77Skettenis return 1;
1085b725ae77Skettenis }
1086b725ae77Skettenis
1087b725ae77Skettenis /* Wrapper for target_read_memory to make dlgetmodinfo happy. */
1088b725ae77Skettenis
1089b725ae77Skettenis static void *
pa64_target_read_memory(void * buffer,CORE_ADDR ptr,size_t bufsiz,int ident)1090b725ae77Skettenis pa64_target_read_memory (void *buffer, CORE_ADDR ptr, size_t bufsiz, int ident)
1091b725ae77Skettenis {
1092b725ae77Skettenis if (target_read_memory (ptr, buffer, bufsiz) != 0)
1093b725ae77Skettenis return 0;
1094b725ae77Skettenis return buffer;
1095b725ae77Skettenis }
1096b725ae77Skettenis
1097b725ae77Skettenis /* Called from handle_dynlink_load_event and pa64_solib_add to add
1098b725ae77Skettenis a shared library to so_list_head list and possibly to read in the
1099b725ae77Skettenis debug information for the library.
1100b725ae77Skettenis
1101b725ae77Skettenis If load_module_desc_p is NULL, then the load module descriptor must
1102b725ae77Skettenis be read from the inferior process at the address load_module_desc_addr. */
1103b725ae77Skettenis
1104b725ae77Skettenis static void
add_to_solist(int from_tty,char * dll_path,int readsyms,struct load_module_desc * load_module_desc_p,CORE_ADDR load_module_desc_addr,struct target_ops * target)1105b725ae77Skettenis add_to_solist (int from_tty, char *dll_path, int readsyms,
1106b725ae77Skettenis struct load_module_desc *load_module_desc_p,
1107b725ae77Skettenis CORE_ADDR load_module_desc_addr, struct target_ops *target)
1108b725ae77Skettenis {
1109b725ae77Skettenis struct so_list *new_so, *so_list_tail;
1110b725ae77Skettenis int pa64_solib_st_size_threshhold_exceeded;
1111b725ae77Skettenis LONGEST st_size;
1112b725ae77Skettenis
1113b725ae77Skettenis if (symfile_objfile == NULL)
1114b725ae77Skettenis return;
1115b725ae77Skettenis
1116b725ae77Skettenis so_list_tail = so_list_head;
1117b725ae77Skettenis /* Find the end of the list of shared objects. */
1118b725ae77Skettenis while (so_list_tail && so_list_tail->next)
1119b725ae77Skettenis {
1120b725ae77Skettenis if (strcmp (so_list_tail->name, dll_path) == 0)
1121b725ae77Skettenis return;
1122b725ae77Skettenis so_list_tail = so_list_tail->next;
1123b725ae77Skettenis }
1124b725ae77Skettenis
1125b725ae77Skettenis if (so_list_tail && strcmp (so_list_tail->name, dll_path) == 0)
1126b725ae77Skettenis return;
1127b725ae77Skettenis
1128b725ae77Skettenis /* Add the shared library to the so_list_head list */
1129b725ae77Skettenis new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
1130b725ae77Skettenis memset ((char *)new_so, 0, sizeof (struct so_list));
1131b725ae77Skettenis if (so_list_head == NULL)
1132b725ae77Skettenis {
1133b725ae77Skettenis so_list_head = new_so;
1134b725ae77Skettenis so_list_tail = new_so;
1135b725ae77Skettenis }
1136b725ae77Skettenis else
1137b725ae77Skettenis {
1138b725ae77Skettenis so_list_tail->next = new_so;
1139b725ae77Skettenis so_list_tail = new_so;
1140b725ae77Skettenis }
1141b725ae77Skettenis
1142b725ae77Skettenis /* Initialize the new_so */
1143b725ae77Skettenis if (load_module_desc_p)
1144b725ae77Skettenis {
1145b725ae77Skettenis new_so->pa64_solib_desc = *load_module_desc_p;
1146b725ae77Skettenis }
1147b725ae77Skettenis else
1148b725ae77Skettenis {
1149b725ae77Skettenis if (target_read_memory (load_module_desc_addr,
1150b725ae77Skettenis (char*) &new_so->pa64_solib_desc,
1151b725ae77Skettenis sizeof(struct load_module_desc))
1152b725ae77Skettenis != 0)
1153b725ae77Skettenis {
1154b725ae77Skettenis error ("Error while reading in dynamic library %s", dll_path);
1155b725ae77Skettenis }
1156b725ae77Skettenis }
1157b725ae77Skettenis
1158b725ae77Skettenis new_so->pa64_solib_desc_addr = load_module_desc_addr;
1159b725ae77Skettenis new_so->loaded = 1;
1160b725ae77Skettenis new_so->name = obsavestring (dll_path, strlen(dll_path),
1161b725ae77Skettenis &symfile_objfile->objfile_obstack);
1162b725ae77Skettenis
1163b725ae77Skettenis /* If we are not going to load the library, tell the user if we
1164b725ae77Skettenis haven't already and return. */
1165b725ae77Skettenis
1166b725ae77Skettenis st_size = pa64_solib_sizeof_symbol_table (dll_path);
1167b725ae77Skettenis pa64_solib_st_size_threshhold_exceeded =
1168b725ae77Skettenis !from_tty
1169b725ae77Skettenis && readsyms
1170b725ae77Skettenis && ( (st_size + pa64_solib_total_st_size)
1171b725ae77Skettenis > (auto_solib_limit * (LONGEST) (1024 * 1024)));
1172b725ae77Skettenis if (pa64_solib_st_size_threshhold_exceeded)
1173b725ae77Skettenis {
1174b725ae77Skettenis pa64_solib_add_solib_objfile (new_so, dll_path, from_tty, 1);
1175b725ae77Skettenis return;
1176b725ae77Skettenis }
1177b725ae77Skettenis
1178b725ae77Skettenis /* Now read in debug info. */
1179b725ae77Skettenis pa64_solib_total_st_size += st_size;
1180b725ae77Skettenis
1181b725ae77Skettenis /* This fills in new_so->objfile, among others. */
1182b725ae77Skettenis pa64_solib_load_symbols (new_so,
1183b725ae77Skettenis dll_path,
1184b725ae77Skettenis from_tty,
1185b725ae77Skettenis 0,
1186b725ae77Skettenis target);
1187b725ae77Skettenis return;
1188b725ae77Skettenis }
1189b725ae77Skettenis
1190b725ae77Skettenis
1191b725ae77Skettenis /*
1192b725ae77Skettenis LOCAL FUNCTION
1193b725ae77Skettenis
1194b725ae77Skettenis bfd_lookup_symbol -- lookup the value for a specific symbol
1195b725ae77Skettenis
1196b725ae77Skettenis SYNOPSIS
1197b725ae77Skettenis
1198b725ae77Skettenis CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
1199b725ae77Skettenis
1200b725ae77Skettenis DESCRIPTION
1201b725ae77Skettenis
1202b725ae77Skettenis An expensive way to lookup the value of a single symbol for
1203b725ae77Skettenis bfd's that are only temporary anyway. This is used by the
1204b725ae77Skettenis shared library support to find the address of the debugger
1205b725ae77Skettenis interface structures in the shared library.
1206b725ae77Skettenis
1207b725ae77Skettenis Note that 0 is specifically allowed as an error return (no
1208b725ae77Skettenis such symbol).
1209b725ae77Skettenis */
1210b725ae77Skettenis
1211b725ae77Skettenis static CORE_ADDR
bfd_lookup_symbol(bfd * abfd,char * symname)1212b725ae77Skettenis bfd_lookup_symbol (bfd *abfd, char *symname)
1213b725ae77Skettenis {
1214b725ae77Skettenis unsigned int storage_needed;
1215b725ae77Skettenis asymbol *sym;
1216b725ae77Skettenis asymbol **symbol_table;
1217b725ae77Skettenis unsigned int number_of_symbols;
1218b725ae77Skettenis unsigned int i;
1219b725ae77Skettenis struct cleanup *back_to;
1220b725ae77Skettenis CORE_ADDR symaddr = 0;
1221b725ae77Skettenis
1222b725ae77Skettenis storage_needed = bfd_get_symtab_upper_bound (abfd);
1223b725ae77Skettenis
1224b725ae77Skettenis if (storage_needed > 0)
1225b725ae77Skettenis {
1226b725ae77Skettenis symbol_table = (asymbol **) xmalloc (storage_needed);
1227b725ae77Skettenis back_to = make_cleanup (xfree, symbol_table);
1228b725ae77Skettenis number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
1229b725ae77Skettenis
1230b725ae77Skettenis for (i = 0; i < number_of_symbols; i++)
1231b725ae77Skettenis {
1232b725ae77Skettenis sym = *symbol_table++;
1233b725ae77Skettenis if (strcmp (sym->name, symname) == 0)
1234b725ae77Skettenis {
1235b725ae77Skettenis /* Bfd symbols are section relative. */
1236b725ae77Skettenis symaddr = sym->value + sym->section->vma;
1237b725ae77Skettenis break;
1238b725ae77Skettenis }
1239b725ae77Skettenis }
1240b725ae77Skettenis do_cleanups (back_to);
1241b725ae77Skettenis }
1242b725ae77Skettenis return (symaddr);
1243b725ae77Skettenis }
1244b725ae77Skettenis
1245