public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Move nm.c cached line number info to bfd usrdata
@ 2023-03-06  3:28 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2023-03-06  3:28 UTC (permalink / raw)
  To: binutils

Replace the static variables used by nm to cache line number info
with a struct attached to the bfd.  Cleaner, and it avoids any concern
that lineno_cache_bfd is somehow left pointing at memory for a closed
bfd and that memory is later reused for another bfd, not that I think
this is possible.  Also don't bomb via bfd_fatal on errors getting
the line number info, just omit the line numbers.

	* nm.c (struct lineno_cache): Rename from get_relocs_info.
	Add symcount.
	(lineno_cache_bfd, lineno_cache_rel_bfd): Delete.
	(get_relocs): Adjust for struct rename.  Don't call bfd_fatal
	on errors.
	(free_lineno_cache): New function.
	(print_symbol): Use lineno_cache in place of statics.  Don't
	call bfd_fatal on errors reading symbols, just omit the line
	info.
	(display_archive, display_file): Call free_lineno_cache.

diff --git a/binutils/nm.c b/binutils/nm.c
index e91aa676931..2c428d20fdf 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -53,15 +53,15 @@ struct size_sym
   bfd_vma size;
 };
 
-/* When fetching relocs, we use this structure to pass information to
-   get_relocs.  */
+/* line number related info cached in bfd usrdata.  */
 
-struct get_relocs_info
+struct lineno_cache
 {
   asection **secs;
   arelent ***relocs;
   long *relcount;
   asymbol **syms;
+  long symcount;
 };
 
 struct extended_symbol_info
@@ -218,10 +218,6 @@ static const char *plugin_target = "plugin";
 static const char *plugin_target = NULL;
 #endif
 
-/* Used to cache the line numbers for a BFD.  */
-static bfd *lineno_cache_bfd;
-static bfd *lineno_cache_rel_bfd;
-
 typedef enum unicode_display_type
 {
   unicode_default = 0,
@@ -1140,28 +1136,21 @@ sort_symbols_by_size (bfd *abfd, bool is_dynamic, void *minisyms,
 static void
 get_relocs (bfd *abfd, asection *sec, void *dataarg)
 {
-  struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
+  struct lineno_cache *data = (struct lineno_cache *) dataarg;
 
   *data->secs = sec;
+  *data->relocs = NULL;
+  *data->relcount = 0;
 
-  if ((sec->flags & SEC_RELOC) == 0)
-    {
-      *data->relocs = NULL;
-      *data->relcount = 0;
-    }
-  else
+  if ((sec->flags & SEC_RELOC) != 0)
     {
-      long relsize;
-
-      relsize = bfd_get_reloc_upper_bound (abfd, sec);
-      if (relsize < 0)
-	bfd_fatal (bfd_get_filename (abfd));
-
-      *data->relocs = (arelent **) xmalloc (relsize);
-      *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
-						data->syms);
-      if (*data->relcount < 0)
-	bfd_fatal (bfd_get_filename (abfd));
+      long relsize = bfd_get_reloc_upper_bound (abfd, sec);
+      if (relsize > 0)
+	{
+	  *data->relocs = (arelent **) xmalloc (relsize);
+	  *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
+						    data->syms);
+	}
     }
 
   ++data->secs;
@@ -1169,6 +1158,26 @@ get_relocs (bfd *abfd, asection *sec, void *dataarg)
   ++data->relcount;
 }
 
+static void
+free_lineno_cache (bfd *abfd)
+{
+  struct lineno_cache *lc = bfd_usrdata (abfd);
+
+  if (lc)
+    {
+      unsigned int seccount = bfd_count_sections (abfd);
+      for (unsigned int i = 0; i < seccount; i++)
+	if (lc->relocs[i] != NULL)
+	  free (lc->relocs[i]);
+      free (lc->relcount);
+      free (lc->relocs);
+      free (lc->secs);
+      free (lc->syms);
+      free (lc);
+      bfd_set_usrdata (abfd, NULL);
+    }
+}
+
 /* Print a single symbol.  */
 
 static void
