source: branches/libc-0.6/src/binutils/ld/ldmisc.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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