Replace solib_global_lookup with gdbarch_iterate_over_objfiles_in_search_order
[deliverable/binutils-gdb.git] / gdb / solib-svr4.c
index 8cd5b7d8e7031fd13ea913ac232853b8eef2e2e4..dc635491058a7af4d974bfd0e4403eabdb6bc935 100644 (file)
@@ -51,6 +51,10 @@ static int svr4_have_link_map_offsets (void);
 static void svr4_relocate_main_executable (void);
 static void svr4_free_library_list (void *p_list);
 static void probes_table_remove_objfile_probes (struct objfile *objfile);
+static void svr4_iterate_over_objfiles_in_search_order (
+  struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype *cb,
+  void *cb_data, struct objfile *objfile);
+
 
 /* On SVR4 systems, a list of symbols in the dynamic linker where
    GDB can try to place a breakpoint to monitor shared library
@@ -234,7 +238,7 @@ lm_addr_check (const struct so_list *so, bfd *abfd)
       if (dyninfo_sect == NULL)
        goto set_addr;
 
-      dynaddr = bfd_section_vma (abfd, dyninfo_sect);
+      dynaddr = bfd_section_vma (dyninfo_sect);
 
       if (dynaddr + l_addr != l_dynaddr)
        {
@@ -559,7 +563,7 @@ find_program_interpreter (void)
      interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
      if (interp_sect != NULL)
       {
-       int sect_size = bfd_section_size (exec_bfd, interp_sect);
+       int sect_size = bfd_section_size (interp_sect);
 
        gdb::byte_vector buf (sect_size);
        bfd_get_section_contents (exec_bfd, interp_sect, buf.data (), 0,
@@ -618,12 +622,12 @@ scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
         such fallback to the file VMA address without the possibility of
         having the section relocated to its actual in-memory address.  */
 
-      dyn_addr = bfd_section_vma (abfd, sect);
+      dyn_addr = bfd_section_vma (sect);
     }
 
   /* Read in .dynamic from the BFD.  We will get the actual value
      from memory later.  */
-  sect_size = bfd_section_size (abfd, sect);
+  sect_size = bfd_section_size (sect);
   buf = bufstart = (gdb_byte *) alloca (sect_size);
   if (!bfd_get_section_contents (abfd, sect,
                                 buf, 0, sect_size))
@@ -1756,7 +1760,7 @@ solib_event_probe_action (struct probe_and_action *pa)
        arg2: struct link_map *new (optional, for incremental updates)  */
   try
     {
-      probe_argc = pa->prob->get_argument_count (frame);
+      probe_argc = pa->prob->get_argument_count (get_frame_arch (frame));
     }
   catch (const gdb_exception_error &ex)
     {
@@ -2061,6 +2065,71 @@ svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
   svr4_update_solib_event_breakpoints ();
 }
 
+/* Find all the glibc named probes.  Only if all of the probes are found, then
+   create them and return true.  Otherwise return false.  If WITH_PREFIX is set
+   then add "rtld" to the front of the probe names.  */
+static bool
+svr4_find_and_create_probe_breakpoints (svr4_info *info,
+                                       struct gdbarch *gdbarch,
+                                       struct obj_section *os,
+                                       bool with_prefix)
+{
+  std::vector<probe *> probes[NUM_PROBES];
+
+  for (int i = 0; i < NUM_PROBES; i++)
+    {
+      const char *name = probe_info[i].name;
+      char buf[32];
+
+      /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4 shipped with an early
+        version of the probes code in which the probes' names were prefixed
+        with "rtld_" and the "map_failed" probe did not exist.  The locations
+        of the probes are otherwise the same, so we check for probes with
+        prefixed names if probes with unprefixed names are not present.  */
+      if (with_prefix)
+       {
+         xsnprintf (buf, sizeof (buf), "rtld_%s", name);
+         name = buf;
+       }
+
+      probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
+
+      /* The "map_failed" probe did not exist in early
+        versions of the probes code in which the probes'
+        names were prefixed with "rtld_".  */
+      if (with_prefix && streq (name, "rtld_map_failed"))
+       continue;
+
+      /* Ensure at least one probe for the current name was found.  */
+      if (probes[i].empty ())
+       return false;
+
+      /* Ensure probe arguments can be evaluated.  */
+      for (probe *p : probes[i])
+       {
+         if (!p->can_evaluate_arguments ())
+           return false;
+         /* This will fail if the probe is invalid.  This has been seen on Arm
+            due to references to symbols that have been resolved away.  */
+         try
+           {
+             p->get_argument_count (gdbarch);
+           }
+         catch (const gdb_exception_error &ex)
+           {
+             exception_print (gdb_stderr, ex);
+             warning (_("Initializing probes-based dynamic linker interface "
+                        "failed.\nReverting to original interface."));
+             return false;
+           }
+       }
+    }
+
+  /* All probes found.  Now create them.  */
+  svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
+  return true;
+}
+
 /* Both the SunOS and the SVR4 dynamic linkers call a marker function
    before and after mapping and unmapping shared libraries.  The sole
    purpose of this method is to allow debuggers to set a breakpoint so
@@ -2077,74 +2146,12 @@ static void
 svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
                                     CORE_ADDR address)
 {
-  struct obj_section *os;
-
-  os = find_pc_section (address);
-  if (os != NULL)
-    {
-      int with_prefix;
-
-      for (with_prefix = 0; with_prefix <= 1; with_prefix++)
-       {
-         std::vector<probe *> probes[NUM_PROBES];
-         int all_probes_found = 1;
-         int checked_can_use_probe_arguments = 0;
-
-         for (int i = 0; i < NUM_PROBES; i++)
-           {
-             const char *name = probe_info[i].name;
-             probe *p;
-             char buf[32];
-
-             /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4
-                shipped with an early version of the probes code in
-                which the probes' names were prefixed with "rtld_"
-                and the "map_failed" probe did not exist.  The
-                locations of the probes are otherwise the same, so
-                we check for probes with prefixed names if probes
-                with unprefixed names are not present.  */
-             if (with_prefix)
-               {
-                 xsnprintf (buf, sizeof (buf), "rtld_%s", name);
-                 name = buf;
-               }
+  struct obj_section *os = find_pc_section (address);
 
