]>
Commit | Line | Data |
---|---|---|
c611e285 | 1 | /* ldmisc.c |
288897f4 | 2 | Copyright (C) 1991, 1993 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" |
1418c83b | 31 | #include "ldlex.h" |
fcf276c4 ILT |
32 | #include "ldmain.h" |
33 | #include "ldfile.h" | |
2fa0b342 | 34 | |
9b0da7f4 KR |
35 | /* VARARGS*/ |
36 | static void finfo (); | |
288897f4 DM |
37 | static const char *demangle PARAMS ((const char *string, |
38 | int remove_underscore)); | |
9b0da7f4 | 39 | |
2fa0b342 | 40 | /* |
fcf276c4 | 41 | %% literal % |
2fa0b342 | 42 | %F error is fatal |
fcf276c4 | 43 | %P print program name |
2fa0b342 DHW |
44 | %S print script file and linenumber |
45 | %E current bfd error or errno | |
46 | %I filename from a lang_input_statement_type | |
47 | %B filename from a bfd | |
288897f4 | 48 | %T symbol name |
2fa0b342 DHW |
49 | %X no object output, fail return |
50 | %V hex bfd_vma | |
9b0da7f4 | 51 | %v hex bfd_vma, no leading zeros |
2fa0b342 | 52 | %C Clever filename:linenumber |
c611e285 | 53 | %R info about a relent |
fcf276c4 ILT |
54 | %s arbitrary string, like printf |
55 | %d integer, like printf | |
2fa0b342 | 56 | */ |
9b0da7f4 | 57 | |
288897f4 DM |
58 | static const char * |
59 | demangle (string, remove_underscore) | |
60 | const char *string; | |
61 | int remove_underscore; | |
9b0da7f4 | 62 | { |
288897f4 | 63 | const char *res; |
9b0da7f4 KR |
64 | if (remove_underscore && output_bfd) |
65 | { | |
288897f4 | 66 | if (bfd_get_symbol_leading_char (output_bfd) == string[0]) |
9b0da7f4 KR |
67 | string++; |
68 | } | |
69 | /* Note that there's a memory leak here, we keep buying memory | |
70 | for demangled names, and never free. But if you have so many | |
71 | errors that you run out of VM with the error messages, then | |
72 | there's something up */ | |
288897f4 | 73 | res = cplus_demangle (string, DMGL_ANSI|DMGL_PARAMS); |
9b0da7f4 KR |
74 | return res ? res : string; |
75 | } | |
76 | ||
c611e285 SC |
77 | static void |
78 | vfinfo(fp, fmt, arg) | |
79 | FILE *fp; | |
80 | char *fmt; | |
81 | va_list arg; | |
2fa0b342 | 82 | { |
2fa0b342 | 83 | boolean fatal = false; |
2a28d8b0 | 84 | |
9d1fe8a4 SC |
85 | while (*fmt) |
86 | { | |
87 | while (*fmt != '%' && *fmt != '\0') | |
88 | { | |
c611e285 | 89 | putc(*fmt, fp); |
2fa0b342 DHW |
90 | fmt++; |
91 | } | |
2a28d8b0 | 92 | |
9d1fe8a4 SC |
93 | if (*fmt == '%') |
94 | { | |
2fa0b342 | 95 | fmt ++; |
9d1fe8a4 SC |
96 | switch (*fmt++) |
97 | { | |
fcf276c4 ILT |
98 | default: |
99 | fprintf(fp,"%%%c", fmt[-1]); | |
100 | break; | |
101 | ||
102 | case '%': | |
103 | /* literal % */ | |
104 | putc('%', fp); | |
105 | break; | |
106 | ||
6bf2e3a7 | 107 | case 'X': |
fcf276c4 | 108 | /* no object output, fail return */ |
2fa0b342 DHW |
109 | config.make_executable = false; |
110 | break; | |
2a28d8b0 | 111 | |
6bf2e3a7 | 112 | case 'V': |
fcf276c4 | 113 | /* hex bfd_vma */ |
2a28d8b0 DM |
114 | { |
115 | bfd_vma value = va_arg(arg, bfd_vma); | |
116 | fprintf_vma(fp, value); | |
117 | } | |
2fa0b342 | 118 | break; |
2a28d8b0 | 119 | |
9b0da7f4 | 120 | case 'v': |
fcf276c4 | 121 | /* hex bfd_vma, no leading zeros */ |
9b0da7f4 KR |
122 | { |
123 | char buf[100]; | |
124 | char *p = buf; | |
125 | bfd_vma value = va_arg (arg, bfd_vma); | |
126 | sprintf_vma (p, value); | |
127 | while (*p == '0') | |
128 | p++; | |
129 | if (!*p) | |
130 | p--; | |
131 | fputs (p, fp); | |
132 | } | |
133 | break; | |
2a28d8b0 | 134 | |
6bf2e3a7 | 135 | case 'T': |
288897f4 DM |
136 | /* Symbol name. */ |
137 | { | |
138 | const char *name = va_arg (arg, const char *); | |
139 | ||
140 | if (name != (const char *) NULL) | |
141 | fprintf (fp, "%s", demangle (name, 1)); | |
142 | else | |
143 | fprintf (fp, "no symbol"); | |
144 | } | |
2fa0b342 | 145 | break; |
2a28d8b0 | 146 | |
6bf2e3a7 | 147 | case 'B': |
fcf276c4 | 148 | /* filename from a bfd */ |
6bf2e3a7 SC |
149 | { |
150 | bfd *abfd = va_arg(arg, bfd *); | |
151 | if (abfd->my_archive) { | |
152 | fprintf(fp,"%s(%s)", abfd->my_archive->filename, | |
153 | abfd->filename); | |
154 | } | |
155 | else { | |
156 | fprintf(fp,"%s", abfd->filename); | |
6bf2e3a7 SC |
157 | } |
158 | } | |
2fa0b342 | 159 | break; |
2a28d8b0 | 160 | |
6bf2e3a7 | 161 | case 'F': |
fcf276c4 | 162 | /* error is fatal */ |
2fa0b342 DHW |
163 | fatal = true; |
164 | break; | |
2a28d8b0 | 165 | |
6bf2e3a7 | 166 | case 'P': |
fcf276c4 | 167 | /* print program name */ |
c611e285 | 168 | fprintf(fp,"%s", program_name); |
2fa0b342 | 169 | break; |
2a28d8b0 | 170 | |
6bf2e3a7 | 171 | case 'E': |
fcf276c4 | 172 | /* current bfd error or errno */ |
c611e285 | 173 | fprintf(fp, bfd_errmsg(bfd_error)); |
2fa0b342 | 174 | break; |
2a28d8b0 | 175 | |
6bf2e3a7 | 176 | case 'I': |
fcf276c4 | 177 | /* filename from a lang_input_statement_type */ |
6bf2e3a7 SC |
178 | { |
179 | lang_input_statement_type *i = | |
180 | va_arg(arg,lang_input_statement_type *); | |
288897f4 DM |
181 | |
182 | if (i->the_bfd->my_archive) | |
183 | fprintf(fp, "(%s)", i->the_bfd->my_archive->filename); | |
6bf2e3a7 SC |
184 | fprintf(fp,"%s", i->local_sym_name); |
185 | } | |
2fa0b342 | 186 | break; |
2a28d8b0 | 187 | |
6bf2e3a7 | 188 | case 'S': |
fcf276c4 | 189 | /* print script file and linenumber */ |
6bf2e3a7 | 190 | { |
6bf2e3a7 SC |
191 | if (ldfile_input_filename == (char *)NULL) { |
192 | fprintf(fp,"command line"); | |
193 | } | |
194 | else { | |
195 | fprintf(fp,"%s:%u", ldfile_input_filename, lineno ); | |
196 | } | |
197 | } | |
2fa0b342 | 198 | break; |
c611e285 | 199 | |
6bf2e3a7 | 200 | case 'R': |
c611e285 | 201 | /* Print all that's interesting about a relent */ |
6bf2e3a7 SC |
202 | { |
203 | arelent *relent = va_arg(arg, arelent *); | |
c611e285 | 204 | |
9b0da7f4 KR |
205 | finfo (fp, "%s+0x%v (type %s)", |
206 | (*(relent->sym_ptr_ptr))->name, | |
207 | relent->addend, | |
208 | relent->howto->name); | |
6bf2e3a7 | 209 | } |
c611e285 SC |
210 | break; |
211 | ||
6bf2e3a7 | 212 | case 'C': |
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 | { | |
217 | bfd *abfd; | |
218 | asection *section; | |
219 | bfd_vma offset; | |
220 | lang_input_statement_type *entry; | |
221 | asymbol **asymbols; | |
222 | const char *filename; | |
223 | const char *functionname; | |
224 | unsigned int linenumber; | |
225 | ||
226 | abfd = va_arg (arg, bfd *); | |
227 | section = va_arg (arg, asection *); | |
228 | offset = va_arg (arg, bfd_vma); | |
229 | ||
230 | entry = (lang_input_statement_type *) abfd->usrdata; | |
231 | if (entry != (lang_input_statement_type *) NULL | |
232 | && entry->asymbols != (asymbol **) NULL) | |
233 | asymbols = entry->asymbols; | |
234 | else | |
235 | { | |
236 | unsigned int symsize; | |
237 | unsigned int symbol_count; | |
238 | ||
239 | symsize = get_symtab_upper_bound (abfd); | |
240 | asymbols = (asymbol **) ldmalloc (symsize); | |
241 | symbol_count = bfd_canonicalize_symtab (abfd, asymbols); | |
242 | if (entry != (lang_input_statement_type *) NULL) | |
243 | { | |
244 | entry->asymbols = asymbols; | |
245 | entry->symbol_count = symbol_count; | |
246 | } | |
247 | } | |
248 | ||
249 | if (bfd_find_nearest_line (abfd, section, asymbols, offset, | |
250 | &filename, &functionname, &linenumber)) | |
251 | { | |
252 | if (filename == (char *) NULL) | |
253 | filename = abfd->filename; | |
254 | ||
255 | if (functionname != (char *)NULL) | |
256 | fprintf (fp, "%s:%u: %s", filename, linenumber, | |
257 | demangle (functionname, 1)); | |
258 | else if (linenumber != 0) | |
259 | fprintf (fp, "%s:%u", filename, linenumber); | |
260 | else | |
261 | finfo (fp, "%s(%s+0x%v)", filename, section->name, offset); | |
262 | ||
263 | } | |
264 | else | |
265 | finfo (fp, "%s(%s+0x%v)", abfd->filename, section->name, offset); | |
266 | } | |
2fa0b342 DHW |
267 | break; |
268 | ||
6bf2e3a7 | 269 | case 's': |
fcf276c4 | 270 | /* arbitrary string, like printf */ |
c611e285 | 271 | fprintf(fp,"%s", va_arg(arg, char *)); |
2fa0b342 | 272 | break; |
2a28d8b0 | 273 | |
6bf2e3a7 | 274 | case 'd': |
fcf276c4 | 275 | /* integer, like printf */ |
c611e285 | 276 | fprintf(fp,"%d", va_arg(arg, int)); |
2fa0b342 | 277 | break; |
2fa0b342 DHW |
278 | } |
279 | } | |
280 | } | |
2a28d8b0 | 281 | |
6bf2e3a7 SC |
282 | if (fatal == true) |
283 | { | |
6bf2e3a7 SC |
284 | if (output_filename) |
285 | { | |
6bf2e3a7 SC |
286 | if (output_bfd && output_bfd->iostream) |
287 | fclose((FILE *)(output_bfd->iostream)); | |
fcf276c4 ILT |
288 | if (delete_output_file_on_failure) |
289 | unlink (output_filename); | |
9d1fe8a4 | 290 | } |
6bf2e3a7 SC |
291 | exit(1); |
292 | } | |
c611e285 SC |
293 | } |
294 | ||
295 | /* Format info message and print on stdout. */ | |
296 | ||
fcf276c4 ILT |
297 | /* (You would think this should be called just "info", but then you would |
298 | hosed by LynxOS, which defines that name in its libc.) */ | |
299 | ||
300 | void info_msg(va_alist) | |
288897f4 | 301 | va_dcl |
c611e285 SC |
302 | { |
303 | char *fmt; | |
304 | va_list arg; | |
305 | va_start(arg); | |
306 | fmt = va_arg(arg, char *); | |
307 | vfinfo(stdout, fmt, arg); | |
2fa0b342 DHW |
308 | va_end(arg); |
309 | } | |
310 | ||
c611e285 SC |
311 | /* ('e' for error.) Format info message and print on stderr. */ |
312 | ||
313 | void einfo(va_alist) | |
288897f4 | 314 | va_dcl |
c611e285 SC |
315 | { |
316 | char *fmt; | |
317 | va_list arg; | |
318 | va_start(arg); | |
319 | fmt = va_arg(arg, char *); | |
320 | vfinfo(stderr, fmt, arg); | |
321 | va_end(arg); | |
322 | } | |
2fa0b342 | 323 | |
2a28d8b0 DM |
324 | /* Warn about a symbol NEWSYM being multiply defined with another symbol OLDSYM. |
325 | MESSAGE1 and MESSAGE2 should look something like: | |
326 | "%C: warning: multiple commons of `%s'\n" | |
327 | "%C: warning: previous common here\n" */ | |
328 | ||
329 | void | |
330 | multiple_warn (message1, newsym, message2, oldsym) | |
331 | char *message1; | |
332 | asymbol *newsym; | |
333 | char *message2; | |
334 | asymbol *oldsym; | |
335 | { | |
288897f4 | 336 | lang_input_statement_type *inp_stat; |
2a28d8b0 DM |
337 | asymbol **stat_symbols; |
338 | ||
288897f4 DM |
339 | inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (newsym)->usrdata; |
340 | stat_symbols = inp_stat ? inp_stat->asymbols : 0; | |
2a28d8b0 DM |
341 | |
342 | einfo (message1, | |
343 | bfd_asymbol_bfd (newsym), newsym->section, stat_symbols, newsym->value, | |
344 | demangle (newsym->name, 1)); | |
345 | ||
288897f4 DM |
346 | inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (oldsym)->usrdata; |
347 | stat_symbols = inp_stat ? inp_stat->asymbols : 0; | |
2a28d8b0 DM |
348 | |
349 | einfo (message2, | |
350 | bfd_asymbol_bfd (oldsym), oldsym->section, stat_symbols, oldsym->value); | |
351 | } | |
352 | ||
2fa0b342 DHW |
353 | void |
354 | info_assert(file, line) | |
2a28d8b0 DM |
355 | char *file; |
356 | unsigned int line; | |
2fa0b342 | 357 | { |
fcf276c4 | 358 | einfo("%F%P: internal error %s %d\n", file,line); |
2fa0b342 DHW |
359 | } |
360 | ||
361 | /* Return a newly-allocated string | |
362 | whose contents concatenate those of S1, S2, S3. */ | |
363 | ||
364 | char * | |
9b0da7f4 KR |
365 | concat (s1, s2, s3) |
366 | CONST char *s1; | |
367 | CONST char *s2; | |
368 | CONST char *s3; | |
2fa0b342 | 369 | { |
9b0da7f4 KR |
370 | size_t len1 = strlen (s1); |
371 | size_t len2 = strlen (s2); | |
372 | size_t len3 = strlen (s3); | |
2fa0b342 DHW |
373 | char *result = ldmalloc (len1 + len2 + len3 + 1); |
374 | ||
375 | if (len1 != 0) | |
376 | memcpy(result, s1, len1); | |
377 | if (len2 != 0) | |
378 | memcpy(result+len1, s2, len2); | |
379 | if (len3 != 0) | |
380 | memcpy(result+len1+len2, s2, len3); | |
381 | *(result + len1 + len2 + len3) = 0; | |
382 | ||
383 | return result; | |
384 | } | |
385 | ||
386 | ||
c611e285 | 387 | PTR |
9b0da7f4 KR |
388 | ldmalloc (size) |
389 | size_t size; | |
2fa0b342 | 390 | { |
c611e285 | 391 | PTR result = malloc ((int)size); |
2fa0b342 DHW |
392 | |
393 | if (result == (char *)NULL && size != 0) | |
fcf276c4 | 394 | einfo("%F%P: virtual memory exhausted\n"); |
2fa0b342 DHW |
395 | |
396 | return result; | |
397 | } | |
398 | ||
6bf2e3a7 | 399 | PTR |
9b0da7f4 KR |
400 | xmalloc (size) |
401 | int size; | |
6bf2e3a7 | 402 | { |
288897f4 | 403 | return ldmalloc ((size_t) size); |
6bf2e3a7 SC |
404 | } |
405 | ||
2fa0b342 | 406 | |
9d1fe8a4 | 407 | PTR |
9b0da7f4 KR |
408 | ldrealloc (ptr, size) |
409 | PTR ptr; | |
410 | size_t size; | |
9d1fe8a4 SC |
411 | { |
412 | PTR result = realloc (ptr, (int)size); | |
413 | ||
414 | if (result == (char *)NULL && size != 0) | |
fcf276c4 | 415 | einfo("%F%P: virtual memory exhausted\n"); |
9d1fe8a4 SC |
416 | |
417 | return result; | |
418 | } | |
419 | ||
9b0da7f4 KR |
420 | PTR |
421 | xrealloc (ptr, size) | |
422 | PTR ptr; | |
288897f4 | 423 | int size; |
9b0da7f4 | 424 | { |
288897f4 | 425 | return ldrealloc (ptr, (size_t) size); |
9b0da7f4 | 426 | } |
9d1fe8a4 | 427 | |
2fa0b342 | 428 | |
9b0da7f4 KR |
429 | char * |
430 | buystring (x) | |
431 | CONST char *CONST x; | |
2fa0b342 | 432 | { |
9b0da7f4 | 433 | size_t l = strlen(x)+1; |
2fa0b342 DHW |
434 | char *r = ldmalloc(l); |
435 | memcpy(r, x,l); | |
436 | return r; | |
437 | } | |
c611e285 SC |
438 | |
439 | ||
9d1fe8a4 SC |
440 | /* ('m' for map) Format info message and print on map. */ |
441 | ||
442 | void minfo(va_alist) | |
288897f4 | 443 | va_dcl |
9d1fe8a4 SC |
444 | { |
445 | char *fmt; | |
446 | va_list arg; | |
447 | va_start(arg); | |
448 | fmt = va_arg(arg, char *); | |
449 | vfinfo(config.map_file, fmt, arg); | |
450 | va_end(arg); | |
451 | } | |
452 | ||
453 | ||
9b0da7f4 KR |
454 | static void |
455 | finfo (va_alist) | |
456 | va_dcl | |
457 | { | |
458 | char *fmt; | |
459 | FILE *file; | |
460 | va_list arg; | |
461 | va_start (arg); | |
462 | file = va_arg (arg, FILE *); | |
463 | fmt = va_arg (arg, char *); | |
464 | vfinfo (file, fmt, arg); | |
465 | va_end (arg); | |
466 | } | |
9d1fe8a4 SC |
467 | |
468 | ||
469 | ||
c611e285 SC |
470 | /*---------------------------------------------------------------------- |
471 | Functions to print the link map | |
472 | */ | |
473 | ||
474 | void | |
9b0da7f4 | 475 | print_space () |
c611e285 | 476 | { |
9d1fe8a4 | 477 | fprintf(config.map_file, " "); |
c611e285 SC |
478 | } |
479 | void | |
9b0da7f4 | 480 | print_nl () |
c611e285 | 481 | { |
9d1fe8a4 | 482 | fprintf(config.map_file, "\n"); |
c611e285 SC |
483 | } |
484 | void | |
9b0da7f4 KR |
485 | print_address (value) |
486 | bfd_vma value; | |
c611e285 | 487 | { |
9d1fe8a4 | 488 | fprintf_vma(config.map_file, value); |
c611e285 | 489 | } |