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