@@ -1215,73 +1224,48 @@ print_symbol (bfd *        abfd,
 
   if (line_numbers)
     {
-      static asymbol **syms;
-      static long symcount;
+      struct lineno_cache *lc = bfd_usrdata (abfd);
       const char *filename, *functionname;
       unsigned int lineno;
 
       /* We need to get the canonical symbols in order to call
          bfd_find_nearest_line.  This is inefficient, but, then, you
          don't have to use --line-numbers.  */
-      if (abfd != lineno_cache_bfd && syms != NULL)
+      if (lc == NULL)
 	{
-	  free (syms);
-	  syms = NULL;
+	  lc = xcalloc (1, sizeof (*lc));
+	  bfd_set_usrdata (abfd, lc);
 	}
-      if (syms == NULL)
+      if (lc->syms == NULL && lc->symcount == 0)
 	{
-	  long symsize;
-
-	  symsize = bfd_get_symtab_upper_bound (abfd);
-	  if (symsize < 0)
-	    bfd_fatal (bfd_get_filename (abfd));
-	  syms = (asymbol **) xmalloc (symsize);
-	  symcount = bfd_canonicalize_symtab (abfd, syms);
-	  if (symcount < 0)
-	    bfd_fatal (bfd_get_filename (abfd));
-	  lineno_cache_bfd = abfd;
+	  long symsize = bfd_get_symtab_upper_bound (abfd);
+	  if (symsize <= 0)
+	    lc->symcount = -1;
+	  else
+	    {
+	      lc->syms = xmalloc (symsize);
+	      lc->symcount = bfd_canonicalize_symtab (abfd, lc->syms);
+	    }
 	}
 
-      if (bfd_is_und_section (bfd_asymbol_section (sym)))
+      if (lc->symcount <= 0)
+	;
+      else if (bfd_is_und_section (bfd_asymbol_section (sym)))
 	{
-	  static asection **secs;
-	  static arelent ***relocs;
-	  static long *relcount;
-	  static unsigned int seccount;
 	  unsigned int i;
 	  const char *symname;
+	  unsigned int seccount = bfd_count_sections (abfd);
 
 	  /* For an undefined symbol, we try to find a reloc for the
              symbol, and print the line number of the reloc.  */
-	  if (abfd != lineno_cache_rel_bfd && relocs != NULL)
-	    {
-	      for (i = 0; i < seccount; i++)
-		if (relocs[i] != NULL)
-		  free (relocs[i]);
-	      free (secs);
-	      free (relocs);
-	      free (relcount);
-	      secs = NULL;
-	      relocs = NULL;
-	      relcount = NULL;
-	    }
-
-	  if (relocs == NULL)
+	  if (lc->relocs == NULL)
 	    {
-	      struct get_relocs_info rinfo;
+	      lc->secs = xmalloc (seccount * sizeof (*lc->secs));
+	      lc->relocs = xmalloc (seccount * sizeof (*lc->relocs));
+	      lc->relcount = xmalloc (seccount * sizeof (*lc->relcount));
 
-	      seccount = bfd_count_sections (abfd);
-
-	      secs = (asection **) xmalloc (seccount * sizeof *secs);
-	      relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
-	      relcount = (long *) xmalloc (seccount * sizeof *relcount);
-
-	      rinfo.secs = secs;
-	      rinfo.relocs = relocs;
-	      rinfo.relcount = relcount;
-	      rinfo.syms = syms;
-	      bfd_map_over_sections (abfd, get_relocs, (void *) &rinfo);
-	      lineno_cache_rel_bfd = abfd;
+	      struct lineno_cache rinfo = *lc;
+	      bfd_map_over_sections (abfd, get_relocs, &rinfo);
 	    }
 
 	  symname = bfd_asymbol_name (sym);
@@ -1289,17 +1273,17 @@ print_symbol (bfd *        abfd,
 	    {
 	      long j;
 
-	      for (j = 0; j < relcount[i]; j++)
+	      for (j = 0; j < lc->relcount[i]; j++)
 		{
 		  arelent *r;
 
-		  r = relocs[i][j];
+		  r = lc->relocs[i][j];
 		  if (r->sym_ptr_ptr != NULL
 		      && (*r->sym_ptr_ptr)->section == sym->section
 		      && (*r->sym_ptr_ptr)->value == sym->value
 		      && strcmp (symname,
 				 bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
-		      && bfd_find_nearest_line (abfd, secs[i], syms,
+		      && bfd_find_nearest_line (abfd, lc->secs[i], lc->syms,
 						r->address, &filename,
 						&functionname, &lineno)
 		      && filename != NULL)
@@ -1314,9 +1298,9 @@ print_symbol (bfd *        abfd,
 	}
       else if (bfd_asymbol_section (sym)->owner == abfd)
 	{
-	  if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
+	  if ((bfd_find_line (abfd, lc->syms, sym, &filename, &lineno)
 	       || bfd_find_nearest_line (abfd, bfd_asymbol_section (sym),
-					 syms, sym->value, &filename,
+					 lc->syms, sym->value, &filename,
 					 &functionname, &lineno))
 	      && filename != NULL
 	      && lineno != 0)
@@ -1624,9 +1608,8 @@ display_archive (bfd *file)
 
       if (last_arfile != NULL)
 	{
+	  free_lineno_cache (last_arfile);
 	  bfd_close (last_arfile);
-	  lineno_cache_bfd = NULL;
-	  lineno_cache_rel_bfd = NULL;
 	  if (arfile == last_arfile)
 	    return;
 	}
@@ -1635,9 +1618,8 @@ display_archive (bfd *file)
 
   if (last_arfile != NULL)
     {
+      free_lineno_cache (last_arfile);
       bfd_close (last_arfile);
-      lineno_cache_bfd = NULL;
-      lineno_cache_rel_bfd = NULL;
     }
 }
 
@@ -1680,12 +1662,10 @@ display_file (char *filename)
       retval = false;
     }
 
+  free_lineno_cache (file);
   if (!bfd_close (file))
     bfd_fatal (filename);
 
-  lineno_cache_bfd = NULL;
-  lineno_cache_rel_bfd = NULL;
-
   return retval;
 }
 \f

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Move nm.c cached line number info to bfd usrdata
@ 2023-03-08  3:15 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2023-03-08  3:15 UTC (permalink / raw)
  To: binutils

Commit e3f450f3933d resulted in a nm -l segfault on object files
without undefined symbols.  Fix that, and be paranoid about bfd
section count changing.

	* nm.c (struct lineno_cache): Add seccount.
	(free_lineno_cache): Don't segfault on NULL lc->relocs.
	(print_symbol): Stash section count when creating arrays.

diff --git a/binutils/nm.c b/binutils/nm.c
index 8b6b249a951..f96cfa31cb9 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -62,6 +62,7 @@ struct lineno_cache
   long *relcount;
   asymbol **syms;
   long symcount;
+  unsigned int seccount;
 };
 
 struct extended_symbol_info
@@ -1165,9 +1166,8 @@ free_lineno_cache (bfd *abfd)
 
   if (lc)
     {
-      unsigned int seccount = bfd_count_sections (abfd);
-      for (unsigned int i = 0; i < seccount; i++)
-	if (lc->relocs[i] != NULL)
+      if (lc->relocs)
+	for (unsigned int i = 0; i < lc->seccount; i++)
 	  free (lc->relocs[i]);
       free (lc->relcount);
       free (lc->relocs);
@@ -1254,12 +1254,13 @@ print_symbol (bfd *        abfd,
 	{
 	  unsigned int i;
 	  const char *symname;
-	  unsigned int seccount = bfd_count_sections (abfd);
 
 	  /* For an undefined symbol, we try to find a reloc for the
              symbol, and print the line number of the reloc.  */
 	  if (lc->relocs == NULL)
 	    {
+	      unsigned int seccount = bfd_count_sections (abfd);
+	      lc->seccount = seccount;
 	      lc->secs = xmalloc (seccount * sizeof (*lc->secs));
 	      lc->relocs = xmalloc (seccount * sizeof (*lc->relocs));
 	      lc->relcount = xmalloc (seccount * sizeof (*lc->relcount));
@@ -1269,7 +1270,7 @@ print_symbol (bfd *        abfd,
 	    }
 
 	  symname = bfd_asymbol_name (sym);
-	  for (i = 0; i < seccount; i++)
+	  for (i = 0; i < lc->seccount; i++)
 	    {
 	      long j;
 
@@ -1290,7 +1291,7 @@ print_symbol (bfd *        abfd,
 		    {
 		      /* We only print the first one we find.  */
 		      printf ("\t%s:%u", filename, lineno);
-		      i = seccount;
+		      i = lc->seccount;
 		      break;
 		    }
 		}

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-03-08  3:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-06  3:28 Move nm.c cached line number info to bfd usrdata Alan Modra
2023-03-08  3:15 Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).