2011-02-21 Hui Zhu <teawater@gmail.com>
[deliverable/binutils-gdb.git] / gdb / solib-frv.c
index cd3fc8d4dcb62137b04b214a3eb4658ed5f4578e..16455bef03f4801406a9f93599a8534f4090259a 100644 (file)
@@ -1,12 +1,12 @@
 /* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
-   Copyright 2004
+   Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011
    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., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include "defs.h"
 #include "gdb_string.h"
 #include "inferior.h"
 #include "gdbcore.h"
+#include "solib.h"
 #include "solist.h"
 #include "frv-tdep.h"
 #include "objfiles.h"
@@ -32,6 +31,7 @@
 #include "command.h"
 #include "gdbcmd.h"
 #include "elf/frv.h"
+#include "exceptions.h"
 
 /* Flag which indicates whether internal debug messages should be printed.  */
 static int solib_frv_debug;
@@ -44,9 +44,9 @@ enum { FRV_PTR_SIZE = 4 };
 /* External versions; the size and alignment of the fields should be
    the same as those on the target.  When loaded, the placement of
    the bits in each field will be the same as on the target.  */
-typedef unsigned char ext_Elf32_Half[2];
-typedef unsigned char ext_Elf32_Addr[4];
-typedef unsigned char ext_Elf32_Word[4];
+typedef gdb_byte ext_Elf32_Half[2];
+typedef gdb_byte ext_Elf32_Addr[4];
+typedef gdb_byte ext_Elf32_Word[4];
 
 struct ext_elf32_fdpic_loadseg
 {
@@ -98,6 +98,7 @@ struct int_elf32_fdpic_loadmap {
 static struct int_elf32_fdpic_loadmap *
 fetch_loadmap (CORE_ADDR ldmaddr)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   struct ext_elf32_fdpic_loadmap ext_ldmbuf_partial;
   struct ext_elf32_fdpic_loadmap *ext_ldmbuf;
   struct int_elf32_fdpic_loadmap *int_ldmbuf;
@@ -105,7 +106,7 @@ fetch_loadmap (CORE_ADDR ldmaddr)
   int version, seg, nsegs;
 
   /* Fetch initial portion of the loadmap.  */
-  if (target_read_memory (ldmaddr, (char *) &ext_ldmbuf_partial,
+  if (target_read_memory (ldmaddr, (gdb_byte *) &ext_ldmbuf_partial,
                           sizeof ext_ldmbuf_partial))
     {
       /* Problem reading the target's memory.  */
@@ -113,8 +114,9 @@ fetch_loadmap (CORE_ADDR ldmaddr)
     }
 
   /* Extract the version.  */
-  version = extract_unsigned_integer (&ext_ldmbuf_partial.version,
-                                      sizeof ext_ldmbuf_partial.version);
+  version = extract_unsigned_integer (ext_ldmbuf_partial.version,
+                                      sizeof ext_ldmbuf_partial.version,
+                                     byte_order);
   if (version != 0)
     {
       /* We only handle version 0.  */
@@ -122,8 +124,12 @@ fetch_loadmap (CORE_ADDR ldmaddr)
     }
 
   /* Extract the number of segments.  */
-  nsegs = extract_unsigned_integer (&ext_ldmbuf_partial.nsegs,
-                                    sizeof ext_ldmbuf_partial.nsegs);
+  nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs,
+                                    sizeof ext_ldmbuf_partial.nsegs,
+                                   byte_order);
+
+  if (nsegs <= 0)
+    return NULL;
 
   /* Allocate space for the complete (external) loadmap.  */
   ext_ldmbuf_size = sizeof (struct ext_elf32_fdpic_loadmap)
@@ -135,7 +141,7 @@ fetch_loadmap (CORE_ADDR ldmaddr)
 
   /* Read the rest of the loadmap from the target.  */
   if (target_read_memory (ldmaddr + sizeof ext_ldmbuf_partial,
-                          (char *) ext_ldmbuf + sizeof ext_ldmbuf_partial,
+                          (gdb_byte *) ext_ldmbuf + sizeof ext_ldmbuf_partial,
                           ext_ldmbuf_size - sizeof ext_ldmbuf_partial))
     {
       /* Couldn't read rest of the loadmap.  */
@@ -155,14 +161,17 @@ fetch_loadmap (CORE_ADDR ldmaddr)
   for (seg = 0; seg < nsegs; seg++)
     {
       int_ldmbuf->segs[seg].addr
-       = extract_unsigned_integer (&ext_ldmbuf->segs[seg].addr,
-                                   sizeof (ext_ldmbuf->segs[seg].addr));
+       = extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
+                                   sizeof (ext_ldmbuf->segs[seg].addr),
+                                   byte_order);
       int_ldmbuf->segs[seg].p_vaddr
-       = extract_unsigned_integer (&ext_ldmbuf->segs[seg].p_vaddr,
-                                   sizeof (ext_ldmbuf->segs[seg].p_vaddr));
+       = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
+                                   sizeof (ext_ldmbuf->segs[seg].p_vaddr),
+                                   byte_order);
       int_ldmbuf->segs[seg].p_memsz
-       = extract_unsigned_integer (&ext_ldmbuf->segs[seg].p_memsz,
-                                   sizeof (ext_ldmbuf->segs[seg].p_memsz));
+       = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
+                                   sizeof (ext_ldmbuf->segs[seg].p_memsz),
+                                   byte_order);
     }
 
   xfree (ext_ldmbuf);
@@ -171,7 +180,7 @@ fetch_loadmap (CORE_ADDR ldmaddr)
 
 /* External link_map and elf32_fdpic_loadaddr struct definitions.  */
 
-typedef unsigned char ext_ptr[4];
+typedef gdb_byte ext_ptr[4];
 
 struct ext_elf32_fdpic_loadaddr
 {
@@ -193,7 +202,7 @@ struct ext_link_map
   ext_ptr l_next, l_prev;      /* struct link_map *l_next, *l_prev; */
 };
 
-/* Link map info to include in an allocated so_list entry */
+/* Link map info to include in an allocated so_list entry */
 
 struct lm_info
   {
@@ -201,6 +210,8 @@ struct lm_info
     struct int_elf32_fdpic_loadmap *map;
     /* The GOT address for this link map entry.  */
     CORE_ADDR got_value;
+    /* The link map address, needed for frv_fetch_objfile_link_map().  */
+    CORE_ADDR lm_addr;
 
     /* Cached dynamic symbol table and dynamic relocs initialized and
        used only by find_canonical_descriptor_in_load_object().
@@ -214,7 +225,7 @@ struct lm_info
        caching of the dynamic relocations could be dispensed with.  */
     asymbol **dyn_syms;
     arelent **dyn_relocs;
-    int dyn_reloc_count;       /* number of dynamic relocs.  */
+    int dyn_reloc_count;       /* Number of dynamic relocs.  */
 
   };
 
@@ -273,7 +284,7 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
          sym = *symbol_table++;
          if (strcmp (sym->name, symname) == 0)
            {
-             /* Bfd symbols are section relative. */
+             /* Bfd symbols are section relative.  */
              symaddr = sym->value + sym->section->vma;
              break;
            }
@@ -299,7 +310,7 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
          sym = *symbol_table++;
          if (strcmp (sym->name, symname) == 0)
            {
-             /* Bfd symbols are section relative. */
+             /* Bfd symbols are section relative.  */
              symaddr = sym->value + sym->section->vma;
              break;
            }
@@ -329,7 +340,7 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
   If FROM_TTYP dereferences to a non-zero integer, allow messages to
   be printed.  This parameter is a pointer rather than an int because
   open_symbol_file_object() is called via catch_errors() and
-  catch_errors() requires a pointer argument. */
+  catch_errors() requires a pointer argument.  */
 
 static int
 open_symbol_file_object (void *from_ttyp)
@@ -341,6 +352,9 @@ open_symbol_file_object (void *from_ttyp)
 /* Cached value for lm_base(), below.  */
 static CORE_ADDR lm_base_cache = 0;
 
+/* Link map address for main module.  */
+static CORE_ADDR main_lm_addr = 0;
+
 /* Return the address from which the link map chain may be found.  On
    the FR-V, this may be found in a number of ways.  Assuming that the
    main executable has already been relocated, the easiest way to find
@@ -352,9 +366,18 @@ static CORE_ADDR lm_base_cache = 0;
 static CORE_ADDR
 lm_base (void)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   struct minimal_symbol *got_sym;
   CORE_ADDR addr;
-  char buf[FRV_PTR_SIZE];
+  gdb_byte buf[FRV_PTR_SIZE];
+
+  /* One of our assumptions is that the main executable has been relocated.
+     Bail out if this has not happened.  (Note that post_create_inferior()
+     in infcmd.c will call solib_add prior to solib_create_inferior_hook().
+     If we allow this to happen, lm_base_cache will be initialized with
+     a bogus value.  */
+  if (main_executable_lm_info == 0)
+    return 0;
 
   /* If we already have a cached value, return it.  */
   if (lm_base_cache)
@@ -379,7 +402,7 @@ lm_base (void)
 
   if (target_read_memory (addr, buf, sizeof buf) != 0)
     return 0;
-  lm_base_cache = extract_unsigned_integer (buf, sizeof buf);
+  lm_base_cache = extract_unsigned_integer (buf, sizeof buf, byte_order);
 
   if (solib_frv_debug)
     fprintf_unfiltered (gdb_stdlog,
@@ -412,10 +435,27 @@ lm_base (void)
 static struct so_list *
 frv_current_sos (void)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   CORE_ADDR lm_addr, mgot;
   struct so_list *sos_head = NULL;
   struct so_list **sos_next_ptr = &sos_head;
 
+  /* Make sure that the main executable has been relocated.  This is
+     required in order to find the address of the global offset table,
+     which in turn is used to find the link map info.  (See lm_base()
+     for details.)
+
+     Note that the relocation of the main executable is also performed
+     by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core
+     files, this hook is called too late in order to be of benefit to
+     SOLIB_ADD.  SOLIB_ADD eventually calls this this function,
+     frv_current_sos, and also precedes the call to
+     SOLIB_CREATE_INFERIOR_HOOK().   (See post_create_inferior() in
+     infcmd.c.)  */
+  if (main_executable_lm_info == 0 && core_bfd != NULL)
+    frv_relocate_main_executable ();
+
+  /* Fetch the GOT corresponding to the main executable.  */
   mgot = main_got ();
 
   /* Locate the address of the first link map struct.  */
@@ -433,15 +473,18 @@ frv_current_sos (void)
                            "current_sos: reading link_map entry at %s\n",
                            hex_string_custom (lm_addr, 8));
 
-      if (target_read_memory (lm_addr, (char *) &lm_buf, sizeof (lm_buf)) != 0)
+      if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf,
+                             sizeof (lm_buf)) != 0)
        {
-         warning ("frv_current_sos: Unable to read link map entry.  Shared object chain may be incomplete.");
+         warning (_("frv_current_sos: Unable to read link map entry.  "
+                    "Shared object chain may be incomplete."));
          break;
        }
 
       got_addr
