]>
Commit | Line | Data |
---|---|---|
c611e285 | 1 | /* ldmisc.c |
f0f80b13 | 2 | Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. |
c611e285 | 3 | Written by Steve Chamberlain of Cygnus Support. |
2fa0b342 DHW |
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 | |
c611e285 | 9 | the Free Software Foundation; either version 2, or (at your option) |
2fa0b342 DHW |
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 | |
7d6439d9 | 19 | the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
2fa0b342 | 20 | |
c611e285 | 21 | #include "bfd.h" |
2fa0b342 | 22 | #include "sysdep.h" |
efa6c497 ILT |
23 | #include "libiberty.h" |
24 | #include "demangle.h" | |
23cb3b65 ILT |
25 | |
26 | #ifdef ANSI_PROTOTYPES | |
27 | #include <stdarg.h> | |
28 | #define USE_STDARG 1 | |
7d6439d9 ILT |
29 | #else |
30 | #include <varargs.h> | |
23cb3b65 | 31 | #define USE_STDARG 0 |
7d6439d9 | 32 | #endif |
2fa0b342 DHW |
33 | |
34 | #include "ld.h" | |
35 | #include "ldmisc.h" | |
fcf276c4 | 36 | #include "ldexp.h" |
2fa0b342 | 37 | #include "ldlang.h" |
8bff41c1 | 38 | #include "ldgram.h" |
1418c83b | 39 | #include "ldlex.h" |
fcf276c4 ILT |
40 | #include "ldmain.h" |
41 | #include "ldfile.h" | |
2fa0b342 | 42 | |
7d6439d9 | 43 | |
23cb3b65 ILT |
44 | #if USE_STDARG |
45 | static void finfo PARAMS ((FILE *, const char *, ...)); | |
46 | #else | |
9b0da7f4 KR |
47 | /* VARARGS*/ |
48 | static void finfo (); | |
23cb3b65 | 49 | #endif |
9b0da7f4 | 50 | |
2fa0b342 | 51 | /* |
fcf276c4 | 52 | %% literal % |
2fa0b342 | 53 | %F error is fatal |
fcf276c4 | 54 | %P print program name |
2fa0b342 DHW |
55 | %S print script file and linenumber |
56 | %E current bfd error or errno | |
57 | %I filename from a lang_input_statement_type | |
58 | %B filename from a bfd | |
288897f4 | 59 | %T symbol name |
2fa0b342 DHW |
60 | %X no object output, fail return |
61 | %V hex bfd_vma | |
9b0da7f4 | 62 | %v hex bfd_vma, no leading zeros |
cc23cc69 ILT |
63 | %C clever filename:linenumber with function |
64 | %D like %C, but no function name | |
efa6c497 | 65 | %G like %D, but only function name |
c611e285 | 66 | %R info about a relent |
fcf276c4 ILT |
67 | %s arbitrary string, like printf |
68 | %d integer, like printf | |
7d6439d9 | 69 | %u integer, like printf |
2fa0b342 | 70 | */ |
9b0da7f4 | 71 | |
efa6c497 ILT |
72 | char * |
73 | demangle (string) | |
288897f4 | 74 | const char *string; |
9b0da7f4 | 75 | { |
efa6c497 | 76 | char *res; |
23cb3b65 | 77 | |
efa6c497 | 78 | if (output_bfd != NULL |
23cb3b65 ILT |
79 | && bfd_get_symbol_leading_char (output_bfd) == string[0]) |
80 | ++string; | |
81 | ||
82 | /* This is a hack for better error reporting on XCOFF. */ | |
efa6c497 | 83 | if (string[0] == '.') |
23cb3b65 ILT |
84 | ++string; |
85 | ||
23cb3b65 | 86 | res = cplus_demangle (string, DMGL_ANSI | DMGL_PARAMS); |
efa6c497 | 87 | return res ? res : xstrdup (string); |
9b0da7f4 KR |
88 | } |
89 | ||
c611e285 | 90 | static void |
23cb3b65 | 91 | vfinfo (fp, fmt, arg) |
c611e285 | 92 | FILE *fp; |
23cb3b65 | 93 | const char *fmt; |
c611e285 | 94 | va_list arg; |
2fa0b342 | 95 | { |
2fa0b342 | 96 | boolean fatal = false; |
2a28d8b0 | 97 | |
f0f80b13 | 98 | while (*fmt != '\0') |
9d1fe8a4 | 99 | { |
f0f80b13 | 100 | while (*fmt != '%' && *fmt != '\0') |
2a28d8b0 | 101 | { |
f0f80b13 ILT |
102 | putc (*fmt, fp); |
103 | fmt++; | |
2a28d8b0 | 104 | } |
2a28d8b0 | 105 | |
f0f80b13 | 106 | if (*fmt == '%') |
9b0da7f4 | 107 | { |
f0f80b13 ILT |
108 | fmt ++; |
109 | switch (*fmt++) | |
110 | { | |
111 | default: | |
112 | fprintf (fp,"%%%c", fmt[-1]); | |
113 | break; | |
114 | ||
115 | case '%': | |
116 | /* literal % */ | |
117 | putc ('%', fp); | |
118 | break; | |
119 | ||
120 | case 'X': | |
121 | /* no object output, fail return */ | |
122 | config.make_executable = false; | |
123 | break; | |
124 | ||
125 | case 'V': | |
126 | /* hex bfd_vma */ | |
127 | { | |
128 | bfd_vma value = va_arg (arg, bfd_vma); | |
129 | fprintf_vma (fp, value); | |
130 | } | |
131 | break; | |
132 | ||
133 | case 'v': | |
134 | /* hex bfd_vma, no leading zeros */ | |
135 | { | |
136 | char buf[100]; | |
137 | char *p = buf; | |
138 | bfd_vma value = va_arg (arg, bfd_vma); | |
139 | sprintf_vma (p, value); | |
140 | while (*p == '0') | |
141 | p++; | |
142 | if (!*p) | |
143 | p--; | |
144 | fputs (p, fp); | |
145 | } | |
146 | break; | |
147 | ||
148 | case 'T': | |
149 | /* Symbol name. */ | |
150 | { | |
151 | const char *name = va_arg (arg, const char *); | |
152 | ||
efa6c497 | 153 | if (name == (const char *) NULL) |
f0f80b13 | 154 | fprintf (fp, "no symbol"); |
efa6c497 ILT |
155 | else |
156 | { | |
157 | char *demangled; | |
158 | ||
159 | demangled = demangle (name); | |
160 | fprintf (fp, "%s", demangled); | |
161 | free (demangled); | |
162 | } | |
f0f80b13 ILT |
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; | |
288897f4 | 218 | |
f0f80b13 ILT |
219 | case 'R': |
220 | /* Print all that's interesting about a relent */ | |
221 | { | |
222 | arelent *relent = va_arg (arg, arelent *); | |
c611e285 | 223 | |
f0f80b13 ILT |
224 | finfo (fp, "%s+0x%v (type %s)", |
225 | (*(relent->sym_ptr_ptr))->name, | |
226 | relent->addend, | |
227 | relent->howto->name); | |
228 | } | |
229 | break; | |
c611e285 | 230 | |
f0f80b13 ILT |
231 | case 'C': |
232 | case 'D': | |
efa6c497 | 233 | case 'G': |
f0f80b13 ILT |
234 | /* Clever filename:linenumber with function name if possible, |
235 | or section name as a last resort. The arguments are a BFD, | |
236 | a section, and an offset. */ | |
237 | { | |
238 | static bfd *last_bfd; | |
239 | static char *last_file = NULL; | |
240 | static char *last_function = NULL; | |
241 | bfd *abfd; | |
242 | asection *section; | |
243 | bfd_vma offset; | |
244 | lang_input_statement_type *entry; | |
245 | asymbol **asymbols; | |
246 | const char *filename; | |
247 | const char *functionname; | |
248 | unsigned int linenumber; | |
249 | boolean discard_last; | |
250 | ||
251 | abfd = va_arg (arg, bfd *); | |
252 | section = va_arg (arg, asection *); | |
253 | offset = va_arg (arg, bfd_vma); | |
254 | ||
255 | entry = (lang_input_statement_type *) abfd->usrdata; | |
256 | if (entry != (lang_input_statement_type *) NULL | |
257 | && entry->asymbols != (asymbol **) NULL) | |
258 | asymbols = entry->asymbols; | |
259 | else | |
260 | { | |
261 | long symsize; | |
262 | long symbol_count; | |
263 | ||
264 | symsize = bfd_get_symtab_upper_bound (abfd); | |
265 | if (symsize < 0) | |
266 | einfo ("%B%F: could not read symbols\n", abfd); | |
267 | asymbols = (asymbol **) xmalloc (symsize); | |
268 | symbol_count = bfd_canonicalize_symtab (abfd, asymbols); | |
269 | if (symbol_count < 0) | |
270 | einfo ("%B%F: could not read symbols\n", abfd); | |
271 | if (entry != (lang_input_statement_type *) NULL) | |
272 | { | |
273 | entry->asymbols = asymbols; | |
274 | entry->symbol_count = symbol_count; | |
275 | } | |
276 | } | |
277 | ||
278 | discard_last = true; | |
279 | if (bfd_find_nearest_line (abfd, section, asymbols, offset, | |
280 | &filename, &functionname, | |
281 | &linenumber)) | |
282 | { | |
efa6c497 ILT |
283 | if (functionname != NULL && fmt[-1] == 'G') |
284 | { | |
285 | finfo (fp, "%B:", abfd); | |
286 | if (filename != NULL | |
287 | && strcmp (filename, bfd_get_filename (abfd)) != 0) | |
288 | fprintf (fp, "%s:", filename); | |
289 | finfo (fp, "%T", functionname); | |
290 | } | |
291 | else if (functionname != NULL && fmt[-1] == 'C') | |
f0f80b13 ILT |
292 | { |
293 | if (filename == (char *) NULL) | |
294 | filename = abfd->filename; | |
295 | ||
296 | if (last_bfd == NULL | |
297 | || last_file == NULL | |
298 | || last_function == NULL | |
299 | || last_bfd != abfd | |
300 | || strcmp (last_file, filename) != 0 | |
301 | || strcmp (last_function, functionname) != 0) | |
302 | { | |
303 | /* We use abfd->filename in this initial line, | |
304 | in case filename is a .h file or something | |
305 | similarly unhelpful. */ | |
efa6c497 ILT |
306 | finfo (fp, "%B: In function `%T':\n", |
307 | abfd, functionname); | |
f0f80b13 ILT |
308 | |
309 | last_bfd = abfd; | |
310 | if (last_file != NULL) | |
311 | free (last_file); | |
312 | last_file = buystring (filename); | |
313 | if (last_function != NULL) | |
314 | free (last_function); | |
315 | last_function = buystring (functionname); | |
316 | } | |
317 | discard_last = false; | |
318 | if (linenumber != 0) | |
319 | fprintf (fp, "%s:%u", filename, linenumber); | |
320 | else | |
321 | finfo (fp, "%s(%s+0x%v)", filename, section->name, | |
322 | offset); | |
323 | } | |
324 | else if (filename == NULL | |
325 | || strcmp (filename, abfd->filename) == 0) | |
326 | { | |
327 | finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset); | |
328 | if (linenumber != 0) | |
efa6c497 | 329 | finfo (fp, ":%u", linenumber); |
f0f80b13 ILT |
330 | } |
331 | else if (linenumber != 0) | |
332 | finfo (fp, "%B:%s:%u", abfd, filename, linenumber); | |
333 | else | |
334 | finfo (fp, "%B(%s+0x%v):%s", abfd, section->name, offset, | |
335 | filename); | |
336 | } | |
337 | else | |
338 | finfo (fp, "%B(%s+0x%v)", abfd, section->name, offset); | |
288897f4 | 339 | |
f0f80b13 ILT |
340 | if (discard_last) |
341 | { | |
342 | last_bfd = NULL; | |
343 | if (last_file != NULL) | |
344 | { | |
31c27164 | 345 | free (last_file); |
f0f80b13 ILT |
346 | last_file = NULL; |
347 | } | |
348 | if (last_function != NULL) | |
349 | { | |
31c27164 | 350 | free (last_function); |
f0f80b13 ILT |
351 | last_function = NULL; |
352 | } | |
353 | } | |
354 | } | |
355 | break; | |
356 | ||
357 | case 's': | |
358 | /* arbitrary string, like printf */ | |
359 | fprintf (fp, "%s", va_arg (arg, char *)); | |
360 | break; | |
361 | ||
362 | case 'd': | |
363 | /* integer, like printf */ | |
364 | fprintf (fp, "%d", va_arg (arg, int)); | |
365 | break; | |
366 | ||
367 | case 'u': | |
368 | /* unsigned integer, like printf */ | |
efa6c497 | 369 | fprintf (fp, "%u", va_arg (arg, unsigned int)); |
f0f80b13 | 370 | break; |
31c27164 | 371 | } |
288897f4 | 372 | } |
2fa0b342 | 373 | } |
2a28d8b0 | 374 | |
6bf2e3a7 | 375 | if (fatal == true) |
5bcb7f28 | 376 | xexit(1); |
c611e285 SC |
377 | } |
378 | ||
379 | /* Format info message and print on stdout. */ | |
380 | ||
23cb3b65 ILT |
381 | /* (You would think this should be called just "info", but then you |
382 | would hosed by LynxOS, which defines that name in its libc.) */ | |
fcf276c4 | 383 | |
23cb3b65 ILT |
384 | void |
385 | #if USE_STDARG | |
386 | info_msg (const char *fmt, ...) | |
387 | #else | |
388 | info_msg (va_alist) | |
288897f4 | 389 | va_dcl |
23cb3b65 | 390 | #endif |
c611e285 | 391 | { |
c611e285 | 392 | va_list arg; |
23cb3b65 ILT |
393 | |
394 | #if ! USE_STDARG | |
395 | const char *fmt; | |
396 | ||
397 | va_start (arg); | |
398 | fmt = va_arg (arg, const char *); | |
399 | #else | |
400 | va_start (arg, fmt); | |
401 | #endif | |
402 | ||
403 | vfinfo (stdout, fmt, arg); | |
404 | va_end (arg); | |
2fa0b342 DHW |
405 | } |
406 | ||
c611e285 SC |
407 | /* ('e' for error.) Format info message and print on stderr. */ |
408 | ||
23cb3b65 ILT |
409 | void |
410 | #if USE_STDARG | |
411 | einfo (const char *fmt, ...) | |
412 | #else | |
413 | einfo (va_alist) | |
288897f4 | 414 | va_dcl |
23cb3b65 | 415 | #endif |
c611e285 | 416 | { |
c611e285 | 417 | va_list arg; |
23cb3b65 ILT |
418 | |
419 | #if ! USE_STDARG | |
420 | const char *fmt; | |
421 | ||
422 | va_start (arg); | |
423 | fmt = va_arg (arg, const char *); | |
424 | #else | |
425 | va_start (arg, fmt); | |
426 | #endif | |
427 | ||
428 | vfinfo (stderr, fmt, arg); | |
429 | va_end (arg); | |
c611e285 | 430 | } |
2fa0b342 DHW |
431 | |
432 | void | |
23cb3b65 ILT |
433 | info_assert (file, line) |
434 | const char *file; | |
2a28d8b0 | 435 | unsigned int line; |
2fa0b342 | 436 | { |
23cb3b65 | 437 | einfo ("%F%P: internal error %s %d\n", file, line); |
2fa0b342 DHW |
438 | } |
439 | ||
9b0da7f4 KR |
440 | char * |
441 | buystring (x) | |
442 | CONST char *CONST x; | |
2fa0b342 | 443 | { |
9b0da7f4 | 444 | size_t l = strlen(x)+1; |
5bcb7f28 | 445 | char *r = xmalloc(l); |
2fa0b342 DHW |
446 | memcpy(r, x,l); |
447 | return r; | |
448 | } | |
c611e285 | 449 | |
9d1fe8a4 SC |
450 | /* ('m' for map) Format info message and print on map. */ |
451 | ||
23cb3b65 ILT |
452 | void |
453 | #if USE_STDARG | |
454 | minfo (const char *fmt, ...) | |
455 | #else | |
456 | minfo (va_alist) | |
288897f4 | 457 | va_dcl |
23cb3b65 | 458 | #endif |
9d1fe8a4 | 459 | { |
9d1fe8a4 | 460 | va_list arg; |
9d1fe8a4 | 461 | |
23cb3b65 ILT |
462 | #if ! USE_STDARG |
463 | const char *fmt; | |
464 | va_start (arg); | |
465 | fmt = va_arg (arg, const char *); | |
466 | #else | |
467 | va_start (arg, fmt); | |
468 | #endif | |
469 | ||
470 | vfinfo (config.map_file, fmt, arg); | |
471 | va_end (arg); | |
472 | } | |
9d1fe8a4 | 473 | |
9b0da7f4 | 474 | static void |
23cb3b65 ILT |
475 | #if USE_STDARG |
476 | finfo (FILE *file, const char *fmt, ...) | |
477 | #else | |
9b0da7f4 KR |
478 | finfo (va_alist) |
479 | va_dcl | |
23cb3b65 | 480 | #endif |
9b0da7f4 | 481 | { |
9b0da7f4 | 482 | va_list arg; |
23cb3b65 ILT |
483 | |
484 | #if ! USE_STDARG | |
485 | FILE *file; | |
486 | const char *fmt; | |
487 | ||
9b0da7f4 KR |
488 | va_start (arg); |
489 | file = va_arg (arg, FILE *); | |
23cb3b65 ILT |
490 | fmt = va_arg (arg, const char *); |
491 | #else | |
492 | va_start (arg, fmt); | |
493 | #endif | |
494 | ||
9b0da7f4 KR |
495 | vfinfo (file, fmt, arg); |
496 | va_end (arg); | |
497 | } | |
23cb3b65 ILT |
498 | \f |
499 | /* Functions to print the link map. */ | |
c611e285 SC |
500 | |
501 | void | |
9b0da7f4 | 502 | print_space () |
c611e285 | 503 | { |
23cb3b65 | 504 | fprintf (config.map_file, " "); |
c611e285 | 505 | } |
23cb3b65 | 506 | |
c611e285 | 507 | void |
9b0da7f4 | 508 | print_nl () |
c611e285 | 509 | { |
23cb3b65 | 510 | fprintf (config.map_file, "\n"); |
c611e285 | 511 | } |
23cb3b65 | 512 | |
c611e285 | 513 | void |
9b0da7f4 KR |
514 | print_address (value) |
515 | bfd_vma value; | |
c611e285 | 516 | { |
23cb3b65 | 517 | fprintf_vma (config.map_file, value); |
c611e285 | 518 | } |