gdb_curses.h: Undefine KEY_EVENT before including curses
[deliverable/binutils-gdb.git] / gdb / elfread.c
index 067c77f26dcc354f9e8ce08055044c535109549c..d825d9a6e9a969f66cf923020f51f6dab4c0844f 100644 (file)
@@ -1,8 +1,6 @@
 /* Read ELF (Executable and Linking Format) object files for GDB.
 
-   Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2012 Free Software Foundation, Inc.
 
    Written by Fred Fish at Cygnus Support.
 
 #include "demangle.h"
 #include "psympriv.h"
 #include "filenames.h"
+#include "probe.h"
+#include "arch-utils.h"
 #include "gdbtypes.h"
 #include "value.h"
 #include "infcall.h"
 #include "gdbthread.h"
 #include "regcache.h"
+#include "bcache.h"
 
 extern void _initialize_elfread (void);
 
@@ -61,6 +62,10 @@ struct elfinfo
     asection *mdebugsect;      /* Section pointer for .mdebug section */
   };
 
+/* Per-objfile data for probe info.  */
+
+static const struct objfile_data *probe_key = NULL;
+
 static void free_elfinfo (void *);
 
 /* Minimal symbols located at the GOT entries for .plt - that is the real
@@ -143,7 +148,7 @@ elf_symfile_segments (bfd *abfd)
         binaries are not relocatable.  */
       if (bfd_get_section_size (sect) > 0 && j == num_segments
          && (bfd_get_section_flags (abfd, sect) & SEC_LOAD) != 0)
-       warning (_("Loadable segment \"%s\" outside of ELF segments"),
+       warning (_("Loadable section \"%s\" outside of ELF segments"),
                 bfd_section_name (abfd, sect));
     }
 
@@ -240,8 +245,8 @@ elf_symtab_read (struct objfile *objfile, int type,
      seen any section info for it yet.  */
   asymbol *filesym = 0;
   /* Name of filesym.  This is either a constant string or is saved on
-     the objfile's obstack.  */
-  char *filesymname = "";
+     the objfile's filename cache.  */
+  const char *filesymname = "";
   struct dbx_symfile_info *dbx = objfile->deprecated_sym_stab_info;
   int stripped = (bfd_get_symcount (objfile->obfd) == 0);
 
@@ -303,6 +308,23 @@ elf_symtab_read (struct objfile *objfile, int type,
          if (!sect)
            continue;
 
+         /* On ia64-hpux, we have discovered that the system linker
+            adds undefined symbols with nonzero addresses that cannot
+            be right (their address points inside the code of another
+            function in the .text section).  This creates problems
+            when trying to determine which symbol corresponds to
+            a given address.
+
+            We try to detect those buggy symbols by checking which
+            section we think they correspond to.  Normally, PLT symbols
+            are stored inside their own section, and the typical name
+            for that section is ".plt".  So, if there is a ".plt"
+            section, and yet the section name of our symbol does not
+            start with ".plt", we ignore that symbol.  */
+         if (strncmp (sect->name, ".plt", 4) != 0
+             && bfd_get_section_by_name (abfd, ".plt") != NULL)
+           continue;
+
          symaddr += ANOFFSET (objfile->section_offsets, sect->index);
 
          msym = record_minimal_symbol
@@ -329,9 +351,8 @@ elf_symtab_read (struct objfile *objfile, int type,
              sectinfo = NULL;
            }
          filesym = sym;
-         filesymname =
-           obsavestring ((char *) filesym->name, strlen (filesym->name),
-                         &objfile->objfile_obstack);
+         filesymname = bcache (filesym->name, strlen (filesym->name) + 1,
+                               objfile->filename_cache);
        }
       else if (sym->flags & BSF_SECTION_SYM)
        continue;
@@ -905,7 +926,7 @@ elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p)
 static CORE_ADDR
 elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  char *name_at_pc;
+  const char *name_at_pc;
   CORE_ADDR start_at_pc, address;
   struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
   struct value *function, *address_val;
@@ -980,6 +1001,9 @@ elf_gnu_ifunc_resolver_stop (struct breakpoint *b)
                                           prev_frame_id,
                                           bp_gnu_ifunc_resolver_return);
 
+      /* set_momentary_breakpoint invalidates PREV_FRAME.  */
+      prev_frame = NULL;
+
       /* Add new b_return to the ring list b->related_breakpoint.  */
       gdb_assert (b_return->related_breakpoint == b_return);
       b_return->related_breakpoint = b->related_breakpoint;
@@ -1105,6 +1129,9 @@ static char *
 build_id_to_debug_filename (struct build_id *build_id)
 {
   char *link, *debugdir, *retval = NULL;
+  VEC (char_ptr) *debugdir_vec;
+  struct cleanup *back_to;
+  int ix;
 
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
   link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
@@ -1113,22 +1140,18 @@ build_id_to_debug_filename (struct build_id *build_id)
   /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
      cause "/.build-id/..." lookups.  */
 
-  debugdir = debug_file_directory;
-  do
+  debugdir_vec = dirnames_to_char_ptr_vec (debug_file_directory);
+  back_to = make_cleanup_free_char_ptr_vec (debugdir_vec);
+
+  for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix)
     {
-      char *s, *debugdir_end;
+      size_t debugdir_len = strlen (debugdir);
       gdb_byte *data = build_id->data;
       size_t size = build_id->size;
+      char *s;
 
-      while (*debugdir == DIRNAME_SEPARATOR)
-       debugdir++;
-
-      debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
-      if (debugdir_end == NULL)
-       debugdir_end = &debugdir[strlen (debugdir)];
-
-      memcpy (link, debugdir, debugdir_end - debugdir);
-      s = &link[debugdir_end - debugdir];
+      memcpy (link, debugdir, debugdir_len);
+      s = &link[debugdir_len];
       s += sprintf (s, "/.build-id/");
       if (size > 0)
        {
@@ -1153,11 +1176,9 @@ build_id_to_debug_filename (struct build_id *build_id)
 
       if (retval != NULL)
        break;
-
-      debugdir = debugdir_end;
     }
-  while (*debugdir != 0);
 
+  do_cleanups (back_to);
   return retval;
 }
 
