Use gdbpy_ref in gdbpy_lookup_symbol
[binutils-gdb.git] / gdb / psymtab.c
index 5d0aa1c61d580b95babee960161e8c70ea8898d4..e895828cf06ded1a9ca5506d1b479d6afddb6141 100644 (file)
@@ -1,6 +1,6 @@
 /* Partial symbol tables.
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "cp-support.h"
 #include "gdbcmd.h"
 
-#ifndef DEV_TTY
-#define DEV_TTY "/dev/tty"
-#endif
-
 struct psymbol_bcache
 {
   struct bcache *bcache;
@@ -315,7 +311,8 @@ find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
 
   if (objfile->psymtabs_addrmap != NULL)
     {
-      pst = addrmap_find (objfile->psymtabs_addrmap, pc);
+      pst = ((struct partial_symtab *)
+            addrmap_find (objfile->psymtabs_addrmap, pc));
       if (pst != NULL)
        {
          /* FIXME: addrmaps currently do not handle overlayed sections,
@@ -590,9 +587,6 @@ match_partial_symbol (struct objfile *objfile,
        {
          center = bottom + (top - bottom) / 2;
          gdb_assert (center < top);
-         if (!do_linear_search
-             && (SYMBOL_LANGUAGE (*center) == language_java))
-           do_linear_search = 1;
          if (ordered_compare (SYMBOL_SEARCH_NAME (*center), name) >= 0)
            top = center;
          else
@@ -641,7 +635,6 @@ psymtab_search_name (const char *name)
   switch (current_language->la_language)
     {
     case language_cplus:
-    case language_java:
       {
        if (strchr (name, '('))
          {
@@ -703,11 +696,6 @@ lookup_partial_symbol (struct objfile *objfile,
          if (!(center < top))
            internal_error (__FILE__, __LINE__,
                            _("failed internal consistency check"));
-         if (!do_linear_search
-             && SYMBOL_LANGUAGE (*center) == language_java)
-           {
-             do_linear_search = 1;
-           }
          if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center),
                                 search_name) >= 0)
            {
@@ -1223,7 +1211,8 @@ psymtab_to_fullname (struct partial_symtab *ps)
          if (ps->dirname == NULL || IS_ABSOLUTE_PATH (ps->filename))
            fullname = xstrdup (ps->filename);
          else
-           fullname = concat (ps->dirname, SLASH_STRING, ps->filename, NULL);
+           fullname = concat (ps->dirname, SLASH_STRING,
+                              ps->filename, (char *) NULL);
 
          back_to = make_cleanup (xfree, fullname);
          ps->fullname = rewrite_source_path (fullname);
@@ -1489,8 +1478,8 @@ const struct quick_symbol_functions psym_functions =
 static int
 compare_psymbols (const void *s1p, const void *s2p)
 {
-  struct partial_symbol *const *s1 = s1p;
-  struct partial_symbol *const *s2 = s2p;
+  struct partial_symbol *const *s1 = (struct partial_symbol * const*) s1p;
+  struct partial_symbol *const *s2 = (struct partial_symbol * const*) s2p;
 
   return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
                            SYMBOL_SEARCH_NAME (*s2));
@@ -1575,7 +1564,7 @@ psymbol_compare (const void *addr1, const void *addr2, int length)
   struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
   struct partial_symbol *sym2 = (struct partial_symbol *) addr2;
 
-  return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,
+  return (memcmp (&sym1->ginfo.value, &sym2->ginfo.value,
                   sizeof (sym1->ginfo.value)) == 0
          && sym1->ginfo.language == sym2->ginfo.language
           && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
@@ -1624,10 +1613,9 @@ psymbol_bcache_full (struct partial_symbol *sym,
                      struct psymbol_bcache *bcache,
                      int *added)
 {
-  return bcache_full (sym,
-                      sizeof (struct partial_symbol),
-                      bcache->bcache,
-                      added);
+  return ((const struct partial_symbol *)
+         bcache_full (sym, sizeof (struct partial_symbol), bcache->bcache,
+                      added));
 }
 
 /* Helper function, initialises partial symbol structure and stashes
@@ -1640,8 +1628,7 @@ static const struct partial_symbol *
 add_psymbol_to_bcache (const char *name, int namelength, int copy_name,
                       domain_enum domain,
                       enum address_class theclass,
-                      long val,        /* Value as a long */
-                      CORE_ADDR coreaddr,      /* Value as a CORE_ADDR */
+                      CORE_ADDR coreaddr,
                       enum language language, struct objfile *objfile,
                       int *added)
 {
@@ -1652,15 +1639,7 @@ add_psymbol_to_bcache (const char *name, int namelength, int copy_name,
      holes.  */
   memset (&psymbol, 0, sizeof (psymbol));
 
-  /* val and coreaddr are mutually exclusive, one of them *will* be zero.  */
-  if (val != 0)
-    {
-      SYMBOL_VALUE (&psymbol) = val;
-    }
-  else
-    {
-      SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
-    }
+  SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
   SYMBOL_SECTION (&psymbol) = -1;
   SYMBOL_SET_LANGUAGE (&psymbol, language, &objfile->objfile_obstack);
   PSYMBOL_DOMAIN (&psymbol) = domain;
@@ -1685,8 +1664,7 @@ extend_psymbol_list (struct psymbol_allocation_list *listp,
   if (listp->size == 0)
     {
       new_size = 255;
-      listp->list = (struct partial_symbol **)
-       xmalloc (new_size * sizeof (struct partial_symbol *));
+      listp->list = XNEWVEC (struct partial_symbol *, new_size);
     }
   else
     {
@@ -1716,6 +1694,8 @@ append_psymbol_to_list (struct psymbol_allocation_list *list,
 
 /* Add a symbol with a long value to a psymtab.
    Since one arg is a struct, we pass in a ptr and deref it (sigh).
+   The only value we need to store for psyms is an address.
+   For all other psyms pass zero for COREADDR.
    Return the partial symbol that has been added.  */
 
 void
@@ -1723,8 +1703,7 @@ add_psymbol_to_list (const char *name, int namelength, int copy_name,
                     domain_enum domain,
                     enum address_class theclass,
                     struct psymbol_allocation_list *list,
-                    long val,  /* Value as a long */
-                    CORE_ADDR coreaddr,        /* Value as a CORE_ADDR */
+                    CORE_ADDR coreaddr,
                     enum language language, struct objfile *objfile)
 {
   const struct partial_symbol *psym;
@@ -1733,7 +1712,7 @@ add_psymbol_to_list (const char *name, int namelength, int copy_name,
 
   /* Stash the partial symbol away in the cache.  */
   psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, theclass,
-                               val, coreaddr, language, objfile, &added);
+                               coreaddr, language, objfile, &added);
 
   /* Do not duplicate global partial symbols.  */
   if (list == &objfile->global_psymbols
@@ -1766,16 +1745,14 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
   if (objfile->global_psymbols.size > 0)
     {
       objfile->global_psymbols.next =
-       objfile->global_psymbols.list = (struct partial_symbol **)
-       xmalloc ((objfile->global_psymbols.size
-                 * sizeof (struct partial_symbol *)));
+       objfile->global_psymbols.list =
+         XNEWVEC (struct partial_symbol *, objfile->global_psymbols.size);
     }
   if (objfile->static_psymbols.size > 0)
     {
       objfile->static_psymbols.next =
-       objfile->static_psymbols.list = (struct partial_symbol **)
-       xmalloc ((objfile->static_psymbols.size
-                 * sizeof (struct partial_symbol *)));
+       objfile->static_psymbols.list =
+         XNEWVEC (struct partial_symbol *, objfile->static_psymbols.size);
     }
 }
 
@@ -1795,8 +1772,9 @@ allocate_psymtab (const char *filename, struct objfile *objfile)
                     sizeof (struct partial_symtab));
 
   memset (psymtab, 0, sizeof (struct partial_symtab));
-  psymtab->filename = bcache (filename, strlen (filename) + 1,
-                             objfile->per_bfd->filename_cache);
+  psymtab->filename
+    = (const char *) bcache (filename, strlen (filename) + 1,
+                            objfile->per_bfd->filename_cache);
   psymtab->compunit_symtab = NULL;
 
   /* Prepend it to the psymtab list for the objfile it belongs to.
@@ -1872,7 +1850,7 @@ struct psymtab_state
 static void
 discard_psymtabs_upto (void *arg)
 {
-  struct psymtab_state *state = arg;
+  struct psymtab_state *state = (struct psymtab_state *) arg;
 
   while (state->objfile->psymtabs != state->save)
     discard_psymtab (state->objfile, state->objfile->psymtabs);
@@ -1894,51 +1872,241 @@ make_cleanup_discard_psymtabs (struct objfile *objfile)
 
 \f
 
+/* We need to pass a couple of items to the addrmap_foreach function,
+   so use a struct.  */
+
+struct dump_psymtab_addrmap_data
+{
+  struct objfile *objfile;
+  struct partial_symtab *psymtab;
+  struct ui_file *outfile;
+
+  /* Non-zero if the previously printed addrmap entry was for PSYMTAB.
+     If so, we want to print the next one as well (since the next addrmap
+     entry defines the end of the range).  */
+  int previous_matched;
+};
+
+/* Helper function for dump_psymtab_addrmap to print an addrmap entry.  */
+
+static int
+dump_psymtab_addrmap_1 (void *datap, CORE_ADDR start_addr, void *obj)
+{
+  struct dump_psymtab_addrmap_data *data
+    = (struct dump_psymtab_addrmap_data *) datap;
+  struct gdbarch *gdbarch = get_objfile_arch (data->objfile);
+  struct partial_symtab *addrmap_psymtab = (struct partial_symtab *) obj;
+  const char *psymtab_address_or_end = NULL;
+
+  QUIT;
+
+  if (data->psymtab == NULL
+      || data->psymtab == addrmap_psymtab)
+    psymtab_address_or_end = host_address_to_string (addrmap_psymtab);
+  else if (data->previous_matched)
+    psymtab_address_or_end = "<ends here>";
+
+  if (data->psymtab == NULL
+      || data->psymtab == addrmap_psymtab
+      || data->previous_matched)
+    {
+      fprintf_filtered (data->outfile, "  %s%s %s\n",
+                       data->psymtab != NULL ? "  " : "",
+                       paddress (gdbarch, start_addr),
+                       psymtab_address_or_end);
+    }
+
+  data->previous_matched = (data->psymtab == NULL
+                           || data->psymtab == addrmap_psymtab);
+
+  return 0;
+}
+
+/* Helper function for maintenance_print_psymbols to print the addrmap
+   of PSYMTAB.  If PSYMTAB is NULL print the entire addrmap.  */
+
+static void
+dump_psymtab_addrmap (struct objfile *objfile, struct partial_symtab *psymtab,
+                     struct ui_file *outfile)
+{
+  struct dump_psymtab_addrmap_data addrmap_dump_data;
+
+  if ((psymtab == NULL
+       || psymtab->psymtabs_addrmap_supported)
+      && objfile->psymtabs_addrmap != NULL)
+    {
+      addrmap_dump_data.objfile = objfile;
+      addrmap_dump_data.psymtab = psymtab;
+      addrmap_dump_data.outfile = outfile;
+      addrmap_dump_data.previous_matched = 0;
+      fprintf_filtered (outfile, "%sddress map:\n",
+                       psymtab == NULL ? "Entire a" : "  A");
+      addrmap_foreach (objfile->psymtabs_addrmap, dump_psymtab_addrmap_1,
+                      &addrmap_dump_data);
+    }
+}
+
 static void
 maintenance_print_psymbols (char *args, int from_tty)
 {
   char **argv;
-  struct ui_file *outfile;
+  struct ui_file *outfile = gdb_stdout;
   struct cleanup *cleanups;
-  char *symname = NULL;
-  char *filename = DEV_TTY;
+  char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
   struct objfile *objfile;
   struct partial_symtab *ps;
+  int i, outfile_idx, found;
+  CORE_ADDR pc = 0;
+  struct obj_section *section = NULL;
 
   dont_repeat ();
 
-  if (args == NULL)
-    {
-      error (_("\
-print-psymbols takes an output file name and optional symbol file name"));
-    }
   argv = gdb_buildargv (args);
   cleanups = make_cleanup_freeargv (argv);
 
-  if (argv[0] != NULL)
+  for (i = 0; argv[i] != NULL; ++i)
     {
-      filename = argv[0];
-      /* If a second arg is supplied, it is a source file name to match on.  */
-      if (argv[1] != NULL)
+      if (strcmp (argv[i], "-pc") == 0)
+       {
+         if (argv[i + 1] == NULL)
+           error (_("Missing pc value"));
+         address_arg = argv[++i];
+       }
+      else if (strcmp (argv[i], "-source") == 0)
+       {
+         if (argv[i + 1] == NULL)
+           error (_("Missing source file"));
+         source_arg = argv[++i];
+       }
+      else if (strcmp (argv[i], "-objfile") == 0)
        {
-         symname = argv[1];
+         if (argv[i + 1] == NULL)
+           error (_("Missing objfile name"));
+         objfile_arg = argv[++i];
        }
+      else if (strcmp (argv[i], "--") == 0)
+       {
+         /* End of options.  */
+         ++i;
+         break;
+       }
+      else if (argv[i][0] == '-')
+       {
+         /* Future proofing: Don't allow OUTFILE to begin with "-".  */
+         error (_("Unknown option: %s"), argv[i]);
+       }
+      else
+       break;
     }
+  outfile_idx = i;
 
-  filename = tilde_expand (filename);
-  make_cleanup (xfree, filename);
+  if (address_arg != NULL && source_arg != NULL)
+    error (_("Must specify at most one of -pc and -source"));
 
-  outfile = gdb_fopen (filename, FOPEN_WT);
-  if (outfile == NULL)
-    perror_with_name (filename);
-  make_cleanup_ui_file_delete (outfile);
+  if (argv[outfile_idx] != NULL)
+    {
+      char *outfile_name;
+
+      if (argv[outfile_idx + 1] != NULL)
+       error (_("Junk at end of command"));
+      outfile_name = tilde_expand (argv[outfile_idx]);
+      make_cleanup (xfree, outfile_name);
+      outfile = gdb_fopen (outfile_name, FOPEN_WT);
+      if (outfile == NULL)
+       perror_with_name (outfile_name);
+      make_cleanup_ui_file_delete (outfile);
+    }
 
-  ALL_PSYMTABS (objfile, ps)
+  if (address_arg != NULL)
     {
+      pc = parse_and_eval_address (address_arg);
+      /* If we fail to find a section, that's ok, try the lookup anyway.  */
+      section = find_pc_section (pc);
+    }
+
+  found = 0;
+  ALL_OBJFILES (objfile)
+    {
+      int printed_objfile_header = 0;
+      int print_for_objfile = 1;
+
       QUIT;
-      if (symname == NULL || filename_cmp (symname, ps->filename) == 0)
-       dump_psymtab (objfile, ps, outfile);
+      if (objfile_arg != NULL)
+       print_for_objfile
+         = compare_filenames_for_search (objfile_name (objfile),
+                                         objfile_arg);
+      if (!print_for_objfile)
+       continue;
+
+      if (address_arg != NULL)
+       {
+         struct bound_minimal_symbol msymbol = { NULL, NULL };
+
+         /* We don't assume each pc has a unique objfile (this is for
+            debugging).  */
+         ps = find_pc_sect_psymtab (objfile, pc, section, msymbol);
+         if (ps != NULL)
+           {
+             if (!printed_objfile_header)
+               {
+                 fprintf_filtered (outfile,
+                                   "\nPartial symtabs for objfile %s\n",
+                                   objfile_name (objfile));
+                 printed_objfile_header = 1;
+               }
+             dump_psymtab (objfile, ps, outfile);
+             dump_psymtab_addrmap (objfile, ps, outfile);
+             found = 1;
+           }
+       }
+      else
+       {
+         ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
+           {
+             int print_for_source = 0;
+
+             QUIT;
+             if (source_arg != NULL)
+               {
+                 print_for_source
+                   = compare_filenames_for_search (ps->filename, source_arg);
+                 found = 1;
+               }
+             if (source_arg == NULL
+                 || print_for_source)
+               {
+                 if (!printed_objfile_header)
+                   {
+                     fprintf_filtered (outfile,
+                                       "\nPartial symtabs for objfile %s\n",
+                                       objfile_name (objfile));
+                     printed_objfile_header = 1;
+                   }
+                 dump_psymtab (objfile, ps, outfile);
+                 dump_psymtab_addrmap (objfile, ps, outfile);
+               }
+           }
+       }
+
+      /* If we're printing all the objfile's symbols dump the full addrmap.  */
+
+      if (address_arg == NULL
+         && source_arg == NULL
+         && objfile->psymtabs_addrmap != NULL)
+       {
+         fprintf_filtered (outfile, "\n");
+         dump_psymtab_addrmap (objfile, NULL, outfile);
+       }
     }
+
+  if (!found)
+    {
+      if (address_arg != NULL)
+       error (_("No partial symtab for address: %s"), address_arg);
+      if (source_arg != NULL)
+       error (_("No partial symtab for source file: %s"), source_arg);
+    }
+
   do_cleanups (cleanups);
 }
 
@@ -2149,8 +2317,13 @@ _initialize_psymtab (void)
 {
   add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols, _("\
 Print dump of current partial symbol definitions.\n\
-Entries in the partial symbol table are dumped to file OUTFILE.\n\
-If a SOURCE file is specified, dump only that file's partial symbols."),
+Usage: mt print psymbols [-objfile objfile] [-pc address] [--] [outfile]\n\
+       mt print psymbols [-objfile objfile] [-source source] [--] [outfile]\n\
+Entries in the partial symbol table are dumped to file OUTFILE,\n\
+or the terminal if OUTFILE is unspecified.\n\
+If ADDRESS is provided, dump only the file for that address.\n\
+If SOURCE is provided, dump only that file's symbols.\n\
+If OBJFILE is provided, dump only that file's minimal symbols."),
           &maintenanceprintlist);
 
   add_cmd ("psymtabs", class_maintenance, maintenance_info_psymtabs, _("\