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" |
fe2b6209 | 23 | #include <demangle.h> |
23cb3b65 ILT |
24 | |
25 | #ifdef ANSI_PROTOTYPES | |
26 | #include <stdarg.h> | |
27 | #define USE_STDARG 1 | |
7d6439d9 ILT |
28 | #else |
29 | #include <varargs.h> | |
23cb3b65 | 30 | #define USE_STDARG 0 |
7d6439d9 | 31 | #endif |
2fa0b342 DHW |
32 | |
33 | #include "ld.h" | |
34 | #include "ldmisc.h" | |
fcf276c4 | 35 | #include "ldexp.h" |
2fa0b342 | 36 | #include "ldlang.h" |
8bff41c1 | 37 | #include "ldgram.h" |
1418c83b | 38 | #include "ldlex.h" |
fcf276c4 ILT |
39 | #include "ldmain.h" |
40 | #include "ldfile.h" | |
2fa0b342 | 41 | |
7d6439d9 | 42 | |
23cb3b65 ILT |
43 | #if USE_STDARG |
44 | static void finfo PARAMS ((FILE *, const char *, ...)); | |
45 | #else | |
9b0da7f4 KR |
46 | /* VARARGS*/ |
47 | static void finfo (); | |
23cb3b65 | 48 | #endif |
288897f4 DM |
49 | static const char *demangle PARAMS ((const char *string, |
50 | int remove_underscore)); | |
9b0da7f4 | 51 | |
2fa0b342 | 52 | /* |
fcf276c4 | 53 | %% literal % |
2fa0b342 | 54 | %F error is fatal |
fcf276c4 | 55 | %P print program name |
2fa0b342 DHW |
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 | |
288897f4 | 60 | %T symbol name |
2fa0b342 DHW |
61 | %X no object output, fail return |
62 | %V hex bfd_vma | |
9b0da7f4 | 63 | %v hex bfd_vma, no leading zeros |
cc23cc69 ILT |
64 | %C clever filename:linenumber with function |
65 | %D like %C, but no 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 | |
288897f4 DM |
72 | static const char * |
73 | demangle (string, remove_underscore) | |
74 | const char *string; | |
75 | int remove_underscore; | |
9b0da7f4 | 76 | { |
288897f4 | 77 | const char *res; |
23cb3b65 ILT |
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); | |
9b0da7f4 KR |
93 | return res ? res : string; |
94 | } | |
95 | ||
c611e285 | 96 | static void |
23cb3b65 | 97 | vfinfo (fp, fmt, arg) |
c611e285 | 98 | FILE *fp; |
23cb3b65 | 99 | const char *fmt; |
c611e285 | 100 | va_list arg; |
2fa0b342 | 101 | { |
2fa0b342 | 102 | boolean fatal = false; |
2a28d8b0 | 103 | |
f0f80b13 | 104 | while (*fmt != '\0') |
9d1fe8a4 | 105 | { |
f0f80b13 | 106 | while (*fmt != '%' && *fmt != '\0') |
2a28d8b0 | 107 | { |
f0f80b13 ILT |
108 | putc (*fmt, fp); |
109 | fmt++; | |
2a28d8b0 | 110 | } |
2a28d8b0 | 111 | |
f0f80b13 | 112 | if (*fmt == '%') |
9b0da7f4 | 113 | { |
f0f80b13 ILT |
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; | |
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': | |
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); | |
288897f4 | 330 | |
f0f80b13 ILT |
331 | if (discard_last) |
332 | { | |
333 | last_bfd = NULL; | |
334 | if (last_file != NULL) | |
335 | { | |
31c27164 | 336 | free (last_file); |
f0f80b13 ILT |
337 | last_file = NULL; |
338 | } | |
339 | if (last_function != NULL) | |
340 | { | |
31c27164 | 341 | free (last_function); |
f0f80b13 ILT |
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; | |
31c27164 | 362 | } |
288897f4 | 363 | } |
2fa0b342 | 364 | } |
2a28d8b0 | 365 | |
6bf2e3a7 | 366 | if (fatal == true) |
5bcb7f28 | 367 | xexit(1); |
c611e285 SC |
368 | } |
369 | ||
370 | /* Format info message and print on stdout. */ | |
371 | ||
23cb3b65 ILT |
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.) */ | |
fcf276c4 | 374 | |
23cb3b65 ILT |
375 | void |
376 | #if USE_STDARG | |
377 | info_msg (const char *fmt, ...) | |
378 | #else | |
379 | info_msg (va_alist) | |
288897f4 | 380 | va_dcl |
23cb3b65 | 381 | #endif |
c611e285 | 382 | { |
c611e285 | 383 | va_list arg; |
23cb3b65 ILT |
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); | |
2fa0b342 DHW |
396 | } |
397 | ||
c611e285 SC |
398 | /* ('e' for error.) Format info message and print on stderr. */ |
399 | ||
23cb3b65 ILT |
400 | void |
401 | #if USE_STDARG | |
402 | einfo (const char *fmt, ...) | |
403 | #else | |
404 | einfo (va_alist) | |
288897f4 | 405 | va_dcl |
23cb3b65 | 406 | #endif |
c611e285 | 407 | { |
c611e285 | 408 | va_list arg; |
23cb3b65 ILT |
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); | |
c611e285 | 421 | } |
2fa0b342 DHW |
422 | |
423 | void | |
23cb3b65 ILT |
424 | info_assert (file, line) |
425 | const char *file; | |
2a28d8b0 | 426 | unsigned int line; |
2fa0b342 | 427 | { |
23cb3b65 | 428 | einfo ("%F%P: internal error %s %d\n", file, line); |
2fa0b342 DHW |
429 | } |
430 | ||
9b0da7f4 KR |
431 | char * |
432 | buystring (x) | |
433 | CONST char *CONST x; | |
2fa0b342 | 434 | { |
9b0da7f4 | 435 | size_t l = strlen(x)+1; |
5bcb7f28 | 436 | char *r = xmalloc(l); |
2fa0b342 DHW |
437 | memcpy(r, x,l); |
438 | return r; | |
439 | } | |
c611e285 | 440 | |
9d1fe8a4 SC |
441 | /* ('m' for map) Format info message and print on map. */ |
442 | ||
23cb3b65 ILT |
443 | void |
444 | #if USE_STDARG | |
445 | minfo (const char *fmt, ...) | |
446 | #else | |
447 | minfo (va_alist) | |
288897f4 | 448 | va_dcl |
23cb3b65 | 449 | #endif |
9d1fe8a4 | 450 | { |
9d1fe8a4 | 451 | va_list arg; |
9d1fe8a4 | 452 | |
23cb3b65 ILT |
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 | } | |
9d1fe8a4 | 464 | |
9b0da7f4 | 465 | static void |
23cb3b65 ILT |
466 | #if USE_STDARG |
467 | finfo (FILE *file, const char *fmt, ...) | |
468 | #else | |
9b0da7f4 KR |
469 | finfo (va_alist) |
470 | va_dcl | |
23cb3b65 | 471 | #endif |
9b0da7f4 | 472 | { |
9b0da7f4 | 473 | va_list arg; |
23cb3b65 ILT |
474 | |
475 | #if ! USE_STDARG | |
476 | FILE *file; | |
477 | const char *fmt; | |
478 | ||
9b0da7f4 KR |
479 | va_start (arg); |
480 | file = va_arg (arg, FILE *); | |
23cb3b65 ILT |
481 | fmt = va_arg (arg, const char *); |
482 | #else | |
483 | va_start (arg, fmt); | |
484 | #endif | |
485 | ||
9b0da7f4 KR |
486 | vfinfo (file, fmt, arg); |
487 | va_end (arg); | |
488 | } | |
23cb3b65 ILT |
489 | \f |
490 | /* Functions to print the link map. */ | |
c611e285 SC |
491 | |
492 | void | |
9b0da7f4 | 493 | print_space () |
c611e285 | 494 | { |
23cb3b65 | 495 | fprintf (config.map_file, " "); |
c611e285 | 496 | } |
23cb3b65 | 497 | |
c611e285 | 498 | void |
9b0da7f4 | 499 | print_nl () |
c611e285 | 500 | { |
23cb3b65 | 501 | fprintf (config.map_file, "\n"); |
c611e285 | 502 | } |
23cb3b65 | 503 | |
c611e285 | 504 | void |
9b0da7f4 KR |
505 | print_address (value) |
506 | bfd_vma value; | |
c611e285 | 507 | { |
23cb3b65 | 508 | fprintf_vma (config.map_file, value); |
c611e285 | 509 | } |