Fix "nosharedlibrary + continue + shared lib event" crash
[binutils-gdb.git] / gdb / solib-svr4.c
index 358d7e7cc6cddc8dcffd42043ea7797b5b7a75e2..2c79dfec2bb60d68e90995ebff38133aa0ee631d 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2018 Free Software Foundation, Inc.
+   Copyright (C) 1990-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -50,6 +50,7 @@ static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 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);
 
 /* On SVR4 systems, a list of symbols in the dynamic linker where
    GDB can try to place a breakpoint to monitor shared library
@@ -153,8 +154,12 @@ svr4_same_1 (const char *gdb_so_name, const char *inferior_so_name)
       && strcmp (inferior_so_name, "/lib/ld.so.1") == 0)
     return 1;
 
-  /* Similarly, we observed the same issue with sparc64, but with
+  /* Similarly, we observed the same issue with amd64 and sparcv9, but with
      different locations.  */
+  if (strcmp (gdb_so_name, "/usr/lib/amd64/ld.so.1") == 0
+      && strcmp (inferior_so_name, "/lib/amd64/ld.so.1") == 0)
+    return 1;
+
   if (strcmp (gdb_so_name, "/usr/lib/sparcv9/ld.so.1") == 0
       && strcmp (inferior_so_name, "/lib/sparcv9/ld.so.1") == 0)
     return 1;
@@ -865,16 +870,15 @@ solib_svr4_r_map (struct svr4_info *info)
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
   CORE_ADDR addr = 0;
 
-  TRY
+  try
     {
       addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
                                         ptr_type);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
     }
-  END_CATCH
 
   return addr;
 }
@@ -902,7 +906,7 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   ULONGEST version = 0;
 
-  TRY
+  try
     {
       /* Check version, and return zero if `struct r_debug' doesn't have
         the r_ldsomap member.  */
@@ -910,11 +914,10 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
        = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
                                        lmo->r_version_size, byte_order);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
     }
-  END_CATCH
 
   if (version < 2 || lmo->r_ldsomap_offset == -1)
     return 0;
@@ -1023,6 +1026,14 @@ struct svr4_library_list
   CORE_ADDR main_lm;
 };
 
+/* This module's 'free_objfile' observer.  */
+
+static void
+svr4_free_objfile_observer (struct objfile *objfile)
+{
+  probes_table_remove_objfile_probes (objfile);
+}
+
 /* Implementation for target_so_ops.free_so.  */
 
 static void
@@ -1194,8 +1205,10 @@ static const struct gdb_xml_element svr4_library_list_elements[] =
 static int
 svr4_parse_libraries (const char *document, struct svr4_library_list *list)
 {
-  struct cleanup *back_to = make_cleanup (svr4_free_library_list,
-                                         &list->head);
+  auto cleanup = make_scope_exit ([&] ()
+    {
+      svr4_free_library_list (&list->head);
+    });
 
   memset (list, 0, sizeof (*list));
   list->tailp = &list->head;
@@ -1203,11 +1216,10 @@ svr4_parse_libraries (const char *document, struct svr4_library_list *list)
                           svr4_library_list_elements, document, list) == 0)
     {
       /* Parsed successfully, keep the result.  */
-      discard_cleanups (back_to);
+      cleanup.release ();
       return 1;
     }
 
-  do_cleanups (back_to);
   return 0;
 }
 
@@ -1370,7 +1382,6 @@ svr4_current_sos_direct (struct svr4_info *info)
   CORE_ADDR lm;
   struct so_list *head = NULL;
   struct so_list **link_ptr = &head;
-  struct cleanup *back_to;
   int ignore_first;
   struct svr4_library_list library_list;
 
@@ -1408,7 +1419,10 @@ svr4_current_sos_direct (struct svr4_info *info)
   else
     ignore_first = 1;
 
-  back_to = make_cleanup (svr4_free_library_list, &head);
+  auto cleanup = make_scope_exit ([&] ()
+    {
+      svr4_free_library_list (&head);
+    });
 
   /* Walk the inferior's link map list, and build our list of
      `struct so_list' nodes.  */