-       = extract_unsigned_integer (&lm_buf.l_addr.got_value,
-                                   sizeof (lm_buf.l_addr.got_value));
+       = extract_unsigned_integer (lm_buf.l_addr.got_value,
+                                   sizeof (lm_buf.l_addr.got_value),
+                                   byte_order);
       /* If the got_addr is the same as mgotr, then we're looking at the
         entry for the main executable.  By convention, we don't include
         this in the list of shared objects.  */
@@ -454,12 +497,14 @@ frv_current_sos (void)
          CORE_ADDR addr;
 
          /* Fetch the load map address.  */
-         addr = extract_unsigned_integer (&lm_buf.l_addr.map,
-                                          sizeof lm_buf.l_addr.map);
+         addr = extract_unsigned_integer (lm_buf.l_addr.map,
+                                          sizeof lm_buf.l_addr.map,
+                                          byte_order);
          loadmap = fetch_loadmap (addr);
          if (loadmap == NULL)
            {
-             warning ("frv_current_sos: Unable to fetch load map.  Shared object chain may be incomplete.");
+             warning (_("frv_current_sos: Unable to fetch load map.  "
+                        "Shared object chain may be incomplete."));
              break;
            }
 
@@ -467,9 +512,11 @@ frv_current_sos (void)
          sop->lm_info = xcalloc (1, sizeof (struct lm_info));
          sop->lm_info->map = loadmap;
          sop->lm_info->got_value = got_addr;
