aboutsummaryrefslogtreecommitdiff
path: root/gdb/somsolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/somsolib.c')
-rw-r--r--gdb/somsolib.c316
1 files changed, 280 insertions, 36 deletions
diff --git a/gdb/somsolib.c b/gdb/somsolib.c
index 0418bd9..f75ad9c 100644
--- a/gdb/somsolib.c
+++ b/gdb/somsolib.c
@@ -1,6 +1,6 @@
/* Handle HP SOM shared libraries for GDB, the GNU Debugger.
Copyright 1993 Free Software Foundation, Inc.
-
+
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
@@ -34,16 +34,31 @@ and by Cygnus Support. */
#include "objfiles.h"
#include "inferior.h"
-/* We don't currently use this structure, but it isn't documented anywhere,
- and we'll likely need it in som_solib_add as more shared library support
- is added. */
+/* TODO:
+
+ * Relocate data addresses in the shared library.
+
+ * Most of this code should work for hp300 shared libraries. Does
+ anyone care enough to weed out any SOM-isms.
+
+ * Do we need/want a command to load a shared library?
+
+ * Test attaching to running dynamically linked code.
+
+ * Support for hpux8 dynamic linker.
+
+ * Support for tracking user calls to dld_load, dld_unload. */
+
+/* The basic structure which describes a dynamically loaded object. This
+ data structure is private to the dynamic linker and isn't found in
+ any HPUX include file. */
struct som_solib_mapped_entry
{
/* The name of the library. */
char *name;
- /* Version of this structure (it is expected to change again in hpux10. */
+ /* Version of this structure (it is expected to change again in hpux10). */
unsigned char struct_version;
/* Binding mode for this library. */
@@ -72,6 +87,21 @@ struct som_solib_mapped_entry
contained in them. */
};
+/* A structure to keep track of all the known shared objects. */
+struct so_list
+{
+ struct som_solib_mapped_entry som_solib;
+ struct objfile *objfile;
+ bfd *abfd;
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct so_list *next;
+};
+
+static struct so_list *so_list_head;
+
+static void som_sharedlibrary_info_command PARAMS ((char *, int));
+
/* Add symbols from shared libraries into the symtab list. */
void
@@ -79,9 +109,11 @@ som_solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
-{
+{
struct minimal_symbol *msymbol;
+ struct so_list *so_list_tail;
CORE_ADDR addr;
+ asection *shlib_info;
int status;
unsigned int dld_flags;
char buf[4];
@@ -90,9 +122,21 @@ som_solib_add (arg_string, from_tty, target)
process, then som_solib_create_inferior_hook will not have been
called.
- We need to examine __dld_flags to determine if the shared library
- list is valid, and to determine if the libraries have been privately
+ We need to first determine if we're dealing with a dynamically
+ linked executable. If not, then return without an error or warning.
+
+ We also need to examine __dld_flags to determine if the shared library
+ list is valid and to determine if the libraries have been privately
mapped. */
+ /* First see if the objfile was dynamically linked. */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (!shlib_info)
+ return;
+
+ /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
+ if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
+ return;
+
msymbol = lookup_minimal_symbol ("__dld_flags", (struct objfile *) NULL);
if (msymbol == NULL)
{
@@ -119,7 +163,7 @@ som_solib_add (arg_string, from_tty, target)
/* If the libraries were not mapped private, warn the user. */
if ((dld_flags & 1) == 0)
- warning ("The shared libraries were not privately mapped;\nsetting a breakpoint in a shared library will not work.\n");
+ warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
msymbol = lookup_minimal_symbol ("__dld_list", (struct objfile *) NULL);
if (!msymbol)
@@ -173,37 +217,39 @@ som_solib_add (arg_string, from_tty, target)
Skip the first entry since it's our executable. */
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
- {
- error ("Error while reading dynamic library list.\n");
- return;
- }
+ goto err;
+
addr = extract_unsigned_integer (buf, 4);
+ so_list_tail = so_list_head;
+ /* Find the end of the list of shared objects. */
+ while (so_list_tail && so_list_tail->next)
+ so_list_tail = so_list_tail->next;
+
while (1)
{
CORE_ADDR name_addr, text_addr;
unsigned int name_len;
char *name;
+ struct so_list *new_so;
+ struct section_table *p;
+
if (addr == 0)
break;
/* Get a pointer to the name of this library. */
status = target_read_memory (addr, buf, 4);
if (status != 0)
- {
- error ("Error while reading dynamic library list.\n");
- return;
- }
+ goto err;
+
name_addr = extract_unsigned_integer (buf, 4);
name_len = 0;
while (1)
{
target_read_memory (name_addr + name_len, buf, 1);
if (status != 0)
- {
- error ("Error while reading dynamic library list.\n");
- return;
- }
+ goto err;
+
name_len++;
if (*buf == '\0')
break;
@@ -211,32 +257,159 @@ som_solib_add (arg_string, from_tty, target)
name = alloca (name_len);
status = target_read_memory (name_addr, name, name_len);
if (status != 0)
- {
- error ("Error while reading dynamic library list.\n");
- return;
- }
+ goto err;
+
name = obsavestring (name, name_len - 1,
&symfile_objfile->symbol_obstack);
status = target_read_memory (addr + 8, buf, 4);
if (status != 0)
+ goto err;
+
+ text_addr = extract_unsigned_integer (buf, 4);
+
+
+ new_so = (struct so_list *) malloc (sizeof (struct so_list));
+ memset ((char *)new_so, 0, sizeof (struct so_list));
+ if (so_list_head == NULL)
{
- error ("Error while reading dynamic library list.\n");
- return;
+ so_list_head = new_so;
+ so_list_tail = new_so;
}
- text_addr = extract_unsigned_integer (buf, 4);
+ else
+ {
+ so_list_tail->next = new_so;
+ so_list_tail = new_so;
+ }
+
+ /* Fill in all the entries in GDB's shared library list. */
+ new_so->som_solib.name = name;
+ status = target_read_memory (addr + 4, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
+ new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
+ new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
+ new_so->som_solib.text_addr = text_addr;
+
+ status = target_read_memory (addr + 12, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
- /* OK, we've got everything we need. Tell GDB about it. */
- symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
+ status = target_read_memory (addr + 16, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 20, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 24, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 28, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 32, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
- /* Get address of the next record. */
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
+ goto err;
+
+ new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
+ addr = (CORE_ADDR)new_so->som_solib.next;
+
+ new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
+ new_so->abfd = bfd_openr (name, gnutarget);
+ new_so->abfd->cacheable = true;
+
+ if (!bfd_check_format (new_so->abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ name, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Now we need to build a section table for this library since
+ we might be debugging a core file from a dynamically linked
+ executable in which the libraries were not privately mapped. */
+ if (build_section_table (new_so->abfd,
+ &new_so->sections,
+ &new_so->sections_end))
{
- error ("Error while reading dynamic library list.\n");
+ error ("Unable to build section table for shared library\n.");
return;
}
- addr = extract_unsigned_integer (buf, 4);
+
+ /* Relocate all the sections based on where they got loaded. */
+ for (p = new_so->sections; p < new_so->sections_end; p++)
+ {
+ if (p->the_bfd_section->flags & SEC_CODE)
+ {
+ p->addr += text_addr - new_so->som_solib.text_link_addr;
+ p->endaddr += text_addr - new_so->som_solib.text_link_addr;
+ }
+ else if (p->the_bfd_section->flags & SEC_DATA)
+ {
+ p->addr += new_so->som_solib.data_start;
+ p->endaddr += new_so->som_solib.data_start;
+ }
+ }
+
+ /* Now see if we need to map in the text and data for this shared
+ library (for example debugging a core file which does not use
+ private shared libraries.).
+
+ Carefully peek at the first text address in the library. If the
+ read succeeds, then the libraries were privately mapped and were
+ included in the core dump file.
+
+ If the peek failed, then the libraries were not privately mapped
+ and are not in the core file, we'll have to read them in ourselves. */
+ status = target_read_memory (text_addr, buf, 4);
+ if (status != 0)
+ {
+ int old;
+
+ /* Add sections from the shared library to the core target. */
+ if (target->to_sections)
+ {
+ old = target->to_sections_end - target->to_sections;
+ target->to_sections = (struct section_table *)
+ xrealloc ((char *)target->to_sections,
+ ((sizeof (struct section_table))
+ * (old + bfd_count_sections (new_so->abfd))));
+ }
+ else
+ {
+ old = 0;
+ target->to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table))
+ * bfd_count_sections (new_so->abfd));
+ }
+ target->to_sections_end = (target->to_sections
+ + old + bfd_count_sections (new_so->abfd));
+ memcpy ((char *)(target->to_sections + old),
+ new_so->sections,
+ ((sizeof (struct section_table))
+ * bfd_count_sections (new_so->abfd)));
+ }
}
/* Getting new symbols may change our opinion about what is
@@ -247,8 +420,13 @@ som_solib_add (arg_string, from_tty, target)
old_dld:
error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
return;
+
+err:
+ error ("Error while reading dynamic library list.\n");
+ return;
}
+
/* This hook gets called just before the first instruction in the
inferior process is executed.
@@ -268,13 +446,13 @@ old_dld:
Note that shared libraries are not mapped in at this time, so we have
run the inferior until the libraries are mapped in. Typically this
means running until the "_start" is called. */
-
-void
+
+void
som_solib_create_inferior_hook()
{
struct minimal_symbol *msymbol;
- asection *shlib_info;
unsigned int dld_flags, status;
+ asection *shlib_info;
char shadow_contents[BREAKPOINT_MAX], buf[4];
CORE_ADDR anaddr;
@@ -331,6 +509,18 @@ som_solib_create_inferior_hook()
return;
}
+ /* Wipe out all knowledge of old shared libraries since their
+ mapping can change from one exec to another! */
+ while (so_list_head)
+ {
+ struct so_list *temp;
+
+ free_objfile (so_list_head->objfile);
+ temp = so_list_head;
+ free (so_list_head);
+ so_list_head = temp->next;
+ }
+
/* Start the process again and wait for it to hit our breakpoint. */
clear_proceed_status ();
stop_soon_quietly = 1;
@@ -353,3 +543,57 @@ som_solib_create_inferior_hook()
som_solib_add ((char *) 0, 0, (struct target_ops *) 0);
}
+
+/* Dump information about all the currently loaded shared libraries. */
+
+static void
+som_sharedlibrary_info_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct so_list *so_list = so_list_head;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("no exec file.\n");
+ return;
+ }
+
+ if (so_list == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ return;
+ }
+
+ printf_unfiltered ("Shared Object Libraries\n");
+ printf_unfiltered (" %-12s%-12s%-12s%-12s%-12s%-12s\n",
+ " flags", " tstart", " tend", " dstart", " dend", " dlt");
+ while (so_list)
+ {
+ unsigned int flags;
+
+ flags = so_list->som_solib.struct_version << 24;
+ flags |= so_list->som_solib.bind_mode << 16;
+ flags |= so_list->som_solib.library_version;
+ printf_unfiltered ("%s\n", so_list->som_solib.name);
+ printf_unfiltered (" %-12s", local_hex_string_custom (flags, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_end, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_start, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_end, "08l"));
+ printf_unfiltered ("%-12s\n",
+ local_hex_string_custom (so_list->som_solib.got_value, "08l"));
+ so_list = so_list->next;
+ }
+}
+
+void
+_initialize_som_solib ()
+{
+ add_info ("sharedlibrary", som_sharedlibrary_info_command,
+ "Status of loaded shared object libraries.");
+}