@@ -1424,7 +1438,7 @@ svr4_current_sos_direct (struct svr4_info *info)
   if (lm)
     svr4_read_so_list (lm, 0, &link_ptr, 0);
 
-  discard_cleanups (back_to);
+  cleanup.release ();
 
   if (head == NULL)
     return svr4_default_sos ();
@@ -1544,6 +1558,11 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
   if (objfile == symfile_objfile)
     return info->main_lm_addr;
 
+  /* If OBJFILE is a separate debug object file, look for the
+     original object file.  */
+  if (objfile->separate_debug_objfile_backlink != NULL)
+    objfile = objfile->separate_debug_objfile_backlink;
+
   /* The other link map addresses may be found by examining the list
      of shared libraries.  */
   for (so = master_so_list (); so; so = so->next)
@@ -1626,6 +1645,9 @@ struct probe_and_action
 
   /* The action.  */
   enum probe_action action;
+
+  /* The objfile where this probe was found.  */
+  struct objfile *objfile;
 };
 
 /* Returns a hash code for the probe_and_action referenced by p.  */
@@ -1650,11 +1672,37 @@ equal_probe_and_action (const void *p1, const void *p2)
   return pa1->address == pa2->address;
 }
 
+/* Traversal function for probes_table_remove_objfile_probes.  */
+
+static int
+probes_table_htab_remove_objfile_probes (void **slot, void *info)
+{
+  probe_and_action *pa = (probe_and_action *) *slot;
+  struct objfile *objfile = (struct objfile *) info;
+
+  if (pa->objfile == objfile)
+    htab_clear_slot (get_svr4_info ()->probes_table, slot);
+
+  return 1;
+}
+
+/* Remove all probes that belong to OBJFILE from the probes table.  */
+
+static void
+probes_table_remove_objfile_probes (struct objfile *objfile)
+{
+  svr4_info *info = get_svr4_info ();
+  if (info->probes_table != nullptr)
+    htab_traverse_noresize (info->probes_table,
+                           probes_table_htab_remove_objfile_probes, objfile);
+}
+
 /* Register a solib event probe and its associated action in the
    probes table.  */
 
 static void
