diff options
Diffstat (limited to 'gdb/somsolib.c')
-rw-r--r-- | gdb/somsolib.c | 316 |
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."); +} |