]>
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" |
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 */ |
5bcb7f28 | 173 | fprintf(fp, bfd_errmsg(bfd_get_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); | |
5bcb7f28 | 240 | asymbols = (asymbol **) xmalloc (symsize); |
288897f4 DM |
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 | 282 | if (fatal == true) |
5bcb7f28 | 283 | xexit(1); |
c611e285 SC |
284 | } |
285 | ||
286 | /* Format info message and print on stdout. */ | |
287 | ||
fcf276c4 ILT |
288 | /* (You would think this should be called just "info", but then you would |
289 | hosed by LynxOS, which defines that name in its libc.) */ | |
290 | ||
291 | void info_msg(va_alist) | |
288897f4 | 292 | va_dcl |
c611e285 SC |
293 | { |
294 | char *fmt; | |
295 | va_list arg; | |
296 | va_start(arg); | |
297 | fmt = va_arg(arg, char *); | |
298 | vfinfo(stdout, fmt, arg); | |
2fa0b342 DHW |
299 | va_end(arg); |
300 | } | |
301 | ||
c611e285 SC |
302 | /* ('e' for error.) Format info message and print on stderr. */ |
303 | ||
304 | void einfo(va_alist) | |
288897f4 | 305 | va_dcl |
c611e285 SC |
306 | { |
307 | char *fmt; | |
308 | va_list arg; | |
309 | va_start(arg); | |
310 | fmt = va_arg(arg, char *); | |
311 | vfinfo(stderr, fmt, arg); | |
312 | va_end(arg); | |
313 | } | |
2fa0b342 | 314 | |
2a28d8b0 DM |
315 | /* Warn about a symbol NEWSYM being multiply defined with another symbol OLDSYM. |
316 | MESSAGE1 and MESSAGE2 should look something like: | |
317 | "%C: warning: multiple commons of `%s'\n" | |
318 | "%C: warning: previous common here\n" */ | |
319 | ||
320 | void | |
321 | multiple_warn (message1, newsym, message2, oldsym) | |
322 | char *message1; | |
323 | asymbol *newsym; | |
324 | char *message2; | |
325 | asymbol *oldsym; | |
326 | { | |
288897f4 | 327 | lang_input_statement_type *inp_stat; |
2a28d8b0 DM |
328 | asymbol **stat_symbols; |
329 | ||
288897f4 DM |
330 | inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (newsym)->usrdata; |
331 | stat_symbols = inp_stat ? inp_stat->asymbols : 0; | |
2a28d8b0 DM |
332 | |
333 | einfo (message1, | |
334 | bfd_asymbol_bfd (newsym), newsym->section, stat_symbols, newsym->value, | |
335 | demangle (newsym->name, 1)); | |
336 | ||
288897f4 DM |
337 | inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (oldsym)->usrdata; |
338 | stat_symbols = inp_stat ? inp_stat->asymbols : 0; | |
2a28d8b0 DM |
339 | |
340 | einfo (message2, | |
341 | bfd_asymbol_bfd (oldsym), oldsym->section, stat_symbols, oldsym->value); | |
342 | } | |
343 | ||
2fa0b342 DHW |
344 | void |
345 | info_assert(file, line) | |
2a28d8b0 DM |
346 | char *file; |
347 | unsigned int line; | |
2fa0b342 | 348 | { |
fcf276c4 | 349 | einfo("%F%P: internal error %s %d\n", file,line); |
2fa0b342 DHW |
350 | } |
351 | ||
352 | /* Return a newly-allocated string | |
353 | whose contents concatenate those of S1, S2, S3. */ | |
354 | ||
355 | char * | |
9b0da7f4 KR |
356 | concat (s1, s2, s3) |
357 | CONST char *s1; | |
358 | CONST char *s2; | |
359 | CONST char *s3; | |
2fa0b342 | 360 | { |
9b0da7f4 KR |
361 | size_t len1 = strlen (s1); |
362 | size_t len2 = strlen (s2); | |
363 | size_t len3 = strlen (s3); | |
5bcb7f28 | 364 | char *result = xmalloc (len1 + len2 + len3 + 1); |
2fa0b342 DHW |
365 | |
366 | if (len1 != 0) | |
367 | memcpy(result, s1, len1); | |
368 | if (len2 != 0) | |
369 | memcpy(result+len1, s2, len2); | |
370 | if (len3 != 0) | |
371 | memcpy(result+len1+len2, s2, len3); | |
372 | *(result + len1 + len2 + len3) = 0; | |
373 | ||
374 | return result; | |
375 | } | |
376 | ||
9b0da7f4 KR |
377 | char * |
378 | buystring (x) | |
379 | CONST char *CONST x; | |
2fa0b342 | 380 | { |
9b0da7f4 | 381 | size_t l = strlen(x)+1; |
5bcb7f28 | 382 | char *r = xmalloc(l); |
2fa0b342 DHW |
383 | memcpy(r, x,l); |
384 | return r; | |
385 | } | |
c611e285 SC |
386 | |
387 | ||
9d1fe8a4 SC |
388 | /* ('m' for map) Format info message and print on map. */ |
389 | ||
390 | void minfo(va_alist) | |
288897f4 | 391 | va_dcl |
9d1fe8a4 SC |
392 | { |
393 | char *fmt; | |
394 | va_list arg; | |
395 | va_start(arg); | |
396 | fmt = va_arg(arg, char *); | |
397 | vfinfo(config.map_file, fmt, arg); | |
398 | va_end(arg); | |
399 | } | |
400 | ||
401 | ||
9b0da7f4 KR |
402 | static void |
403 | finfo (va_alist) | |
404 | va_dcl | |
405 | { | |
406 | char *fmt; | |
407 | FILE *file; | |
408 | va_list arg; | |
409 | va_start (arg); | |
410 | file = va_arg (arg, FILE *); | |
411 | fmt = va_arg (arg, char *); | |
412 | vfinfo (file, fmt, arg); | |
413 | va_end (arg); | |
414 | } | |
9d1fe8a4 SC |
415 | |
416 | ||
417 | ||
c611e285 SC |
418 | /*---------------------------------------------------------------------- |
419 | Functions to print the link map | |
420 | */ | |
421 | ||
422 | void | |
9b0da7f4 | 423 | print_space () |
c611e285 | 424 | { |
9d1fe8a4 | 425 | fprintf(config.map_file, " "); |
c611e285 SC |
426 | } |
427 | void | |
9b0da7f4 | 428 | print_nl () |
c611e285 | 429 | { |
9d1fe8a4 | 430 | fprintf(config.map_file, "\n"); |
c611e285 SC |
431 | } |
432 | void | |
9b0da7f4 KR |
433 | print_address (value) |
434 | bfd_vma value; | |
c611e285 | 435 | { |
9d1fe8a4 | 436 | fprintf_vma(config.map_file, value); |
c611e285 | 437 | } |