-register_solib_event_probe (probe *prob, CORE_ADDR address,
+register_solib_event_probe (struct objfile *objfile,
+                           probe *prob, CORE_ADDR address,
                            enum probe_action action)
 {
   struct svr4_info *info = get_svr4_info ();
@@ -1667,7 +1715,6 @@ register_solib_event_probe (probe *prob, CORE_ADDR address,
                                            equal_probe_and_action,
                                            xfree, xcalloc, xfree);
 
-  lookup.prob = prob;
   lookup.address = address;
   slot = htab_find_slot (info->probes_table, &lookup, INSERT);
   gdb_assert (*slot == HTAB_EMPTY_ENTRY);
@@ -1676,6 +1723,7 @@ register_solib_event_probe (probe *prob, CORE_ADDR address,
   pa->prob = prob;
   pa->address = address;
   pa->action = action;
+  pa->objfile = objfile;
 
   *slot = pa;
 }
@@ -1720,16 +1768,15 @@ solib_event_probe_action (struct probe_and_action *pa)
        arg0: Lmid_t lmid (mandatory)
        arg1: struct r_debug *debug_base (mandatory)
        arg2: struct link_map *new (optional, for incremental updates)  */
-  TRY
+  try
     {
       probe_argc = pa->prob->get_argument_count (frame);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stderr, ex);
       probe_argc = 0;
     }
-  END_CATCH
 
   /* If get_argument_count throws an exception, probe_argc will be set
      to zero.  However, if pa->prob does not have arguments, then
@@ -1822,7 +1869,7 @@ solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
    ones set up for the probes-based interface are adequate.  */
 
 static void
-disable_probes_interface_cleanup (void *arg)
+disable_probes_interface ()
 {
   struct svr4_info *info = get_svr4_info ();
 
@@ -1843,7 +1890,6 @@ svr4_handle_solib_event (void)
   struct svr4_info *info = get_svr4_info ();
   struct probe_and_action *pa;
   enum probe_action action;
-  struct cleanup *old_chain;
   struct value *val = NULL;
   CORE_ADDR pc, debug_base, lm = 0;
   struct frame_info *frame = get_current_frame ();
@@ -1854,26 +1900,20 @@ svr4_handle_solib_event (void)
 
   /* If anything goes wrong we revert to the original linker
      interface.  */
-  old_chain = make_cleanup (disable_probes_interface_cleanup, NULL);
+  auto cleanup = make_scope_exit (disable_probes_interface);
 
   pc = regcache_read_pc (get_current_regcache ());
   pa = solib_event_probe_at (info, pc);
   if (pa == NULL)
-    {
-      do_cleanups (old_chain);
-      return;
-    }
+    return;
 
   action = solib_event_probe_action (pa);
   if (action == PROBES_INTERFACE_FAILED)
-    {
-      do_cleanups (old_chain);
-      return;
-    }
+    return;
 
   if (action == DO_NOTHING)
     {
-      discard_cleanups (old_chain);
+      cleanup.release ();
       return;
     }
 
@@ -1891,37 +1931,27 @@ svr4_handle_solib_event (void)
     scoped_restore inhibit_updates
       = inhibit_section_map_updates (current_program_space);
 
-    TRY
+    try
       {
        val = pa->prob->evaluate_argument (1, frame);
       }
-    CATCH (ex, RETURN_MASK_ERROR)
+    catch (const gdb_exception_error &ex)
       {
        exception_print (gdb_stderr, ex);
        val = NULL;
       }
-    END_CATCH
 
     if (val == NULL)
-      {
-       do_cleanups (old_chain);
-       return;
-      }
+      return;
 
     debug_base = value_as_address (val);
     if (debug_base == 0)
-      {
-       do_cleanups (old_chain);
-       return;
-      }
+      return;
 
     /* Always locate the debug struct, in case it moved.  */
     info->debug_base = 0;
     if (locate_base (info) == 0)
-      {
-       do_cleanups (old_chain);
-       return;
-      }
+      return;
 
     /* GDB does not currently support libraries loaded via dlmopen
        into namespaces other than the initial one.  We must ignore
@@ -1932,17 +1962,15 @@ svr4_handle_solib_event (void)
 
     if (action == UPDATE_OR_RELOAD)
       {
-       TRY
+       try
          {
            val = pa->prob->evaluate_argument (2, frame);
          }
-       CATCH (ex, RETURN_MASK_ERROR)
+       catch (const gdb_exception_error &ex)
          {
            exception_print (gdb_stderr, ex);
-           do_cleanups (old_chain);
            return;
          }
-       END_CATCH
 
        if (val != NULL)
          lm = value_as_address (val);
@@ -1964,13 +1992,10 @@ svr4_handle_solib_event (void)
   if (action == FULL_RELOAD)
     {
       if (!solist_update_full (info))
-       {
-         do_cleanups (old_chain);
-         return;
-       }
+       return;
     }
 
-  discard_cleanups (old_chain);
+  cleanup.release ();
 }
 
 /* Helper function for svr4_update_solib_event_breakpoints.  */
@@ -2043,7 +2068,7 @@ svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
          CORE_ADDR address = p->get_relocated_address (objfile);
 
          create_solib_event_breakpoint (gdbarch, address);
-         register_solib_event_probe (p, address, action);
+         register_solib_event_probe (objfile, p, address, action);
        }
     }
 
@@ -2287,14 +2312,13 @@ enable_break (struct svr4_info *info, int from_tty)
          mechanism to find the dynamic linker's base address.  */
 
       gdb_bfd_ref_ptr tmp_bfd;
-      TRY
+      try
         {
          tmp_bfd = solib_bfd_open (interp_name);
        }
-      CATCH (ex, RETURN_MASK_ALL)
+      catch (const gdb_exception &ex)
        {
        }
-      END_CATCH
 
       if (tmp_bfd == NULL)
        goto bkpt_at_symbol;
@@ -2471,28 +2495,20 @@ enable_break (struct svr4_info *info, int from_tty)
   return 0;
 }
 
-/* Read the ELF program headers from ABFD.  Return the contents and
-   set *PHDRS_SIZE to the size of the program headers.  */
+/* Read the ELF program headers from ABFD.  */
 