+         sop->lm_info->lm_addr = lm_addr;
          /* Fetch the name.  */
-         addr = extract_unsigned_integer (&lm_buf.l_name,
-                                          sizeof (lm_buf.l_name));
+         addr = extract_unsigned_integer (lm_buf.l_name,
+                                          sizeof (lm_buf.l_name),
+                                          byte_order);
          target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
                              &errcode);
 
@@ -478,10 +525,8 @@ frv_current_sos (void)
                                name_buf);
          
          if (errcode != 0)
-           {
-             warning ("frv_current_sos: Can't read pathname for link map entry: %s\n",
-                      safe_strerror (errcode));
-           }
+           warning (_("Can't read pathname for link map entry: %s."),
+                    safe_strerror (errcode));
          else
            {
              strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1);
@@ -493,8 +538,13 @@ frv_current_sos (void)
          *sos_next_ptr = sop;
          sos_next_ptr = &sop->next;
        }
+      else
+       {
+         main_lm_addr = lm_addr;
+       }
 
-      lm_addr = extract_unsigned_integer (&lm_buf.l_next, sizeof (lm_buf.l_next));
+      lm_addr = extract_unsigned_integer (lm_buf.l_next,
+                                         sizeof (lm_buf.l_next), byte_order);
     }
 
   enable_break2 ();
