Move nm.c cached line number info to bfd usrdata

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.
This commit is contained in:
Alan Modra 2023-03-06 10:42:36 +10:30
parent a734d906cc
commit e3f450f393

View file

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