-             probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
-
-             /* The "map_failed" probe did not exist in early
-                versions of the probes code in which the probes'
-                names were prefixed with "rtld_".  */
-             if (strcmp (name, "rtld_map_failed") == 0)
-               continue;
-
-             if (probes[i].empty ())
-               {
-                 all_probes_found = 0;
-                 break;
-               }
-
-             /* Ensure probe arguments can be evaluated.  */
-             if (!checked_can_use_probe_arguments)
-               {
-                 p = probes[i][0];
-                 if (!p->can_evaluate_arguments ())
-                   {
-                     all_probes_found = 0;
-                     break;
-                   }
-                 checked_can_use_probe_arguments = 1;
-               }
-           }
-
-         if (all_probes_found)
-           svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
-
-         if (all_probes_found)
-           return;
-       }
-    }
-
-  create_solib_event_breakpoint (gdbarch, address);
+  if (os == nullptr
+      || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
+         && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
+    create_solib_event_breakpoint (gdbarch, address);
 }
 
 /* Helper function for gdb_bfd_lookup_symbol.  */
@@ -2252,20 +2259,18 @@ enable_break (struct svr4_info *info, int from_tty)
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
          if (interp_sect)
            {
-             info->interp_text_sect_low =
-               bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
-             info->interp_text_sect_high =
-               info->interp_text_sect_low
-               + bfd_section_size (tmp_bfd, interp_sect);
+             info->interp_text_sect_low
+               = bfd_section_vma (interp_sect) + load_addr;
+             info->interp_text_sect_high
+               = info->interp_text_sect_low + bfd_section_size (interp_sect);
            }
          interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
          if (interp_sect)
            {
-             info->interp_plt_sect_low =
-               bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
-             info->interp_plt_sect_high =
-               info->interp_plt_sect_low
-               + bfd_section_size (tmp_bfd, interp_sect);
+             info->interp_plt_sect_low
+               = bfd_section_vma (interp_sect) + load_addr;
+             info->interp_plt_sect_high
+               = info->interp_plt_sect_low + bfd_section_size (interp_sect);
            }
 
          svr4_create_solib_event_breakpoints (info, target_gdbarch (), sym_addr);
@@ -2389,20 +2394,18 @@ enable_break (struct svr4_info *info, int from_tty)
       interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
       if (interp_sect)
        {
-         info->interp_text_sect_low =
-           bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
-         info->interp_text_sect_high =
-           info->interp_text_sect_low
-           + bfd_section_size (tmp_bfd.get (), interp_sect);
+         info->interp_text_sect_low
+           = bfd_section_vma (interp_sect) + load_addr;
+         info->interp_text_sect_high
+           = info->interp_text_sect_low + bfd_section_size (interp_sect);
        }
       interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
       if (interp_sect)
        {
-         info->interp_plt_sect_low =
-           bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
-         info->interp_plt_sect_high =
-           info->interp_plt_sect_low
-           + bfd_section_size (tmp_bfd.get (), interp_sect);
+         info->interp_plt_sect_low
+           = bfd_section_vma (interp_sect) + load_addr;
+         info->interp_plt_sect_high
+           = info->interp_plt_sect_low + bfd_section_size (interp_sect);
        }
 
       /* Now try to set a breakpoint in the dynamic linker.  */
