]>
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 | |
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
c611e285 | 22 | #include "bfd.h" |
2fa0b342 DHW |
23 | #include "sysdep.h" |
24 | #include <varargs.h> | |
fe2b6209 | 25 | #include <demangle.h> |
2fa0b342 DHW |
26 | |
27 | #include "ld.h" | |
28 | #include "ldmisc.h" | |
fcf276c4 | 29 | #include "ldexp.h" |
2fa0b342 | 30 | #include "ldlang.h" |
8bff41c1 | 31 | #include "ldgram.h" |
1418c83b | 32 | #include "ldlex.h" |
fcf276c4 ILT |
33 | #include "ldmain.h" |
34 | #include "ldfile.h" | |
2fa0b342 | 35 | |
9b0da7f4 KR |
36 | /* VARARGS*/ |
37 | static void finfo (); | |
288897f4 DM |
38 | static const char *demangle PARAMS ((const char *string, |
39 | int remove_underscore)); | |
9b0da7f4 | 40 | |
2fa0b342 | 41 | /* |
fcf276c4 | 42 | %% literal % |
2fa0b342 | 43 | %F error is fatal |
fcf276c4 | 44 | %P print program name |
2fa0b342 DHW |
45 | %S print script file and linenumber |
46 | %E current bfd error or errno | |
47 | %I filename from a lang_input_statement_type | |
48 | %B filename from a bfd | |
288897f4 | 49 | %T symbol name |
2fa0b342 DHW |
50 | %X no object output, fail return |
51 | %V hex bfd_vma | |
9b0da7f4 | 52 | %v hex bfd_vma, no leading zeros |
cc23cc69 ILT |
53 | %C clever filename:linenumber with function |
54 | %D like %C, but no function name | |
c611e285 | 55 | %R info about a relent |
fcf276c4 ILT |
56 | %s arbitrary string, like printf |
57 | %d integer, like printf | |
2fa0b342 | 58 | */ |
9b0da7f4 | 59 | |
288897f4 DM |
60 | static const char * |
61 | demangle (string, remove_underscore) | |
62 | const char *string; | |
63 | int remove_underscore; | |
9b0da7f4 | 64 | { |
288897f4 | 65 | const char *res; |
9b0da7f4 KR |
66 | if (remove_underscore && output_bfd) |
67 | { | |
288897f4 | 68 | if (bfd_get_symbol_leading_char (output_bfd) == string[0]) |
9b0da7f4 KR |
69 | string++; |
70 | } | |
71 | /* Note that there's a memory leak here, we keep buying memory | |
72 | for demangled names, and never free. But if you have so many | |
73 | errors that you run out of VM with the error messages, then | |
74 | there's something up */ | |
288897f4 | 75 | res = cplus_demangle (string, DMGL_ANSI|DMGL_PARAMS); |
9b0da7f4 KR |
76 | return res ? res : string; |
77 | } | |
78 | ||
c611e285 SC |
79 | static void |
80 | vfinfo(fp, fmt, arg) | |
81 | FILE *fp; | |
82 | char *fmt; | |
83 | va_list arg; | |
2fa0b342 | 84 | { |
2fa0b342 | 85 | boolean fatal = false; |
2a28d8b0 | 86 | |
9d1fe8a4 SC |
87 | while (*fmt) |
88 | { | |
89 | while (*fmt != '%' && *fmt != '\0') | |
90 | { | |
c611e285 | 91 | putc(*fmt, fp); |
2fa0b342 DHW |
92 | fmt++; |
93 | } | |
2a28d8b0 | 94 | |
9d1fe8a4 SC |
95 | if (*fmt == '%') |
96 | { | |
2fa0b342 | 97 | fmt ++; |
9d1fe8a4 SC |
98 | switch (*fmt++) |
99 | { | |
fcf276c4 ILT |
100 | default: |
101 | fprintf(fp,"%%%c", fmt[-1]); | |
102 | break; | |
103 | ||
104 | case '%': | |
105 | /* literal % */ | |
106 | putc('%', fp); | |
107 | break; | |
108 | ||
6bf2e3a7 | 109 | case 'X': |
fcf276c4 | 110 | /* no object output, fail return */ |
2fa0b342 DHW |
111 | config.make_executable = false; |
112 | break; | |
2a28d8b0 | 113 | |
6bf2e3a7 | 114 | case 'V': |
fcf276c4 | 115 | /* hex bfd_vma */ |
2a28d8b0 DM |
116 | { |
117 | bfd_vma value = va_arg(arg, bfd_vma); | |
118 | fprintf_vma(fp, value); | |
119 | } | |
2fa0b342 | 120 | break; |
2a28d8b0 | 121 | |
9b0da7f4 | 122 | case 'v': |
fcf276c4 | 123 | /* hex bfd_vma, no leading zeros */ |
9b0da7f4 KR |
124 | { |
125 | char buf[100]; | |
126 | char *p = buf; | |
127 | bfd_vma value = va_arg (arg, bfd_vma); | |
128 | sprintf_vma (p, value); | |
129 | while (*p == '0') | |
130 | p++; | |
131 | if (!*p) | |
132 | p--; | |
133 | fputs (p, fp); | |
134 | } | |
135 | break; | |
2a28d8b0 | 136 | |
6bf2e3a7 | 137 | case 'T': |
288897f4 DM |
138 | /* Symbol name. */ |
139 | { | |
140 | const char *name = va_arg (arg, const char *); | |
141 | ||
142 | if (name != (const char *) NULL) | |
143 | fprintf (fp, "%s", demangle (name, 1)); | |
144 | else | |
145 | fprintf (fp, "no symbol"); | |
146 | } | |
2fa0b342 | 147 | break; |
2a28d8b0 | 148 | |
6bf2e3a7 | 149 | case 'B': |
fcf276c4 | 150 | /* filename from a bfd */ |
6bf2e3a7 SC |
151 | { |
152 | bfd *abfd = va_arg(arg, bfd *); | |
153 | if (abfd->my_archive) { | |
154 | fprintf(fp,"%s(%s)", abfd->my_archive->filename, | |
155 | abfd->filename); | |
156 | } | |
157 | else { | |
158 | fprintf(fp,"%s", abfd->filename); | |
6bf2e3a7 SC |
159 | } |
160 | } | |
2fa0b342 | 161 | break; |
2a28d8b0 | 162 | |
6bf2e3a7 | 163 | case 'F': |
fcf276c4 | 164 | /* error is fatal */ |
2fa0b342 DHW |
165 | fatal = true; |
166 | break; | |
2a28d8b0 | 167 | |
6bf2e3a7 | 168 | case 'P': |
fcf276c4 | 169 | /* print program name */ |
c611e285 | 170 | fprintf(fp,"%s", program_name); |
2fa0b342 | 171 | break; |
2a28d8b0 | 172 | |
6bf2e3a7 | 173 | case 'E': |
fcf276c4 | 174 | /* current bfd error or errno */ |
5bcb7f28 | 175 | fprintf(fp, bfd_errmsg(bfd_get_error ())); |
2fa0b342 | 176 | break; |
2a28d8b0 | 177 | |
6bf2e3a7 | 178 | case 'I': |
fcf276c4 | 179 | /* filename from a lang_input_statement_type */ |
6bf2e3a7 SC |
180 | { |
181 | lang_input_statement_type *i = | |
182 | va_arg(arg,lang_input_statement_type *); | |
288897f4 DM |
183 | |
184 | if (i->the_bfd->my_archive) | |
185 | fprintf(fp, "(%s)", i->the_bfd->my_archive->filename); | |
6bf2e3a7 SC |
186 | fprintf(fp,"%s", i->local_sym_name); |
187 | } | |
2fa0b342 | 188 | break; |
2a28d8b0 | 189 | |
6bf2e3a7 | 190 | case 'S': |
fcf276c4 | 191 | /* print script file and linenumber */ |
6bf2e3a7 | 192 | { |
8bff41c1 | 193 | if (ldfile_input_filename) { |
6bf2e3a7 SC |
194 | fprintf(fp,"%s:%u", ldfile_input_filename, lineno ); |
195 | } | |
196 | } | |
2fa0b342 | 197 | break; |
c611e285 | 198 | |
6bf2e3a7 | 199 | case 'R': |
c611e285 | 200 | /* Print all that's interesting about a relent */ |
6bf2e3a7 SC |
201 | { |
202 | arelent *relent = va_arg(arg, arelent *); | |
c611e285 | 203 | |
9b0da7f4 KR |
204 | finfo (fp, "%s+0x%v (type %s)", |
205 | (*(relent->sym_ptr_ptr))->name, | |
206 | relent->addend, | |
207 | relent->howto->name); | |
6bf2e3a7 | 208 | } |
c611e285 SC |
209 | break; |
210 | ||
6bf2e3a7 | 211 | case 'C': |
cc23cc69 | 212 | case 'D': |
fcf276c4 | 213 | /* Clever filename:linenumber with function name if possible, |
288897f4 DM |
214 | or section name as a last resort. The arguments are a BFD, |
215 | a section, and an offset. */ | |
216 | { | |
31c27164 ILT |
217 | static char *last_file = NULL; |
218 | static char *last_function = NULL; | |
288897f4 DM |
219 | bfd *abfd; |
220 | asection *section; | |
221 | bfd_vma offset; | |
222 | lang_input_statement_type *entry; | |
223 | asymbol **asymbols; | |
224 | const char *filename; | |
225 | const char *functionname; | |
226 | unsigned int linenumber; | |
31c27164 | 227 | boolean discard_last; |
288897f4 DM |
228 | |
229 | abfd = va_arg (arg, bfd *); | |
230 | section = va_arg (arg, asection *); | |
231 | offset = va_arg (arg, bfd_vma); | |
232 | ||
233 | entry = (lang_input_statement_type *) abfd->usrdata; | |
234 | if (entry != (lang_input_statement_type *) NULL | |
235 | && entry->asymbols != (asymbol **) NULL) | |
236 | asymbols = entry->asymbols; | |
237 | else | |
238 | { | |
8bff41c1 ILT |
239 | long symsize; |
240 | long symbol_count; | |
288897f4 | 241 | |
8bff41c1 ILT |
242 | symsize = bfd_get_symtab_upper_bound (abfd); |
243 | if (symsize < 0) | |
244 | einfo ("%B%F: could not read symbols", abfd); | |
5bcb7f28 | 245 | asymbols = (asymbol **) xmalloc (symsize); |
288897f4 | 246 | symbol_count = bfd_canonicalize_symtab (abfd, asymbols); |
8bff41c1 ILT |
247 | if (symbol_count < 0) |
248 | einfo ("%B%F: could not read symbols", abfd); | |
288897f4 DM |
249 | if (entry != (lang_input_statement_type *) NULL) |
250 | { | |
251 | entry->asymbols = asymbols; | |
252 | entry->symbol_count = symbol_count; | |
253 | } | |
254 | } | |
255 | ||
31c27164 | 256 | discard_last = true; |
288897f4 DM |
257 | if (bfd_find_nearest_line (abfd, section, asymbols, offset, |
258 | &filename, &functionname, &linenumber)) | |
259 | { | |
260 | if (filename == (char *) NULL) | |
261 | filename = abfd->filename; | |
262 | ||
cc23cc69 ILT |
263 | if (functionname != NULL && fmt[-1] == 'C') |
264 | { | |
31c27164 ILT |
265 | if (last_file == NULL |
266 | || last_function == NULL | |
267 | || strcmp (last_file, filename) != 0 | |
268 | || strcmp (last_function, functionname) != 0) | |
269 | { | |
270 | fprintf (fp, "%s: In function `%s':\n", filename, | |
271 | demangle (functionname, 1)); | |
272 | if (last_file != NULL) | |
273 | free (last_file); | |
274 | last_file = buystring (filename); | |
275 | if (last_function != NULL) | |
276 | free (last_function); | |
277 | last_function = buystring (functionname); | |
278 | } | |
279 | discard_last = false; | |
cc23cc69 ILT |
280 | fprintf (fp, "%s:%u", filename, linenumber); |
281 | } | |
288897f4 DM |
282 | else if (linenumber != 0) |
283 | fprintf (fp, "%s:%u", filename, linenumber); | |
284 | else | |
285 | finfo (fp, "%s(%s+0x%v)", filename, section->name, offset); | |
288897f4 DM |
286 | } |
287 | else | |
288 | finfo (fp, "%s(%s+0x%v)", abfd->filename, section->name, offset); | |
31c27164 ILT |
289 | |
290 | if (discard_last) | |
291 | { | |
292 | if (last_file != NULL) | |
293 | { | |
294 | free (last_file); | |
295 | last_file = NULL; | |
296 | } | |
297 | if (last_function != NULL) | |
298 | { | |
299 | free (last_function); | |
300 | last_function = NULL; | |
301 | } | |
302 | } | |
288897f4 | 303 | } |
2fa0b342 DHW |
304 | break; |
305 | ||
6bf2e3a7 | 306 | case 's': |
fcf276c4 | 307 | /* arbitrary string, like printf */ |
c611e285 | 308 | fprintf(fp,"%s", va_arg(arg, char *)); |
2fa0b342 | 309 | break; |
2a28d8b0 | 310 | |
6bf2e3a7 | 311 | case 'd': |
fcf276c4 | 312 | /* integer, like printf */ |
c611e285 | 313 | fprintf(fp,"%d", va_arg(arg, int)); |
2fa0b342 | 314 | break; |
2fa0b342 DHW |
315 | } |
316 | } | |
317 | } | |
2a28d8b0 | 318 | |
6bf2e3a7 | 319 | if (fatal == true) |
5bcb7f28 | 320 | xexit(1); |
c611e285 SC |
321 | } |
322 | ||
323 | /* Format info message and print on stdout. */ | |
324 | ||
fcf276c4 ILT |
325 | /* (You would think this should be called just "info", but then you would |
326 | hosed by LynxOS, which defines that name in its libc.) */ | |
327 | ||
328 | void info_msg(va_alist) | |
288897f4 | 329 | va_dcl |
c611e285 SC |
330 | { |
331 | char *fmt; | |
332 | va_list arg; | |
333 | va_start(arg); | |
334 | fmt = va_arg(arg, char *); | |
335 | vfinfo(stdout, fmt, arg); | |
2fa0b342 DHW |
336 | va_end(arg); |
337 | } | |
338 | ||
c611e285 SC |
339 | /* ('e' for error.) Format info message and print on stderr. */ |
340 | ||
341 | void einfo(va_alist) | |
288897f4 | 342 | va_dcl |
c611e285 SC |
343 | { |
344 | char *fmt; | |
345 | va_list arg; | |
346 | va_start(arg); | |
347 | fmt = va_arg(arg, char *); | |
348 | vfinfo(stderr, fmt, arg); | |
349 | va_end(arg); | |
350 | } | |
2fa0b342 DHW |
351 | |
352 | void | |
353 | info_assert(file, line) | |
2a28d8b0 DM |
354 | char *file; |
355 | unsigned int line; | |
2fa0b342 | 356 | { |
fcf276c4 | 357 | einfo("%F%P: internal error %s %d\n", file,line); |
2fa0b342 DHW |
358 | } |
359 | ||
9b0da7f4 KR |
360 | char * |
361 | buystring (x) | |
362 | CONST char *CONST x; | |
2fa0b342 | 363 | { |
9b0da7f4 | 364 | size_t l = strlen(x)+1; |
5bcb7f28 | 365 | char *r = xmalloc(l); |
2fa0b342 DHW |
366 | memcpy(r, x,l); |
367 | return r; | |
368 | } | |
c611e285 SC |
369 | |
370 | ||
9d1fe8a4 SC |
371 | /* ('m' for map) Format info message and print on map. */ |
372 | ||
373 | void minfo(va_alist) | |
288897f4 | 374 | va_dcl |
9d1fe8a4 SC |
375 | { |
376 | char *fmt; | |
377 | va_list arg; | |
378 | va_start(arg); | |
379 | fmt = va_arg(arg, char *); | |
380 | vfinfo(config.map_file, fmt, arg); | |
381 | va_end(arg); | |
382 | } | |
383 | ||
384 | ||
9b0da7f4 KR |
385 | static void |
386 | finfo (va_alist) | |
387 | va_dcl | |
388 | { | |
389 | char *fmt; | |
390 | FILE *file; | |
391 | va_list arg; | |
392 | va_start (arg); | |
393 | file = va_arg (arg, FILE *); | |
394 | fmt = va_arg (arg, char *); | |
395 | vfinfo (file, fmt, arg); | |
396 | va_end (arg); | |
397 | } | |
9d1fe8a4 SC |
398 | |
399 | ||
400 | ||
c611e285 SC |
401 | /*---------------------------------------------------------------------- |
402 | Functions to print the link map | |
403 | */ | |
404 | ||
405 | void | |
9b0da7f4 | 406 | print_space () |
c611e285 | 407 | { |
9d1fe8a4 | 408 | fprintf(config.map_file, " "); |
c611e285 SC |
409 | } |
410 | void | |
9b0da7f4 | 411 | print_nl () |
c611e285 | 412 | { |
9d1fe8a4 | 413 | fprintf(config.map_file, "\n"); |
c611e285 SC |
414 | } |
415 | void | |
9b0da7f4 KR |
416 | print_address (value) |
417 | bfd_vma value; | |
c611e285 | 418 | { |
9d1fe8a4 | 419 | fprintf_vma(config.map_file, value); |
c611e285 | 420 | } |