-static gdb_byte *
-read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
+static gdb::optional<gdb::byte_vector>
+read_program_headers_from_bfd (bfd *abfd)
 {
-  Elf_Internal_Ehdr *ehdr;
-  gdb_byte *buf;
-
-  ehdr = elf_elfheader (abfd);
-
-  *phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
-  if (*phdrs_size == 0)
-    return NULL;
+  Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
+  int phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
+  if (phdrs_size == 0)
+    return {};
 
-  buf = (gdb_byte *) xmalloc (*phdrs_size);
+  gdb::byte_vector buf (phdrs_size);
   if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
-      || bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
-    {
-      xfree (buf);
-      return NULL;
-    }
+      || bfd_bread (buf.data (), phdrs_size, abfd) != phdrs_size)
+    return {};
 
   return buf;
 }
@@ -2586,16 +2602,15 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
 
   if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
     {
-      /* Be optimistic and clear OK only if GDB was able to verify the headers
+      /* Be optimistic and return 0 only if GDB was able to verify the headers
         really do not match.  */
-      int phdrs2_size, ok = 1;
-      gdb_byte *buf2;
       int arch_size;
 
       gdb::optional<gdb::byte_vector> phdrs_target
        = read_program_header (-1, &arch_size, NULL);
-      buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
-      if (phdrs_target && buf2 != NULL)
+      gdb::optional<gdb::byte_vector> phdrs_binary
+       = read_program_headers_from_bfd (exec_bfd);
+      if (phdrs_target && phdrs_binary)
        {
          enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
 
@@ -2612,9 +2627,9 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
             relocate BUF and BUF2 just by the EXEC_BFD vs. target memory
             content offset for the verification purpose.  */
 
-         if (phdrs_target->size () != phdrs2_size
+         if (phdrs_target->size () != phdrs_binary->size ()
              || bfd_get_arch_size (exec_bfd) != arch_size)
-           ok = 0;
+           return 0;
          else if (arch_size == 32
                   && phdrs_target->size () >= sizeof (Elf32_External_Phdr)
                   && phdrs_target->size () % sizeof (Elf32_External_Phdr) == 0)
@@ -2672,7 +2687,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                  phdrp = &((Elf32_External_Phdr *) phdrs_target->data ())[i];
                  buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                  buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
-                 phdr2p = &((Elf32_External_Phdr *) buf2)[i];
+                 phdr2p = &((Elf32_External_Phdr *) phdrs_binary->data ())[i];
 
                  /* PT_GNU_STACK is an exception by being never relocated by
                     prelink as its addresses are always zero.  */
@@ -2747,8 +2762,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                        continue;
                    }
 
-                 ok = 0;
-                 break;
+                 return 0;
                }
            }
          else if (arch_size == 64
@@ -2807,7 +2821,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                  phdrp = &((Elf64_External_Phdr *) phdrs_target->data ())[i];
                  buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
                  buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
-                 phdr2p = &((Elf64_External_Phdr *) buf2)[i];
+                 phdr2p = &((Elf64_External_Phdr *) phdrs_binary->data ())[i];
 
                  /* PT_GNU_STACK is an exception by being never relocated by
                     prelink as its addresses are always zero.  */
@@ -2882,18 +2896,12 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
                        continue;
                    }
 
-                 ok = 0;
-                 break;
+                 return 0;
                }
            }
          else
-           ok = 0;
+           return 0;
        }
-
-      xfree (buf2);
-
-      if (!ok)
-       return 0;
     }
 
   if (info_verbose)
@@ -3228,7 +3236,7 @@ elf_lookup_lib_symbol (struct objfile *objfile,
     }
 
   if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL, NULL) != 1)
-    return (struct block_symbol) {NULL, NULL};
+    return {};
 
   return lookup_global_symbol_from_objfile (objfile, name, domain);
 }
@@ -3254,4 +3262,6 @@ _initialize_svr4_solib (void)
   svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
   svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
   svr4_so_ops.handle_event = svr4_handle_solib_event;
+
+  gdb::observers::free_objfile.attach (svr4_free_objfile_observer);
 }