@@ -1561,7 +1582,117 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst)
     complaint (&symfile_complaints,
               _("elf/stab section information missing for %s"), filename);
 }
+
+/* Implementation of `sym_get_probes', as documented in symfile.h.  */
+
+static VEC (probe_p) *
+elf_get_probes (struct objfile *objfile)
+{
+  VEC (probe_p) *probes_per_objfile;
+
+  /* Have we parsed this objfile's probes already?  */
+  probes_per_objfile = objfile_data (objfile, probe_key);
+
+  if (!probes_per_objfile)
+    {
+      int ix;
+      const struct probe_ops *probe_ops;
+
+      /* Here we try to gather information about all types of probes from the
+        objfile.  */
+      for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, probe_ops);
+          ix++)
+       probe_ops->get_probes (&probes_per_objfile, objfile);
+
+      if (probes_per_objfile == NULL)
+       {
+         VEC_reserve (probe_p, probes_per_objfile, 1);
+         gdb_assert (probes_per_objfile != NULL);
+       }
+
+      set_objfile_data (objfile, probe_key, probes_per_objfile);
+    }
+
+  return probes_per_objfile;
+}
+
+/* Implementation of `sym_get_probe_argument_count', as documented in
+   symfile.h.  */
+
+static unsigned
+elf_get_probe_argument_count (struct objfile *objfile,
+                             struct probe *probe)
+{
+  return probe->pops->get_probe_argument_count (probe, objfile);
+}
+
+/* Implementation of `sym_evaluate_probe_argument', as documented in
+   symfile.h.  */
+
+static struct value *
+elf_evaluate_probe_argument (struct objfile *objfile,
+                            struct probe *probe,
+                            unsigned n)
+{
+  return probe->pops->evaluate_probe_argument (probe, objfile, n);
+}
+
+/* Implementation of `sym_compile_to_ax', as documented in symfile.h.  */
+
+static void
+elf_compile_to_ax (struct objfile *objfile,
+                  struct probe *probe,
+                  struct agent_expr *expr,
+                  struct axs_value *value,
+                  unsigned n)
+{
+  probe->pops->compile_to_ax (probe, objfile, expr, value, n);
+}
+
+/* Implementation of `sym_relocate_probe', as documented in symfile.h.  */
+
+static void
+elf_symfile_relocate_probe (struct objfile *objfile,
+                           struct section_offsets *new_offsets,
+                           struct section_offsets *delta)
+{
+  int ix;
+  VEC (probe_p) *probes = objfile_data (objfile, probe_key);
+  struct probe *probe;
+
+  for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
+    probe->pops->relocate (probe, ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
+}
+
+/* Helper function used to free the space allocated for storing SystemTap
+   probe information.  */
+
+static void
+probe_key_free (struct objfile *objfile, void *d)
+{
+  int ix;
+  VEC (probe_p) *probes = d;
+  struct probe *probe;
+
+  for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
+    probe->pops->destroy (probe);
+
+  VEC_free (probe_p, probes);
+}
+
 \f
+
+/* Implementation `sym_probe_fns', as documented in symfile.h.  */
+
+static const struct sym_probe_fns elf_probe_fns =
+{
+  elf_get_probes,              /* sym_get_probes */
+  elf_get_probe_argument_count,        /* sym_get_probe_argument_count */
+  elf_evaluate_probe_argument, /* sym_evaluate_probe_argument */
+  elf_compile_to_ax,           /* sym_compile_to_ax */
+  elf_symfile_relocate_probe,  /* sym_relocate_probe */
+};
+
 /* Register that we are able to handle ELF object file formats.  */
 
 static const struct sym_fns elf_sym_fns =
@@ -1576,6 +1707,7 @@ static const struct sym_fns elf_sym_fns =
   elf_symfile_segments,                /* Get segment information from a file.  */
   NULL,
   default_symfile_relocate,    /* Relocate a debug section.  */
+  &elf_probe_fns,              /* sym_probe_fns */
   &psym_functions
 };
 
@@ -1594,6 +1726,7 @@ static const struct sym_fns elf_sym_fns_lazy_psyms =
   elf_symfile_segments,                /* Get segment information from a file.  */
   NULL,
   default_symfile_relocate,    /* Relocate a debug section.  */
+  &elf_probe_fns,              /* sym_probe_fns */
   &psym_functions
 };
 
@@ -1611,6 +1744,7 @@ static const struct sym_fns elf_sym_fns_gdb_index =
   elf_symfile_segments,                /* Get segment information from a file.  */
   NULL,
   default_symfile_relocate,    /* Relocate a debug section.  */
+  &elf_probe_fns,              /* sym_probe_fns */
   &dwarf2_gdb_index_functions
 };
 
@@ -1627,6 +1761,7 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns =
 void
 _initialize_elfread (void)
 {
+  probe_key = register_objfile_data_with_cleanup (NULL, probe_key_free);
   add_symtab_fns (&elf_sym_fns);
 
   elf_objfile_gnu_ifunc_cache_data = register_objfile_data ();
This page took 0.026761 seconds and 4 git commands to generate.