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