gdb/
[deliverable/binutils-gdb.git] / gdb / solib-som.c
index 52c7367c47becbcdaab307993c0cae133999a68d..1ac83e15c37912e1613092a6592d104418c0a78d 100644 (file)
@@ -1,12 +1,13 @@
 /* Handle SOM shared libraries.
 
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "som.h"
 #include "symtab.h"
 #include "bfd.h"
 #include "symfile.h"
 
 #include "hppa-tdep.h"
 #include "solist.h"
+#include "solib.h"
+#include "solib-som.h"
+
+#include <sys/utsname.h>
+#include <string.h>
 
 #undef SOLIB_SOM_DBG 
 
@@ -109,17 +112,10 @@ dld_cache;
 
 static void
 som_relocate_section_addresses (struct so_list *so,
-                               struct section_table *sec)
+                               struct target_section *sec)
 {
   flagword aflag = bfd_get_section_flags(so->abfd, sec->the_bfd_section);
 
-  /* solib.c does something similar, but it only recognizes ".text", SOM calls
-     the text section "$CODE$".  */
-  if (strcmp (sec->the_bfd_section->name, "$CODE$") == 0)
-    {
-      so->textsection = sec;
-    }
-
   if (aflag & SEC_CODE)
     {
       sec->addr    += so->lm_info->text_addr - so->lm_info->text_link_addr; 
@@ -134,6 +130,38 @@ som_relocate_section_addresses (struct so_list *so,
     ;
 }
 
+/* Get HP-UX major release number.  Returns zero if the
+   release is not known.  */
+
+static int
+get_hpux_major_release (void)
+{
+  static int hpux_major_release = -1;
+
+  if (hpux_major_release == -1)
+    {
+      struct utsname x;
+      char *p;
+
+      uname (&x);
+      p = strchr (x.release, '.');
+      hpux_major_release = p ? atoi (p + 1) : 0;
+    }
+
+  return hpux_major_release;
+}
+
+/* DL header flag defines.  */
+#define SHLIB_TEXT_PRIVATE_ENABLE 0x4000
+
+/* The DL header is documented in <shl.h>.  We are only interested
+   in the flags field to determine whether the executable wants shared
+   libraries mapped private.  */
+struct {
+    short junk[37];
+    short flags;
+} dl_header;
+
 /* This hook gets called just before the first instruction in the
    inferior process is executed.
 
@@ -155,18 +183,15 @@ som_relocate_section_addresses (struct so_list *so,
    means running until the "_start" is called.  */
 
 static void
-som_solib_create_inferior_hook (void)
+som_solib_create_inferior_hook (int from_tty)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   struct minimal_symbol *msymbol;
   unsigned int dld_flags, status, have_endo;
   asection *shlib_info;
   char buf[4];
   CORE_ADDR anaddr;
 
-  /* First, remove all the solib event breakpoints.  Their addresses
-     may have changed since the last time we ran the program.  */
-  remove_solib_event_breakpoints ();
-
   if (symfile_objfile == NULL)
     return;
 
@@ -179,6 +204,10 @@ som_solib_create_inferior_hook (void)
   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
     return;
 
+  /* Read the DL header.  */
+  bfd_get_section_contents (symfile_objfile->obfd, shlib_info,
+                           (char *) &dl_header, 0, sizeof (dl_header));
+
   have_endo = 0;
   /* Slam the pid of the process into __d_pid.
 
@@ -191,7 +220,7 @@ som_solib_create_inferior_hook (void)
     goto keep_going;
 
   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
-  store_unsigned_integer (buf, 4, PIDGET (inferior_ptid));
+  store_unsigned_integer (buf, 4, byte_order, PIDGET (inferior_ptid));
   status = target_write_memory (anaddr, buf, 4);
   if (status != 0)
     {
@@ -234,7 +263,7 @@ GDB will be unable to track shl_load/shl_unload calls"));
       anaddr = SYMBOL_VALUE (msymbol);
       dld_cache.hook_stub.address = anaddr;
     }
-  store_unsigned_integer (buf, 4, anaddr);
+  store_unsigned_integer (buf, 4, byte_order, anaddr);
 
   msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
   if (msymbol == NULL)
@@ -259,7 +288,8 @@ Suggest linking with /opt/langtools/lib/end.o.\n\
 GDB will be unable to track shl_load/shl_unload calls"));
       goto keep_going;
     }
-  create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+  create_solib_event_breakpoint (target_gdbarch,
+                                SYMBOL_VALUE_ADDRESS (msymbol));
 
   /* We have all the support usually found in end.o, so we can track
      shl_load and shl_unload calls.  */
@@ -281,13 +311,27 @@ keep_going:
   status = target_read_memory (anaddr, buf, 4);
   if (status != 0)
     error (_("Unable to read __dld_flags."));
-  dld_flags = extract_unsigned_integer (buf, 4);
+  dld_flags = extract_unsigned_integer (buf, 4, byte_order);
+
+  /* If the libraries were not mapped private on HP-UX 11 and later, warn
+     the user.  On HP-UX 10 and earlier, there is no easy way to specify
+     that shared libraries should be privately mapped.  So, we just force
+     private mapping.  */
+  if (get_hpux_major_release () >= 11
+      && (dl_header.flags & SHLIB_TEXT_PRIVATE_ENABLE) == 0
+      && (dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
+    warning
+      (_("Private mapping of shared library text was not specified\n"
+        "by the executable; setting a breakpoint in a shared library which\n"
+        "is not privately mapped will not work.  See the HP-UX 11i v3 chatr\n"
+        "manpage for methods to privately map shared library text."));
 
   /* Turn on the flags we care about.  */
-  dld_flags |= DLD_FLAGS_MAPPRIVATE;
+  if (get_hpux_major_release () < 11)
+    dld_flags |= DLD_FLAGS_MAPPRIVATE;
   if (have_endo)
     dld_flags |= DLD_FLAGS_HOOKVALID;
-  store_unsigned_integer (buf, 4, dld_flags);
+  store_unsigned_integer (buf, 4, byte_order, dld_flags);
   status = target_write_memory (anaddr, buf, 4);
   if (status != 0)
     error (_("Unable to write __dld_flags."));
@@ -308,7 +352,7 @@ keep_going:
   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
 
   /* Make the breakpoint at "_start" a shared library event breakpoint.  */
-  create_solib_event_breakpoint (anaddr);
+  create_solib_event_breakpoint (target_gdbarch, anaddr);
 
   clear_symtab_users ();
 }
@@ -347,7 +391,7 @@ som_solib_desire_dynamic_linker_symbols (void)
                                                          objfile);
     if (dld_msymbol != NULL)
       {
-       if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+       if (MSYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
          {
            u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
            if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
@@ -386,7 +430,7 @@ som_solib_desire_dynamic_linker_symbols (void)
                                                          objfile);
     if (dld_msymbol != NULL)
       {
-       if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+       if (MSYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
          {
            u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
            if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
@@ -481,6 +525,7 @@ struct dld_list {
 static CORE_ADDR
 link_map_start (void)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   struct minimal_symbol *sym;
   CORE_ADDR addr;
   char buf[4];
@@ -491,16 +536,10 @@ link_map_start (void)
     error (_("Unable to find __dld_flags symbol in object file."));
   addr = SYMBOL_VALUE_ADDRESS (sym);
   read_memory (addr, buf, 4);
-  dld_flags = extract_unsigned_integer (buf, 4);
+  dld_flags = extract_unsigned_integer (buf, 4, byte_order);
   if ((dld_flags & DLD_FLAGS_LISTVALID) == 0)
     error (_("__dld_list is not valid according to __dld_flags."));
 
-  /* If the libraries were not mapped private, warn the user.  */
-  if ((dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
-    warning (_("The shared libraries were not privately mapped; setting a\n"
-            "breakpoint in a shared library will not work until you rerun the "
-            "program.\n"));
-
   sym = lookup_minimal_symbol ("__dld_list", NULL, NULL);
   if (!sym)
     {
@@ -518,12 +557,12 @@ link_map_start (void)
     addr = SYMBOL_VALUE_ADDRESS (sym);
 
   read_memory (addr, buf, 4);
-  addr = extract_unsigned_integer (buf, 4);
+  addr = extract_unsigned_integer (buf, 4, byte_order);
   if (addr == 0)
     return 0;
 
   read_memory (addr, buf, 4);
-  return extract_unsigned_integer (buf, 4);
+  return extract_unsigned_integer (buf, 4, byte_order);
 }
 
 /* Does this so's name match the main binary? */
@@ -536,6 +575,7 @@ match_main (const char *name)
 static struct so_list *
 som_current_sos (void)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   CORE_ADDR lm;
   struct so_list *head = 0;
   struct so_list **link_ptr = &head;
@@ -560,7 +600,7 @@ som_current_sos (void)
       read_memory (lm, (gdb_byte *)&dbuf, sizeof (struct dld_list));
 
       addr = extract_unsigned_integer ((gdb_byte *)&dbuf.name,
-                                      sizeof (dbuf.name));
+                                      sizeof (dbuf.name), byte_order);
       target_read_string (addr, &namebuf, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
       if (errcode != 0)
        warning (_("Can't read pathname for load map: %s."),
@@ -581,7 +621,8 @@ som_current_sos (void)
            lmi->lm_addr = lm;
 
 #define EXTRACT(_fld) \
-  extract_unsigned_integer ((gdb_byte *)&dbuf._fld, sizeof (dbuf._fld));
+  extract_unsigned_integer ((gdb_byte *)&dbuf._fld, \
+                           sizeof (dbuf._fld), byte_order);
 
            lmi->text_addr = EXTRACT (text_addr);
            tmp = EXTRACT (info);
@@ -596,33 +637,37 @@ som_current_sos (void)
            lmi->got_value = EXTRACT (got_value);
            tmp = EXTRACT (tsd_start_addr_ptr);
            read_memory (tmp, tsdbuf, 4);
-           lmi->tsd_start_addr = extract_unsigned_integer (tsdbuf, 4);
+           lmi->tsd_start_addr
+             = extract_unsigned_integer (tsdbuf, 4, byte_order);
 
 #ifdef SOLIB_SOM_DBG
-           printf ("\n+ library \"%s\" is described at 0x%s\n", new->so_name, 
-                   paddr_nz (lm));
+           printf ("\n+ library \"%s\" is described at %s\n", new->so_name,
+                   paddress (target_gdbarch, lm));
            printf ("  'version' is %d\n", new->lm_info->struct_version);
            printf ("  'bind_mode' is %d\n", new->lm_info->bind_mode);
            printf ("  'library_version' is %d\n", 
                    new->lm_info->library_version);
-           printf ("  'text_addr' is 0x%s\n", 
-                   paddr_nz (new->lm_info->text_addr));
-           printf ("  'text_link_addr' is 0x%s\n", 
-                   paddr_nz (new->lm_info->text_link_addr));
-           printf ("  'text_end' is 0x%s\n", 
-                   paddr_nz (new->lm_info->text_end));
-           printf ("  'data_start' is 0x%s\n", 
-                   paddr_nz (new->lm_info->data_start));
-           printf ("  'bss_start' is 0x%s\n", 
-                   paddr_nz (new->lm_info->bss_start));
-           printf ("  'data_end' is 0x%s\n", 
-                   paddr_nz (new->lm_info->data_end));
-           printf ("  'got_value' is %s\n", 
-                   paddr_nz (new->lm_info->got_value));
-           printf ("  'tsd_start_addr' is 0x%s\n", 
-                   paddr_nz (new->lm_info->tsd_start_addr));
+           printf ("  'text_addr' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->text_addr));
+           printf ("  'text_link_addr' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->text_link_addr));
+           printf ("  'text_end' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->text_end));
+           printf ("  'data_start' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->data_start));
+           printf ("  'bss_start' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->bss_start));
+           printf ("  'data_end' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->data_end));
+           printf ("  'got_value' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->got_value));
+           printf ("  'tsd_start_addr' is %s\n",
+                   paddress (target_gdbarch, new->lm_info->tsd_start_addr));
 #endif
 
+           new->addr_low = lmi->text_addr;
+           new->addr_high = lmi->text_end;
+
            /* Link the new object onto the list.  */
            new->next = NULL;
            *link_ptr = new;
@@ -647,6 +692,7 @@ som_current_sos (void)
 static int
 som_open_symbol_file_object (void *from_ttyp)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   CORE_ADDR lm, l_name;
   char *filename;
   int errcode;
@@ -654,7 +700,7 @@ som_open_symbol_file_object (void *from_ttyp)
   char buf[4];
 
   if (symfile_objfile)
-    if (!query ("Attempt to reload symbols from process? "))
+    if (!query (_("Attempt to reload symbols from process? ")))
       return 0;
 
   /* First link map member should be the executable.  */
@@ -666,7 +712,7 @@ som_open_symbol_file_object (void *from_ttyp)
 
   /* Convert the address to host format.  Assume that the address is
      unsigned.  */
-  l_name = extract_unsigned_integer (buf, 4);
+  l_name = extract_unsigned_integer (buf, 4, byte_order);
 
   if (l_name == 0)
     return 0;          /* No filename.  */
@@ -763,11 +809,14 @@ _initialize_som_solib (void)
   som_so_ops.current_sos = som_current_sos;
   som_so_ops.open_symbol_file_object = som_open_symbol_file_object;
   som_so_ops.in_dynsym_resolve_code = som_in_dynsym_resolve_code;
+  som_so_ops.bfd_open = solib_bfd_open;
 }
 
-void som_solib_select (struct gdbarch_tdep *tdep)
+void
+som_solib_select (struct gdbarch *gdbarch)
 {
-  current_target_so_ops = &som_so_ops;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  set_solib_ops (gdbarch, &som_so_ops);
 
   tdep->solib_thread_start_addr = som_solib_thread_start_addr;
   tdep->solib_get_got_by_pc = som_solib_get_got_by_pc;
This page took 0.030694 seconds and 4 git commands to generate.