/* Handle HP SOM shared libraries for GDB, the GNU Debugger.
- Copyright 1993, 1996, 1999 Free Software Foundation, Inc.
+
+ Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002,
+ 2003 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdb-stabs.h"
#include "gdb_stat.h"
#include "gdbcmd.h"
-#include "assert.h"
#include "language.h"
+#include "regcache.h"
+#include "gdb_assert.h"
#include <fcntl.h>
extern struct target_ops exec_ops;
/* This lives in hppa-tdep.c. */
-extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
+extern struct unwind_table_entry *find_unwind_entry (CORE_ADDR pc);
/* These ought to be defined in some public interface, but aren't. They
define the meaning of the various bits in the distinguished __dld_flags
/* TODO:
- * Most of this code should work for hp300 shared libraries. Does
- anyone care enough to weed out any SOM-isms.
-
* Support for hpux8 dynamic linker. */
/* The basic structure which describes a dynamically loaded object. This
shared objects on the so_list_head list. (When we say size, here
we mean of the information before it is brought into memory and
potentially expanded by GDB.) When adding a new shlib, this value
- is compared against the threshold size, held by auto_solib_add
+ is compared against the threshold size, held by auto_solib_limit
(in megabytes). If adding symbols for the new shlib would cause
- the total size to exceed the threshold, then the new shlib's symbols
- are not loaded.
- */
+ the total size to exceed the threshold, then the new shlib's
+ symbols are not loaded. */
static LONGEST som_solib_total_st_size;
/* When the threshold is reached for any shlib, we refuse to add
/* When adding fields, be sure to clear them in _initialize_som_solib. */
static struct
{
- boolean is_valid;
+ int is_valid;
addr_and_unwind_t hook;
addr_and_unwind_t hook_stub;
addr_and_unwind_t load;
-static void som_sharedlibrary_info_command PARAMS ((char *, int));
+static void som_sharedlibrary_info_command (char *, int);
-static void som_solib_sharedlibrary_command PARAMS ((char *, int));
+static void som_solib_sharedlibrary_command (char *, int);
static LONGEST
-som_solib_sizeof_symbol_table (filename)
- char *filename;
+som_solib_sizeof_symbol_table (char *filename)
{
bfd *abfd;
int desc;
if (!abfd)
{
close (desc);
- make_cleanup (free, filename);
+ make_cleanup (xfree, filename);
error ("\"%s\": can't open to read symbols: %s.", filename,
bfd_errmsg (bfd_get_error ()));
}
if (!bfd_check_format (abfd, bfd_object)) /* Reads in section info */
{
bfd_close (abfd); /* This also closes desc */
- make_cleanup (free, filename);
+ make_cleanup (xfree, filename);
error ("\"%s\": can't read symbols: %s.", filename,
bfd_errmsg (bfd_get_error ()));
}
st_size += (LONGEST) bfd_section_size (abfd, sect);
bfd_close (abfd); /* This also closes desc */
- free (filename);
+ xfree (filename);
/* Unfortunately, just summing the sizes of various debug info
sections isn't a very accurate measurement of how much heap
static void
-som_solib_add_solib_objfile (so, name, from_tty, text_addr)
- struct so_list *so;
- char *name;
- int from_tty;
- CORE_ADDR text_addr;
+som_solib_add_solib_objfile (struct so_list *so, char *name, int from_tty,
+ CORE_ADDR text_addr)
{
obj_private_data_t *obj_private;
- struct section_addr_info section_addrs;
+ struct obj_section *s;
- memset (§ion_addrs, 0, sizeof (section_addrs));
- section_addrs.other[0].name = ".text";
- section_addrs.other[0].addr = text_addr;
- so->objfile = symbol_file_add (name, from_tty, §ion_addrs, 0, OBJF_SHARED);
+ so->objfile = symbol_file_add (name, from_tty, NULL, 0, OBJF_SHARED);
so->abfd = so->objfile->obfd;
+ /* syms_from_objfile has bizarre section offset code,
+ so I do my own right here. */
+ for (s = so->objfile->sections; s < so->objfile->sections_end; s++)
+ {
+ flagword aflag = bfd_get_section_flags(so->abfd, s->the_bfd_section);
+ if (aflag & SEC_CODE)
+ {
+ s->addr += so->som_solib.text_addr - so->som_solib.text_link_addr;
+ s->endaddr += so->som_solib.text_addr - so->som_solib.text_link_addr;
+ }
+ else if (aflag & SEC_DATA)
+ {
+ s->addr += so->som_solib.data_start;
+ s->endaddr += so->som_solib.data_start;
+ }
+ else
+ ;
+ }
+
/* Mark this as a shared library and save private data.
*/
so->objfile->flags |= OBJF_SHARED;
sizeof (obj_private_data_t));
obj_private->unwind_info = NULL;
obj_private->so_info = NULL;
- so->objfile->obj_private = (PTR) obj_private;
+ so->objfile->obj_private = obj_private;
}
obj_private = (obj_private_data_t *) so->objfile->obj_private;
static void
-som_solib_load_symbols (so, name, from_tty, text_addr, target)
- struct so_list *so;
- char *name;
- int from_tty;
- CORE_ADDR text_addr;
- struct target_ops *target;
+som_solib_load_symbols (struct so_list *so, char *name, int from_tty,
+ CORE_ADDR text_addr, struct target_ops *target)
{
struct section_table *p;
int status;
{
if (p->the_bfd_section->flags & SEC_CODE)
{
- p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
- p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
+ p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
+ p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
}
else if (p->the_bfd_section->flags & SEC_DATA)
{
- p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
- p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
+ p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
+ p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
}
}
}
+/* FIXME: cagney/2003-02-01: This just isn't right. Given an address
+ within the target's address space, this converts the value into an
+ address within the host's (i.e., GDB's) address space. Given that
+ the host/target address spaces are separate, this can't be right. */
+
+static void *
+hpux_address_to_host_pointer_hack (CORE_ADDR addr)
+{
+ void *ptr;
+
+ gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
+ ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+ return ptr;
+}
+
/* Add symbols from shared libraries into the symtab list, unless the
- size threshold (specified by auto_solib_add, in megabytes) would
+ size threshold specified by auto_solib_limit (in megabytes) would
be exceeded. */
void
-som_solib_add (arg_string, from_tty, target)
- char *arg_string;
- int from_tty;
- struct target_ops *target;
+som_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
{
struct minimal_symbol *msymbol;
struct so_list *so_list_tail;
int threshold_warning_given = 0;
/* First validate our arguments. */
- if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ re_err = re_comp (arg_string ? arg_string : ".");
+ if (re_err != NULL)
{
error ("Invalid regexp: %s", re_err);
}
if (status != 0)
goto err;
- new_so->som_solib.next = (void *) extract_unsigned_integer (buf, 4);
+ /* FIXME: cagney/2003-02-01: I think som_solib.next should be a
+ CORE_ADDR. */
+ new_so->som_solib.next =
+ hpux_address_to_host_pointer_hack (extract_unsigned_integer (buf, 4));
/* Note that we don't re-set "addr" to the next pointer
* until after we've read the trailing data.
st_size = som_solib_sizeof_symbol_table (name);
som_solib_st_size_threshold_exceeded =
!from_tty &&
- ((st_size + som_solib_total_st_size) > (auto_solib_add * (LONGEST) 1000000));
+ auto_solib_limit > 0 &&
+ readsyms &&
+ ((st_size + som_solib_total_st_size) > (auto_solib_limit * (LONGEST) (1024 * 1024)));
if (som_solib_st_size_threshold_exceeded)
{
if (!threshold_warning_given)
- warning ("Symbols for some libraries have not been loaded, because\ndoing so would exceed the size threshold specified by auto-solib-add.\nTo manually load symbols, use the 'sharedlibrary' command.\nTo raise the threshold, set auto-solib-add to a larger value and rerun\nthe program.\n");
+ warning ("Symbols for some libraries have not been loaded, because\ndoing so would exceed the size threshold specified by auto-solib-limit.\nTo manually load symbols, use the 'sharedlibrary' command.\nTo raise the threshold, set auto-solib-limit to a larger value and rerun\nthe program.\n");
threshold_warning_given = 1;
/* We'll still make note of this shlib, even if we don't
means running until the "_start" is called. */
void
-som_solib_create_inferior_hook ()
+som_solib_create_inferior_hook (void)
{
struct minimal_symbol *msymbol;
unsigned int dld_flags, status, have_endo;
return;
have_endo = 0;
- /* Slam the pid of the process into __d_pid; failing is only a warning! */
+ /* Slam the pid of the process into __d_pid.
+
+ We used to warn when this failed, but that warning is only useful
+ on very old HP systems (hpux9 and older). The warnings are an
+ annoyance to users of modern systems and foul up the testsuite as
+ well. As a result, the warnings have been disabled. */
msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
if (msymbol == NULL)
- {
- warning ("Unable to find __d_pid symbol in object file.");
- warning ("Suggest linking with /opt/langtools/lib/end.o.");
- warning ("GDB will be unable to track shl_load/shl_unload calls");
- goto keep_going;
- }
+ goto keep_going;
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
- store_unsigned_integer (buf, 4, inferior_pid);
+ store_unsigned_integer (buf, 4, PIDGET (inferior_ptid));
status = target_write_memory (anaddr, buf, 4);
if (status != 0)
{
struct minimal_symbol *msymbol2;
/* What a crock. */
- msymbol2 = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
+ msymbol2 = lookup_minimal_symbol_solib_trampoline (DEPRECATED_SYMBOL_NAME (msymbol),
NULL, objfile);
/* Found a symbol with the right name. */
if (msymbol2)
struct so_list *temp;
temp = so_list_head;
- free (so_list_head);
+ xfree (so_list_head);
so_list_head = temp->next;
}
clear_symtab_users ();
}
-
-static void
-reset_inferior_pid (saved_inferior_pid)
- int saved_inferior_pid;
-{
- inferior_pid = saved_inferior_pid;
-}
-
-
/* This operation removes the "hook" between GDB and the dynamic linker,
which causes the dld to notify GDB of shared library events.
GDB may already have been notified of.
*/
void
-som_solib_remove_inferior_hook (pid)
- int pid;
+som_solib_remove_inferior_hook (int pid)
{
CORE_ADDR addr;
struct minimal_symbol *msymbol;
int status;
char dld_flags_buffer[TARGET_INT_BIT / TARGET_CHAR_BIT];
unsigned int dld_flags_value;
- int saved_inferior_pid = inferior_pid;
- struct cleanup *old_cleanups = make_cleanup (reset_inferior_pid, saved_inferior_pid);
+ struct cleanup *old_cleanups = save_inferior_ptid ();
/* Ensure that we're really operating on the specified process. */
- inferior_pid = pid;
+ inferior_ptid = pid_to_ptid (pid);
/* We won't bother to remove the solib breakpoints from this process.
som_solib_create_inferior_hook.
*/
void
-som_solib_create_catch_load_hook (pid, tempflag, filename, cond_string)
- int pid;
- int tempflag;
- char *filename;
- char *cond_string;
+som_solib_create_catch_load_hook (int pid, int tempflag, char *filename,
+ char *cond_string)
{
create_solib_load_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
}
som_solib_create_inferior_hook.
*/
void
-som_solib_create_catch_unload_hook (pid, tempflag, filename, cond_string)
- int pid;
- int tempflag;
- char *filename;
- char *cond_string;
+som_solib_create_catch_unload_hook (int pid, int tempflag, char *filename,
+ char *cond_string)
{
create_solib_unload_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
}
int
-som_solib_have_load_event (pid)
- int pid;
+som_solib_have_load_event (int pid)
{
CORE_ADDR event_kind;
}
int
-som_solib_have_unload_event (pid)
- int pid;
+som_solib_have_unload_event (int pid)
{
CORE_ADDR event_kind;
}
static char *
-som_solib_library_pathname (pid)
- int pid;
+som_solib_library_pathname (int pid)
{
CORE_ADDR dll_handle_address;
CORE_ADDR dll_pathname_address;
}
char *
-som_solib_loaded_library_pathname (pid)
- int pid;
+som_solib_loaded_library_pathname (int pid)
{
if (!som_solib_have_load_event (pid))
error ("Must have a load event to use this query");
}
char *
-som_solib_unloaded_library_pathname (pid)
- int pid;
+som_solib_unloaded_library_pathname (int pid)
{
if (!som_solib_have_unload_event (pid))
error ("Must have an unload event to use this query");
}
static void
-som_solib_desire_dynamic_linker_symbols ()
+som_solib_desire_dynamic_linker_symbols (void)
{
struct objfile *objfile;
struct unwind_table_entry *u;
}
/* Did we find everything we were looking for? If so, stop. */
- if ((dld_cache.load.address != NULL) && (dld_cache.load_stub.address != NULL)
- && (dld_cache.unload.address != NULL) && (dld_cache.unload_stub.address != NULL))
+ if ((dld_cache.load.address != 0)
+ && (dld_cache.load_stub.address != 0)
+ && (dld_cache.unload.address != 0)
+ && (dld_cache.unload_stub.address != 0))
{
dld_cache.is_valid = 1;
break;
}
int
-som_solib_in_dynamic_linker (pid, pc)
- int pid;
- CORE_ADDR pc;
+som_solib_in_dynamic_linker (int pid, CORE_ADDR pc)
{
struct unwind_table_entry *u_pc;
ADDR isn't in any known shared library, return zero. */
CORE_ADDR
-som_solib_get_got_by_pc (addr)
- CORE_ADDR addr;
+som_solib_get_got_by_pc (CORE_ADDR addr)
{
struct so_list *so_list = so_list_head;
CORE_ADDR got_value = 0;
/* this function is used in hppa_fix_call_dummy in hppa-tdep.c */
CORE_ADDR
-som_solib_get_solib_by_pc (addr)
- CORE_ADDR addr;
+som_solib_get_solib_by_pc (CORE_ADDR addr)
{
struct so_list *so_list = so_list_head;
int
-som_solib_section_offsets (objfile, offsets)
- struct objfile *objfile;
- struct section_offsets *offsets;
+som_solib_section_offsets (struct objfile *objfile,
+ struct section_offsets *offsets)
{
struct so_list *so_list = so_list_head;
asection *private_section;
/* The text offset is easy. */
- ANOFFSET (offsets, SECT_OFF_TEXT)
+ offsets->offsets[SECT_OFF_TEXT (objfile)]
= (so_list->som_solib.text_addr
- so_list->som_solib.text_link_addr);
- ANOFFSET (offsets, SECT_OFF_RODATA)
- = ANOFFSET (offsets, SECT_OFF_TEXT);
+ offsets->offsets[SECT_OFF_RODATA (objfile)]
+ = ANOFFSET (offsets, SECT_OFF_TEXT (objfile));
/* We should look at presumed_dp in the SOM header, but
that's not easily available. This should be OK though. */
if (!private_section)
{
warning ("Unable to find $PRIVATE$ in shared library!");
- ANOFFSET (offsets, SECT_OFF_DATA) = 0;
- ANOFFSET (offsets, SECT_OFF_BSS) = 0;
+ offsets->offsets[SECT_OFF_DATA (objfile)] = 0;
+ offsets->offsets[SECT_OFF_BSS (objfile)] = 0;
return 1;
}
- ANOFFSET (offsets, SECT_OFF_DATA)
+ offsets->offsets[SECT_OFF_DATA (objfile)]
= (so_list->som_solib.data_start - private_section->vma);
- ANOFFSET (offsets, SECT_OFF_BSS)
- = ANOFFSET (offsets, SECT_OFF_DATA);
+ offsets->offsets[SECT_OFF_BSS (objfile)]
+ = ANOFFSET (offsets, SECT_OFF_DATA (objfile));
return 1;
}
so_list = so_list->next;
/* Dump information about all the currently loaded shared libraries. */
static void
-som_sharedlibrary_info_command (ignore, from_tty)
- char *ignore;
- int from_tty;
+som_sharedlibrary_info_command (char *ignore, int from_tty)
{
struct so_list *so_list = so_list_head;
}
static void
-som_solib_sharedlibrary_command (args, from_tty)
- char *args;
- int from_tty;
+som_solib_sharedlibrary_command (char *args, int from_tty)
{
dont_repeat ();
- som_solib_add (args, from_tty, (struct target_ops *) 0);
+ som_solib_add (args, from_tty, (struct target_ops *) 0, 1);
}
char *
-som_solib_address (addr)
- CORE_ADDR addr;
+som_solib_address (CORE_ADDR addr)
{
struct so_list *so = so_list_head;
void
-som_solib_restart ()
+som_solib_restart (void)
{
struct so_list *sl = so_list_head;
while (sl)
{
struct so_list *next_sl = sl->next;
- free (sl);
+ xfree (sl);
sl = next_sl;
}
so_list_head = NULL;
}
+/* LOCAL FUNCTION
+
+ no_shared_libraries -- handle command to explicitly discard symbols
+ from shared libraries.
+
+ DESCRIPTION
+
+ Implements the command "nosharedlibrary", which discards symbols
+ that have been auto-loaded from shared libraries. Symbols from
+ shared libraries that were added by explicit request of the user
+ are not discarded. Also called from remote.c. */
+
+void
+no_shared_libraries (char *ignored, int from_tty)
+{
+ /* FIXME */
+}
+
void
-_initialize_som_solib ()
+_initialize_som_solib (void)
{
add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
add_info ("sharedlibrary", som_sharedlibrary_info_command,
"Status of loaded shared object libraries.");
+
add_show_from_set
- (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (add_set_cmd ("auto-solib-add", class_support, var_boolean,
(char *) &auto_solib_add,
- "Set autoloading size threshold (in megabytes) of shared library symbols.\n\
-If nonzero, symbols from all shared object libraries will be loaded\n\
-automatically when the inferior begins execution or when the dynamic linker\n\
-informs gdb that a new library has been loaded, until the symbol table\n\
-of the program and libraries exceeds this threshold.\n\
-Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
+ "Set autoloading of shared library symbols.\n\
+If \"on\", symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution, when the dynamic linker\n\
+informs gdb that a new library has been loaded, or when attaching to the\n\
+inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
&setlist),
&showlist);
- /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how much
- data space a process can use. We ought to be reading MAXDSIZ and
- setting auto_solib_add to some large fraction of that value. If
- not that, we maybe ought to be setting it smaller than the default
- for MAXDSIZ (that being 64Mb, I believe). However, [1] this threshold
- is only crudely approximated rather than actually measured, and [2]
- 50 Mbytes is too small for debugging gdb itself. Thus, the arbitrary
- 100 figure.
- */
- auto_solib_add = 100; /* Megabytes */
+ add_show_from_set
+ (add_set_cmd ("auto-solib-limit", class_support, var_zinteger,
+ (char *) &auto_solib_limit,
+ "Set threshold (in Mb) for autoloading shared library symbols.\n\
+When shared library autoloading is enabled, new libraries will be loaded\n\
+only until the total size of shared library symbols exceeds this\n\
+threshold in megabytes. Is ignored when using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+
+ /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how
+ much data space a process can use. We ought to be reading
+ MAXDSIZ and setting auto_solib_limit to some large fraction of
+ that value. If not that, we maybe ought to be setting it smaller
+ than the default for MAXDSIZ (that being 64Mb, I believe).
+ However, [1] this threshold is only crudely approximated rather
+ than actually measured, and [2] 50 Mbytes is too small for
+ debugging gdb itself. Thus, the arbitrary 100 figure. */
+ auto_solib_limit = 100; /* Megabytes */
som_solib_restart ();
}
/* Get some HPUX-specific data from a shared lib.
*/
CORE_ADDR
-so_lib_thread_start_addr (so)
- struct so_list *so;
+so_lib_thread_start_addr (struct so_list *so)
{
return so->som_solib.tsd_start_addr;
}