- case 'C':
- {
- CONST char *filename;
- CONST char *functionname;
- char *cplus_name;
-
- unsigned int linenumber;
- bfd *abfd = va_arg(arg, bfd *);
- asection *section = va_arg(arg, asection *);
- asymbol **symbols = va_arg(arg, asymbol **);
- bfd_vma offset = va_arg(arg, bfd_vma);
-
- if (bfd_find_nearest_line(abfd,
- section,
- symbols,
- offset,
- &filename,
- &functionname,
- &linenumber))
- {
- if (filename == (char *)NULL)
- filename = abfd->filename;
- if (functionname != (char *)NULL)
- {
- cplus_name = demangle(functionname, 1);
- fprintf(fp,"%s:%u: (%s)", filename, linenumber, cplus_name);
- }
+ case 'C':
+ case 'D':
+ case 'G':
+ /* Clever filename:linenumber with function name if possible,
+ or section name as a last resort. The arguments are a BFD,
+ a section, and an offset. */
+ {
+ static bfd *last_bfd;
+ static char *last_file = NULL;
+ static char *last_function = NULL;
+ bfd *abfd;
+ asection *section;
+ bfd_vma offset;
+ lang_input_statement_type *entry;
+ asymbol **asymbols;
+ const char *filename;
+ const char *functionname;
+ unsigned int linenumber;
+ boolean discard_last;
+
+ abfd = va_arg (arg, bfd *);
+ section = va_arg (arg, asection *);
+ offset = va_arg (arg, bfd_vma);
+
+ entry = (lang_input_statement_type *) abfd->usrdata;
+ if (entry != (lang_input_statement_type *) NULL
+ && entry->asymbols != (asymbol **) NULL)
+ asymbols = entry->asymbols;
+ else
+ {
+ long symsize;
+ long symbol_count;
+
+ symsize = bfd_get_symtab_upper_bound (abfd);
+ if (symsize < 0)
+ einfo (_("%B%F: could not read symbols\n"), abfd);
+ asymbols = (asymbol **) xmalloc (symsize);
+ symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
+ if (symbol_count < 0)
+ einfo (_("%B%F: could not read symbols\n"), abfd);
+ if (entry != (lang_input_statement_type *) NULL)
+ {
+ entry->asymbols = asymbols;
+ entry->symbol_count = symbol_count;
+ }
+ }
+
+ discard_last = true;
+ if (bfd_find_nearest_line (abfd, section, asymbols, offset,
+ &filename, &functionname,
+ &linenumber))
+ {
+ if (functionname != NULL && fmt[-1] == 'G')
+ {
+ lfinfo (fp, "%B:", abfd);
+ if (filename != NULL
+ && strcmp (filename, bfd_get_filename (abfd)) != 0)
+ fprintf (fp, "%s:", filename);
+ lfinfo (fp, "%T", functionname);
+ }
+ else if (functionname != NULL && fmt[-1] == 'C')
+ {
+ if (filename == (char *) NULL)
+ filename = abfd->filename;
+
+ if (last_bfd == NULL
+ || last_file == NULL
+ || last_function == NULL
+ || last_bfd != abfd
+ || strcmp (last_file, filename) != 0
+ || strcmp (last_function, functionname) != 0)
+ {
+ /* We use abfd->filename in this initial line,
+ in case filename is a .h file or something
+ similarly unhelpful. */
+ lfinfo (fp, _("%B: In function `%T':\n"),
+ abfd, functionname);
+
+ last_bfd = abfd;
+ if (last_file != NULL)
+ free (last_file);
+ last_file = buystring (filename);
+ if (last_function != NULL)
+ free (last_function);
+ last_function = buystring (functionname);
+ }
+ discard_last = false;
+ if (linenumber != 0)
+ fprintf (fp, "%s:%u", filename, linenumber);
+ else
+ lfinfo (fp, "%s(%s+0x%v)", filename, section->name,
+ offset);
+ }
+ else if (filename == NULL
+ || strcmp (filename, abfd->filename) == 0)
+ {
+ lfinfo (fp, "%B(%s+0x%v)", abfd, section->name,
+ offset);
+ if (linenumber != 0)
+ lfinfo (fp, ":%u", linenumber);
+ }
+ else if (linenumber != 0)
+ lfinfo (fp, "%B:%s:%u", abfd, filename, linenumber);
+ else
+ lfinfo (fp, "%B(%s+0x%v):%s", abfd, section->name,
+ offset, filename);
+ }
+ else
+ lfinfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
+
+ if (discard_last)
+ {
+ last_bfd = NULL;
+ if (last_file != NULL)
+ {
+ free (last_file);
+ last_file = NULL;
+ }
+ if (last_function != NULL)
+ {
+ free (last_function);
+ last_function = NULL;
+ }
+ }
+ }
+ break;