@@ -2730,7 +2733,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
                      CORE_ADDR filesz;
 
-                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                     content2 = (bfd_section_flags (plt2_asect)
                                  & SEC_HAS_CONTENTS) != 0;
 
                      filesz = extract_unsigned_integer (buf_filesz_p, 4,
@@ -2739,9 +2742,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      /* PLT2_ASECT is from on-disk file (exec_bfd) while
                         FILESZ is from the in-memory image.  */
                      if (content2)
-                       filesz += bfd_get_section_size (plt2_asect);
+                       filesz += bfd_section_size (plt2_asect);
                      else
-                       filesz -= bfd_get_section_size (plt2_asect);
+                       filesz -= bfd_section_size (plt2_asect);
 
                      store_unsigned_integer (buf_filesz_p, 4, byte_order,
                                              filesz);
@@ -2864,7 +2867,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      gdb_byte *buf_filesz_p = (gdb_byte *) &phdrp->p_filesz;
                      CORE_ADDR filesz;
 
-                     content2 = (bfd_get_section_flags (exec_bfd, plt2_asect)
+                     content2 = (bfd_section_flags (plt2_asect)
                                  & SEC_HAS_CONTENTS) != 0;
 
                      filesz = extract_unsigned_integer (buf_filesz_p, 8,
@@ -2873,9 +2876,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                      /* PLT2_ASECT is from on-disk file (exec_bfd) while
                         FILESZ is from the in-memory image.  */
                      if (content2)
-                       filesz += bfd_get_section_size (plt2_asect);
+                       filesz += bfd_section_size (plt2_asect);
                      else
-                       filesz -= bfd_get_section_size (plt2_asect);
+                       filesz -= bfd_section_size (plt2_asect);
 
                      store_unsigned_integer (buf_filesz_p, 8, byte_order,
                                              filesz);
@@ -2969,8 +2972,7 @@ svr4_relocate_main_executable (void)
 
       for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
        exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
-                                 (bfd_section_vma (exec_bfd, asect)
-                                  + displacement));
+                                 bfd_section_vma (asect) + displacement);
     }
 }
 
@@ -3104,6 +3106,8 @@ set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
   ops->fetch_link_map_offsets = flmo;
 
   set_solib_ops (gdbarch, &svr4_so_ops);
+  set_gdbarch_iterate_over_objfiles_in_search_order
+    (gdbarch, svr4_iterate_over_objfiles_in_search_order);
 }
 
 /* Fetch a link_map_offsets structure using the architecture-specific
@@ -3202,31 +3206,45 @@ svr4_lp64_fetch_link_map_offsets (void)
 
 struct target_so_ops svr4_so_ops;
 
-/* Lookup global symbol for ELF DSOs linked with -Bsymbolic.  Those DSOs have a
+/* Search order for ELF DSOs linked with -Bsymbolic.  Those DSOs have a
    different rule for symbol lookup.  The lookup begins here in the DSO, not in
    the main executable.  */
 
-static struct block_symbol
-elf_lookup_lib_symbol (struct objfile *objfile,
-                      const char *name,
-                      const domain_enum domain)
+static void
+svr4_iterate_over_objfiles_in_search_order
+  (struct gdbarch *gdbarch,
+   iterate_over_objfiles_in_search_order_cb_ftype *cb,
+   void *cb_data, struct objfile *current_objfile)
 {
-  bfd *abfd;
-
-  if (objfile == symfile_objfile)
-    abfd = exec_bfd;
-  else
+  bool checked_current_objfile = false;
+  if (current_objfile != nullptr)
     {
-      /* OBJFILE should have been passed as the non-debug one.  */
-      gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+      bfd *abfd;
 
-      abfd = objfile->obfd;
-    }
+      if (current_objfile->separate_debug_objfile_backlink != nullptr)
+        current_objfile = current_objfile->separate_debug_objfile_backlink;
 
-  if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL, NULL) != 1)
-    return {};
+      if (current_objfile == symfile_objfile)
+       abfd = exec_bfd;
+      else
+       abfd = current_objfile->obfd;
 
-  return lookup_global_symbol_from_objfile (objfile, name, domain);
+      if (abfd != nullptr &&
+         scan_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
+       {
+         checked_current_objfile = true;
+         if (cb (current_objfile, cb_data) != 0)
+           return;
+       }
+    }
+
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      if (checked_current_objfile && objfile == current_objfile)
+       continue;
+      if (cb (objfile, cb_data) != 0)
+       return;
+    }
 }
 
 void
@@ -3243,7 +3261,6 @@ _initialize_svr4_solib (void)
   svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
   svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
   svr4_so_ops.bfd_open = solib_bfd_open;
-  svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
   svr4_so_ops.same = svr4_same;
   svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
   svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
This page took 0.02842 seconds and 4 git commands to generate.