* ldmisc.c (vfinfo): Reindent.
[external/binutils.git] / ld / ldmisc.c
1 /* ldmisc.c
2    Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3    Written by Steve Chamberlain of Cygnus Support.
4
5 This file is part of GLD, the Gnu Linker.
6
7 GLD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GLD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GLD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include <demangle.h>
24
25 #ifdef ANSI_PROTOTYPES
26 #include <stdarg.h>
27 #define USE_STDARG 1
28 #else
29 #include <varargs.h>
30 #define USE_STDARG 0
31 #endif
32
33 #include "ld.h"
34 #include "ldmisc.h"
35 #include "ldexp.h"
36 #include "ldlang.h"
37 #include "ldgram.h"
38 #include "ldlex.h"
39 #include "ldmain.h"
40 #include "ldfile.h"
41
42
43 #if USE_STDARG
44 static void finfo PARAMS ((FILE *, const char *, ...));
45 #else
46 /* VARARGS*/
47 static void finfo ();
48 #endif
49 static const char *demangle PARAMS ((const char *string,
50                                      int remove_underscore));
51
52 /*
53  %% literal %
54  %F error is fatal
55  %P print program name
56  %S print script file and linenumber
57  %E current bfd error or errno
58  %I filename from a lang_input_statement_type
59  %B filename from a bfd
60  %T symbol name
61  %X no object output, fail return
62  %V hex bfd_vma
63  %v hex bfd_vma, no leading zeros
64  %C clever filename:linenumber with function
65  %D like %C, but no function name
66  %R info about a relent
67  %s arbitrary string, like printf
68  %d integer, like printf
69  %u integer, like printf
70 */
71
72 static const char *
73 demangle (string, remove_underscore)
74      const char *string;
75      int remove_underscore;
76 {
77   const char *res;
78
79   if (remove_underscore
80       && output_bfd != NULL
81       && bfd_get_symbol_leading_char (output_bfd) == string[0])
82     ++string;
83
84   /* This is a hack for better error reporting on XCOFF.  */
85   if (remove_underscore && string[0] == '.')
86     ++string;
87
88   /* Note that there's a memory leak here, we keep buying memory for
89      demangled names, and never free.  But if you have so many errors
90      that you run out of VM with the error messages, then there's
91      something up.  */
92   res = cplus_demangle (string, DMGL_ANSI | DMGL_PARAMS);
93   return res ? res : string;
94 }
95
96 static void
97 vfinfo (fp, fmt, arg)
98      FILE *fp;
99      const char *fmt;
100      va_list arg;
101 {
102   boolean fatal = false;
103
104   while (*fmt != '\0')
105     {
106       while (*fmt != '%' && *fmt != '\0') 
107         {
108           putc (*fmt, fp);
109           fmt++;
110         }
111
112       if (*fmt == '%') 
113         {
114           fmt ++;
115           switch (*fmt++) 
116             {
117             default:
118               fprintf (fp,"%%%c", fmt[-1]);
119               break;
120
121             case '%':
122               /* literal % */
123               putc ('%', fp);
124               break;
125
126             case 'X':
127               /* no object output, fail return */
128               config.make_executable = false;
129               break;
130
131             case 'V':
132               /* hex bfd_vma */
133               {
134                 bfd_vma value = va_arg (arg, bfd_vma);
135                 fprintf_vma (fp, value);
136               }
137               break;
138
139             case 'v':
140               /* hex bfd_vma, no leading zeros */
141               {
142                 char buf[100];
143                 char *p = buf;
144                 bfd_vma value = va_arg (arg, bfd_vma);
145                 sprintf_vma (p, value);
146                 while (*p == '0')
147                   p++;
148                 if (!*p)
149                   p--;
150                 fputs (p, fp);
151               }
152               break;
153
154             case 'T':
155               /* Symbol name.  */
156               {
157                 const char *name = va_arg (arg, const char *);
158
159                 if (name != (const char *) NULL)
160                   fprintf (fp, "%s", demangle (name, 1));
161                 else
162                   fprintf (fp, "no symbol");
163               }
164               break;
165
166             case 'B':
167               /* filename from a bfd */
168               { 
169                 bfd *abfd = va_arg (arg, bfd *);
170                 if (abfd->my_archive)
171                   fprintf (fp, "%s(%s)", abfd->my_archive->filename,
172                            abfd->filename);
173                 else
174                   fprintf (fp, "%s", abfd->filename);
175               }
176               break;
177
178             case 'F':
179               /* error is fatal */
180               fatal = true;
181               break;
182
183             case 'P':
184               /* print program name */
185               fprintf (fp, "%s", program_name);
186               break;
187
188             case 'E':
189               /* current bfd error or errno */
190               fprintf (fp, bfd_errmsg (bfd_get_error ()));
191               break;
192
193             case 'I':
194               /* filename from a lang_input_statement_type */
195               {
196                 lang_input_statement_type *i;
197
198                 i = va_arg (arg, lang_input_statement_type *);
199                 if (bfd_my_archive (i->the_bfd) != NULL)
200                   fprintf (fp, "(%s)",
201                            bfd_get_filename (bfd_my_archive (i->the_bfd)));
202                 fprintf (fp, "%s", i->local_sym_name);
203                 if (bfd_my_archive (i->the_bfd) == NULL
204                     && strcmp (i->local_sym_name, i->filename) != 0)
205                   fprintf (fp, " (%s)", i->filename);
206               }
207               break;
208
209             case 'S':
210               /* print script file and linenumber */
211               if (parsing_defsym)
212                 fprintf (fp, "--defsym %s", lex_string);
213               else if (ldfile_input_filename != NULL)
214                 fprintf (fp, "%s:%u", ldfile_input_filename, lineno);
215               else
216                 fprintf (fp, "built in linker script:%u", lineno);
217               break;
218
219             case 'R':
220               /* Print all that's interesting about a relent */
221               {
222                 arelent *relent = va_arg (arg, arelent *);
223         
224                 finfo (fp, "%s+0x%v (type %s)",
225                        (*(relent->sym_ptr_ptr))->name,
226                        relent->addend,
227                        relent->howto->name);
228               }
229               break;
230         
231             case 'C':
232             case 'D':
233               /* Clever filename:linenumber with function name if possible,
234                  or section name as a last resort.  The arguments are a BFD,
235                  a section, and an offset.  */
236               {
237                 static bfd *last_bfd;
238                 static char *last_file = NULL;
239                 static char *last_function = NULL;
240                 bfd *abfd;
241                 asection *section;
242                 bfd_vma offset;
243                 lang_input_statement_type *entry;
244                 asymbol **asymbols;
245                 const char *filename;
246                 const char *functionname;
247                 unsigned int linenumber;
248                 boolean discard_last;
249
250                 abfd = va_arg (arg, bfd *);
251                 section = va_arg (arg, asection *);
252                 offset = va_arg (arg, bfd_vma);
253
254                 entry = (lang_input_statement_type *) abfd->usrdata;
255                 if (entry != (lang_input_statement_type *) NULL
256                     && entry->asymbols != (asymbol **) NULL)
257                   asymbols = entry->asymbols;
258                 else
259                   {
260                     long symsize;
261                     long symbol_count;
262
263                     symsize = bfd_get_symtab_upper_bound (abfd);
264                     if (symsize < 0)
265                       einfo ("%B%F: could not read symbols\n", abfd);
266                     asymbols = (asymbol **) xmalloc (symsize);
267                     symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
268                     if (symbol_count < 0)
269                       einfo ("%B%F: could not read symbols\n", abfd);
270                     if (entry != (lang_input_statement_type *) NULL)
271                       {
272                         entry->asymbols = asymbols;
273                         entry->symbol_count = symbol_count;
274                       }
275                   }
276
277                 discard_last = true;
278                 if (bfd_find_nearest_line (abfd, section, asymbols, offset,
279                                            &filename, &functionname,
280                                            &linenumber))
281                   {
282                     if (functionname != NULL && fmt[-1] == 'C')
283                       {
284                         if (filename == (char *) NULL)
285                           filename = abfd->filename;
286
287                         if (last_bfd == NULL
288                             || last_file == NULL
289                             || last_function == NULL
290                             || last_bfd != abfd
291                             || strcmp (last_file, filename) != 0
292                             || strcmp (last_function, functionname) != 0)
293                           {
294                             /* We use abfd->filename in this initial line,
295                                in case filename is a .h file or something
296                                similarly unhelpful.  */
297                             finfo (fp, "%B: In function `%s':\n",
298                                    abfd, demangle (functionname, 1));
299
300                             last_bfd = abfd;
301                             if (last_file != NULL)
302                               free (last_file);
303                             last_file = buystring (filename);
304                             if (last_function != NULL)
305                               free (last_function);
306                             last_function = buystring (functionname);
307                           }
308                         discard_last = false;
309                         if (linenumber != 0)
310                           fprintf (fp, "%s:%u", filename, linenumber);
311                         else
312                           finfo (fp, "%s(%s+0x%v)", filename, section->name,
313                                  offset);
314                       }
315                     else if (filename == NULL
316                              || strcmp (filename, abfd->filename) == 0)
317                       {
318                         finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
319                         if (linenumber != 0)
320                           finfo (fp, "%u", linenumber);
321                       }
322                     else if (linenumber != 0) 
323                       finfo (fp, "%B:%s:%u", abfd, filename, linenumber);
324                     else
325                       finfo (fp, "%B(%s+0x%v):%s", abfd, section->name, offset,
326                              filename);
327                   }
328                 else
329                   finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset);
330
331                 if (discard_last)
332                   {
333                     last_bfd = NULL;
334                     if (last_file != NULL)
335                       {
336                         free (last_file);
337                         last_file = NULL;
338                       }
339                     if (last_function != NULL)
340                       {
341                         free (last_function);
342                         last_function = NULL;
343                       }
344                   }
345               }
346               break;
347                 
348             case 's':
349               /* arbitrary string, like printf */
350               fprintf (fp, "%s", va_arg (arg, char *));
351               break;
352
353             case 'd':
354               /* integer, like printf */
355               fprintf (fp, "%d", va_arg (arg, int));
356               break;
357
358             case 'u':
359               /* unsigned integer, like printf */
360               fprintf (fp,"%u", va_arg (arg, unsigned int));
361               break;
362             }
363         }
364     }
365
366   if (fatal == true) 
367     xexit(1);
368 }
369
370 /* Format info message and print on stdout. */
371
372 /* (You would think this should be called just "info", but then you
373    would hosed by LynxOS, which defines that name in its libc.)  */
374
375 void
376 #if USE_STDARG
377 info_msg (const char *fmt, ...)
378 #else
379 info_msg (va_alist)
380      va_dcl
381 #endif
382 {
383   va_list arg;
384
385 #if ! USE_STDARG
386   const char *fmt;
387
388   va_start (arg);
389   fmt = va_arg (arg, const char *);
390 #else
391   va_start (arg, fmt);
392 #endif
393
394   vfinfo (stdout, fmt, arg);
395   va_end (arg);
396 }
397
398 /* ('e' for error.) Format info message and print on stderr. */
399
400 void
401 #if USE_STDARG
402 einfo (const char *fmt, ...)
403 #else
404 einfo (va_alist)
405      va_dcl
406 #endif
407 {
408   va_list arg;
409
410 #if ! USE_STDARG
411   const char *fmt;
412
413   va_start (arg);
414   fmt = va_arg (arg, const char *);
415 #else
416   va_start (arg, fmt);
417 #endif
418
419   vfinfo (stderr, fmt, arg);
420   va_end (arg);
421 }
422
423 void 
424 info_assert (file, line)
425      const char *file;
426      unsigned int line;
427 {
428   einfo ("%F%P: internal error %s %d\n", file, line);
429 }
430
431 char *
432 buystring (x)
433      CONST char *CONST x;
434 {
435   size_t l = strlen(x)+1;
436   char *r = xmalloc(l);
437   memcpy(r, x,l);
438   return r;
439 }
440
441 /* ('m' for map) Format info message and print on map. */
442
443 void
444 #if USE_STDARG
445 minfo (const char *fmt, ...)
446 #else
447 minfo (va_alist)
448      va_dcl
449 #endif
450 {
451   va_list arg;
452
453 #if ! USE_STDARG
454   const char *fmt;
455   va_start (arg);
456   fmt = va_arg (arg, const char *);
457 #else
458   va_start (arg, fmt);
459 #endif
460
461   vfinfo (config.map_file, fmt, arg);
462   va_end (arg);
463 }
464
465 static void
466 #if USE_STDARG
467 finfo (FILE *file, const char *fmt, ...)
468 #else
469 finfo (va_alist)
470      va_dcl
471 #endif
472 {
473   va_list arg;
474
475 #if ! USE_STDARG
476   FILE *file;
477   const char *fmt;
478
479   va_start (arg);
480   file = va_arg (arg, FILE *);
481   fmt = va_arg (arg, const char *);
482 #else
483   va_start (arg, fmt);
484 #endif
485
486   vfinfo (file, fmt, arg);
487   va_end (arg);
488 }
489 \f
490 /* Functions to print the link map.  */
491
492 void 
493 print_space ()
494 {
495   fprintf (config.map_file, " ");
496 }
497
498 void 
499 print_nl ()
500 {
501   fprintf (config.map_file, "\n");
502 }
503
504 void 
505 print_address (value)
506      bfd_vma value;
507 {
508   fprintf_vma (config.map_file, value);
509 }