From: Alan Modra Date: Mon, 6 Mar 2023 00:12:36 +0000 (+1030) Subject: Move nm.c cached line number info to bfd usrdata X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e3f450f3933ddb9ca4ef405722706f3c793d295e;p=binutils-gdb.git 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. --- 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; }