@@ -522,7 +572,7 @@ frv_in_dynsym_resolve_code (CORE_ADDR pc)
 /* Given a loadmap and an address, return the displacement needed
    to relocate the address.  */
 
-CORE_ADDR
+static CORE_ADDR
 displacement_from_map (struct int_elf32_fdpic_loadmap *map,
                        CORE_ADDR addr)
 {
@@ -546,9 +596,9 @@ displacement_from_map (struct int_elf32_fdpic_loadmap *map,
 static void
 enable_break_failure_warning (void)
 {
-  warning ("Unable to find dynamic linker breakpoint function.\n"
+  warning (_("Unable to find dynamic linker breakpoint function.\n"
            "GDB will be unable to debug shared library initializers\n"
-          "and track explicitly loaded dynamic code.");
+          "and track explicitly loaded dynamic code."));
 }
 
 /*
@@ -585,25 +635,19 @@ enable_break_failure_warning (void)
 
  */
 
-static int enable_break1_done = 0;
 static int enable_break2_done = 0;
 
 static int
 enable_break2 (void)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   int success = 0;
   char **bkpt_namep;
   asection *interp_sect;
 
-  if (!enable_break1_done || enable_break2_done)
+  if (enable_break2_done)
     return 1;
 
-  enable_break2_done = 1;
-
-  /* First, remove all the solib event breakpoints.  Their addresses
-     may have changed since the last time we ran the program.  */
-  remove_solib_event_breakpoints ();
-
   interp_text_sect_low = interp_text_sect_high = 0;
   interp_plt_sect_low = interp_plt_sect_high = 0;
 
@@ -613,14 +657,13 @@ enable_break2 (void)
   if (interp_sect)
     {
       unsigned int interp_sect_size;
-      char *buf;
+      gdb_byte *buf;
       bfd *tmp_bfd = NULL;
-      int tmp_fd = -1;
-      char *tmp_pathname = NULL;
       int status;
       CORE_ADDR addr, interp_loadmap_addr;
-      char addr_buf[FRV_PTR_SIZE];
+      gdb_byte addr_buf[FRV_PTR_SIZE];
       struct int_elf32_fdpic_loadmap *ldm;
+      volatile struct gdb_exception ex;
 
       /* Read the contents of the .interp section into a local buffer;
          the contents specify the dynamic linker this program uses.  */
@@ -638,30 +681,21 @@ enable_break2 (void)
          be trivial on GNU/Linux).  Therefore, we have to try an alternate
          mechanism to find the dynamic linker's base address.  */
 
-      tmp_fd  = solib_open (buf, &tmp_pathname);
-      if (tmp_fd >= 0)
-       tmp_bfd = bfd_fdopenr (tmp_pathname, gnutarget, tmp_fd);
-
+      TRY_CATCH (ex, RETURN_MASK_ALL)
+        {
+          tmp_bfd = solib_bfd_open (buf);
+        }
       if (tmp_bfd == NULL)
        {
          enable_break_failure_warning ();
          return 0;
        }
 
-      /* Make sure the dynamic linker is really a useful object.  */
-      if (!bfd_check_format (tmp_bfd, bfd_object))
-       {
-         warning ("Unable to grok dynamic linker %s as an object file", buf);
-         enable_break_failure_warning ();
-         bfd_close (tmp_bfd);
-         return 0;
-       }
-
-      status = frv_fdpic_loadmap_addresses (current_gdbarch,
+      status = frv_fdpic_loadmap_addresses (target_gdbarch,
                                             &interp_loadmap_addr, 0);
       if (status < 0)
        {
-         warning ("Unable to determine dynamic linker loadmap address\n");
+         warning (_("Unable to determine dynamic linker loadmap address."));
          enable_break_failure_warning ();
          bfd_close (tmp_bfd);
          return 0;
@@ -675,7 +709,7 @@ enable_break2 (void)
       ldm = fetch_loadmap (interp_loadmap_addr);
       if (ldm == NULL)
        {
-         warning ("Unable to load dynamic linker loadmap at address %s\n",
+         warning (_("Unable to load dynamic linker loadmap at address %s."),
                   hex_string_custom (interp_loadmap_addr, 8));
          enable_break_failure_warning ();
          bfd_close (tmp_bfd);
@@ -708,7 +742,8 @@ enable_break2 (void)
       addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr");
       if (addr == 0)
        {
-         warning ("Could not find symbol _dl_debug_addr in dynamic linker");
+         warning (_("Could not find symbol _dl_debug_addr "
+                    "in dynamic linker"));
          enable_break_failure_warning ();
          bfd_close (tmp_bfd);
          return 0;
@@ -716,46 +751,67 @@ enable_break2 (void)
 
       if (solib_frv_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
+                           "enable_break: _dl_debug_addr "
+                           "(prior to relocation) = %s\n",
                            hex_string_custom (addr, 8));
 
       addr += displacement_from_map (ldm, addr);
 
       if (solib_frv_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "enable_break: _dl_debug_addr (after relocation) = %s\n",
+                           "enable_break: _dl_debug_addr "
+                           "(after relocation) = %s\n",
                            hex_string_custom (addr, 8));
 
       /* Fetch the address of the r_debug struct.  */
       if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
        {
-         warning ("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker",
+         warning (_("Unable to fetch contents of _dl_debug_addr "
+                    "(at address %s) from dynamic linker"),
                   hex_string_custom (addr, 8));
        }
-      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
+      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
+
+      if (solib_frv_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "enable_break: _dl_debug_addr[0..3] = %s\n",
+                           hex_string_custom (addr, 8));
+
+      /* If it's zero, then the ldso hasn't initialized yet, and so
+         there are no shared libs yet loaded.  */
+      if (addr == 0)
+       {
+         if (solib_frv_debug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "enable_break: ldso not yet initialized\n");
+         /* Do not warn, but mark to run again.  */
+         return 0;
+       }
 
       /* Fetch the r_brk field.  It's 8 bytes from the start of
          _dl_debug_addr.  */
       if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
        {
-         warning ("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker",
+         warning (_("Unable to fetch _dl_debug_addr->r_brk "
+                    "(at address %s) from dynamic linker"),
                   hex_string_custom (addr + 8, 8));
          enable_break_failure_warning ();
          bfd_close (tmp_bfd);
          return 0;
        }
-      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
+      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
 
       /* Now fetch the function entry point.  */
       if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
        {
-         warning ("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker",
+         warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point "
+                    "(at address %s) from dynamic linker"),
                   hex_string_custom (addr, 8));
          enable_break_failure_warning ();
          bfd_close (tmp_bfd);
          return 0;
        }
-      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
+      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
 
       /* We're done with the temporary bfd.  */
       bfd_close (tmp_bfd);
@@ -763,8 +819,14 @@ enable_break2 (void)
       /* We're also done with the loadmap.  */
       xfree (ldm);
 
+      /* Remove all the solib event breakpoints.  Their addresses
+         may have changed since the last time we ran the program.  */
+      remove_solib_event_breakpoints ();
+
       /* Now (finally!) create the solib breakpoint.  */
-      create_solib_event_breakpoint (addr);
+      create_solib_event_breakpoint (target_gdbarch, addr);
+
+      enable_break2_done = 1;
 
       return 1;
     }
@@ -781,33 +843,44 @@ enable_break (void)
 {
   asection *interp_sect;
 
-  /* 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)
+    {
+      if (solib_frv_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "enable_break: No symbol file found.\n");
+      return 0;
+    }
+
+  if (!symfile_objfile->ei.entry_point_p)
+    {
+      if (solib_frv_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "enable_break: Symbol file has no entry point.\n");
+      return 0;
+    }
 
   /* Check for the presence of a .interp section.  If there is no
      such section, the executable is statically linked.  */
 
   interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
 
-  if (interp_sect)
-    {
-      enable_break1_done = 1;
-      create_solib_event_breakpoint (symfile_objfile->ei.entry_point);
-
-      if (solib_frv_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "enable_break: solib event breakpoint placed at entry point: %s\n",
-                           hex_string_custom
-                             (symfile_objfile->ei.entry_point, 8));
-    }
-  else
+  if (interp_sect == NULL)
     {
       if (solib_frv_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "enable_break: No .interp section found.\n");
+                           "enable_break: No .interp section found.\n");
+      return 0;
     }
 
+  create_solib_event_breakpoint (target_gdbarch,
+                                symfile_objfile->ei.entry_point);
+
+  if (solib_frv_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "enable_break: solib event breakpoint "
+                       "placed at entry point: %s\n",
+                       hex_string_custom (symfile_objfile->ei.entry_point,
+                                          8));
   return 1;
 }
 
@@ -832,23 +905,24 @@ enable_break (void)
 static void
 frv_special_symbol_handling (void)
 {
-  /* Nothing needed (yet) for FRV. */
+  /* Nothing needed (yet) for FRV.  */
 }
 
 static void
 frv_relocate_main_executable (void)
 {
   int status;
-  CORE_ADDR exec_addr;
+  CORE_ADDR exec_addr, interp_addr;
   struct int_elf32_fdpic_loadmap *ldm;
   struct cleanup *old_chain;
   struct section_offsets *new_offsets;
   int changed;
   struct obj_section *osect;
 
-  status = frv_fdpic_loadmap_addresses (current_gdbarch, 0, &exec_addr);
+  status = frv_fdpic_loadmap_addresses (target_gdbarch,
+                                        &interp_addr, &exec_addr);
 
-  if (status < 0)
+  if (status < 0 || (exec_addr == 0 && interp_addr == 0))
     {
       /* Not using FDPIC ABI, so do nothing.  */
       return;
@@ -857,7 +931,7 @@ frv_relocate_main_executable (void)
   /* Fetch the loadmap located at ``exec_addr''.  */
   ldm = fetch_loadmap (exec_addr);
   if (ldm == NULL)
-    error ("Unable to load the executable's loadmap.");
+    error (_("Unable to load the executable's loadmap."));
 
   if (main_executable_lm_info)
     xfree (main_executable_lm_info);
@@ -878,7 +952,7 @@ frv_relocate_main_executable (void)
       osect_idx = osect->the_bfd_section->index;
 
       /* Current address of section.  */
-      addr = osect->addr;
+      addr = obj_section_addr (osect);
       /* Offset from where this section started.  */
       offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
       /* Original address prior to any past relocations.  */
@@ -917,7 +991,7 @@ frv_relocate_main_executable (void)
 
    SYNOPSIS
 
-   void frv_solib_create_inferior_hook()
+   void frv_solib_create_inferior_hook ()
 
    DESCRIPTION
 
@@ -932,7 +1006,7 @@ frv_relocate_main_executable (void)
  */
 
 static void
-frv_solib_create_inferior_hook (void)
+frv_solib_create_inferior_hook (int from_tty)
 {
   /* Relocate main executable.  */
   frv_relocate_main_executable ();
@@ -940,7 +1014,7 @@ frv_solib_create_inferior_hook (void)
   /* Enable shared library breakpoints.  */
   if (!enable_break ())
     {
-      warning ("shared library handler failed to enable breakpoint");
+      warning (_("shared library handler failed to enable breakpoint"));
       return;
     }
 }
@@ -949,8 +1023,16 @@ static void
 frv_clear_solib (void)
 {
   lm_base_cache = 0;
-  enable_break1_done = 0;
   enable_break2_done = 0;
+  main_lm_addr = 0;
+  if (main_executable_lm_info != 0)
+    {
+      xfree (main_executable_lm_info->map);
+      xfree (main_executable_lm_info->dyn_syms);
+      xfree (main_executable_lm_info->dyn_relocs);
+      xfree (main_executable_lm_info);
+      main_executable_lm_info = 0;
+    }
 }
 
 static void
@@ -964,7 +1046,7 @@ frv_free_so (struct so_list *so)
 
 static void
 frv_relocate_section_addresses (struct so_list *so,
-                                 struct section_table *sec)
+                                 struct target_section *sec)
 {
   int seg;
   struct int_elf32_fdpic_loadmap *map;
@@ -977,6 +1059,7 @@ frv_relocate_section_addresses (struct so_list *so,
           && sec->addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
        {
          CORE_ADDR displ = map->segs[seg].addr - map->segs[seg].p_vaddr;
+
          sec->addr += displ;
          sec->endaddr += displ;
          break;
@@ -992,7 +1075,8 @@ main_got (void)
 {
   struct minimal_symbol *got_sym;
 
-  got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL, symfile_objfile);
+  got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_",
+                                  NULL, symfile_objfile);
   if (got_sym == 0)
     return 0;
 
@@ -1092,6 +1176,7 @@ find_canonical_descriptor_in_load_object
   (CORE_ADDR entry_point, CORE_ADDR got_value, char *name, bfd *abfd,
    struct lm_info *lm)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
   arelent *rel;
   unsigned int i;
   CORE_ADDR addr = 0;
@@ -1100,6 +1185,10 @@ find_canonical_descriptor_in_load_object
   if (abfd == 0)
     return 0;
 
+  /* Nothing to do if no link map.  */
+  if (lm == 0)
+    return 0;
+
   /* We want to scan the dynamic relocs for R_FRV_FUNCDESC relocations.
      (More about this later.)  But in order to fetch the relocs, we
      need to first fetch the dynamic symbols.  These symbols need to
@@ -1172,7 +1261,7 @@ find_canonical_descriptor_in_load_object
       if ((name == 0 || strcmp (name, (*rel->sym_ptr_ptr)->name) == 0)
           && rel->howto->type == R_FRV_FUNCDESC)
        {
-         char buf[FRV_PTR_SIZE];
+         gdb_byte buf [FRV_PTR_SIZE];
 
          /* Compute address of address of candidate descriptor.  */
          addr = rel->address + displacement_from_map (lm->map, rel->address);
@@ -1180,18 +1269,20 @@ find_canonical_descriptor_in_load_object
          /* Fetch address of candidate descriptor.  */
          if (target_read_memory (addr, buf, sizeof buf) != 0)
            continue;
-         addr = extract_unsigned_integer (buf, sizeof buf);
+         addr = extract_unsigned_integer (buf, sizeof buf, byte_order);
 
          /* Check for matching entry point.  */
          if (target_read_memory (addr, buf, sizeof buf) != 0)
            continue;
-         if (extract_unsigned_integer (buf, sizeof buf) != entry_point)
+         if (extract_unsigned_integer (buf, sizeof buf, byte_order)
+             != entry_point)
            continue;
 
          /* Check for matching got value.  */
          if (target_read_memory (addr + 4, buf, sizeof buf) != 0)
            continue;
-         if (extract_unsigned_integer (buf, sizeof buf) != got_value)
+         if (extract_unsigned_integer (buf, sizeof buf, byte_order)
+             != got_value)
            continue;
 
          /* Match was successful!  Exit loop.  */
@@ -1202,7 +1293,37 @@ find_canonical_descriptor_in_load_object
   return addr;
 }
 
-static struct target_so_ops frv_so_ops;
+/* Given an objfile, return the address of its link map.  This value is
+   needed for TLS support.  */
+CORE_ADDR
+frv_fetch_objfile_link_map (struct objfile *objfile)
+{
+  struct so_list *so;
+
+  /* Cause frv_current_sos() to be run if it hasn't been already.  */
+  if (main_lm_addr == 0)
+    solib_add (0, 0, 0, 1);
+
+  /* frv_current_sos() will set main_lm_addr for the main executable.  */
+  if (objfile == symfile_objfile)
+    return main_lm_addr;
+
+  /* The other link map addresses may be found by examining the list
+     of shared libraries.  */
+  for (so = master_so_list (); so; so = so->next)
+    {
+      if (so->objfile == objfile)
+       return so->lm_info->lm_addr;
+    }
+
+  /* Not found!  */
+  return 0;
+}
+
+struct target_so_ops frv_so_ops;
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_frv_solib;
 
 void
 _initialize_frv_solib (void)
@@ -1215,16 +1336,15 @@ _initialize_frv_solib (void)
   frv_so_ops.current_sos = frv_current_sos;
   frv_so_ops.open_symbol_file_object = open_symbol_file_object;
   frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;
-
-  /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
-  current_target_so_ops = &frv_so_ops;
+  frv_so_ops.bfd_open = solib_bfd_open;
 
   /* Debug this file's internals.  */
-  deprecated_add_show_from_set
-    (add_set_cmd ("solib-frv", class_maintenance, var_zinteger,
-                 &solib_frv_debug,
-"Set internal debugging of shared library code for FR-V.\n"
-"When non-zero, FR-V solib specific internal debugging is enabled.",
-                 &setdebuglist),
-     &showdebuglist);
+  add_setshow_zinteger_cmd ("solib-frv", class_maintenance,
+                           &solib_frv_debug, _("\
+Set internal debugging of shared library code for FR-V."), _("\
+Show internal debugging of shared library code for FR-V."), _("\
+When non-zero, FR-V solib specific internal debugging is enabled."),
+                           NULL,
+                           NULL, /* FIXME: i18n: */
+                           &setdebuglist, &showdebuglist);
 }
This page took 0.038642 seconds and 4 git commands to generate.