Make the ELF linker handle orphaned sections reasonably. Also,
[deliverable/binutils-gdb.git] / ld / ldmisc.c
1 /* ldmisc.c
2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
3
4 Written by Steve Chamberlain of Cygnus Support.
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
10 the Free Software Foundation; either version 2, or (at your option)
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
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include <varargs.h>
25 #include <demangle.h>
26
27 #include "ld.h"
28 #include "ldmisc.h"
29 #include "ldexp.h"
30 #include "ldlang.h"
31 #include "ldlex.h"
32 #include "ldmain.h"
33 #include "ldfile.h"
34
35 /* VARARGS*/
36 static void finfo ();
37 static const char *demangle PARAMS ((const char *string,
38 int remove_underscore));
39
40 /*
41 %% literal %
42 %F error is fatal
43 %P print program name
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
48 %T symbol name
49 %X no object output, fail return
50 %V hex bfd_vma
51 %v hex bfd_vma, no leading zeros
52 %C Clever filename:linenumber
53 %R info about a relent
54 %s arbitrary string, like printf
55 %d integer, like printf
56 */
57
58 static const char *
59 demangle (string, remove_underscore)
60 const char *string;
61 int remove_underscore;
62 {
63 const char *res;
64 if (remove_underscore && output_bfd)
65 {
66 if (bfd_get_symbol_leading_char (output_bfd) == string[0])
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 */
73 res = cplus_demangle (string, DMGL_ANSI|DMGL_PARAMS);
74 return res ? res : string;
75 }
76
77 static void
78 vfinfo(fp, fmt, arg)
79 FILE *fp;
80 char *fmt;
81 va_list arg;
82 {
83 boolean fatal = false;
84
85 while (*fmt)
86 {
87 while (*fmt != '%' && *fmt != '\0')
88 {
89 putc(*fmt, fp);
90 fmt++;
91 }
92
93 if (*fmt == '%')
94 {
95 fmt ++;
96 switch (*fmt++)
97 {
98 default:
99 fprintf(fp,"%%%c", fmt[-1]);
100 break;
101
102 case '%':
103 /* literal % */
104 putc('%', fp);
105 break;
106
107 case 'X':
108 /* no object output, fail return */
109 config.make_executable = false;
110 break;
111
112 case 'V':
113 /* hex bfd_vma */
114 {
115 bfd_vma value = va_arg(arg, bfd_vma);
116 fprintf_vma(fp, value);
117 }
118 break;
119
120 case 'v':
121 /* hex bfd_vma, no leading zeros */
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;
134
135 case 'T':
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 }
145 break;
146
147 case 'B':
148 /* filename from a bfd */
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);
157 }
158 }
159 break;
160
161 case 'F':
162 /* error is fatal */
163 fatal = true;
164 break;
165
166 case 'P':
167 /* print program name */
168 fprintf(fp,"%s", program_name);
169 break;
170
171 case 'E':
172 /* current bfd error or errno */
173 fprintf(fp, bfd_errmsg(bfd_get_error ()));
174 break;
175
176 case 'I':
177 /* filename from a lang_input_statement_type */
178 {
179 lang_input_statement_type *i =
180 va_arg(arg,lang_input_statement_type *);
181
182 if (i->the_bfd->my_archive)
183 fprintf(fp, "(%s)", i->the_bfd->my_archive->filename);
184 fprintf(fp,"%s", i->local_sym_name);
185 }
186 break;
187
188 case 'S':
189 /* print script file and linenumber */
190 {
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 }
198 break;
199
200 case 'R':
201 /* Print all that's interesting about a relent */
202 {
203 arelent *relent = va_arg(arg, arelent *);
204
205 finfo (fp, "%s+0x%v (type %s)",
206 (*(relent->sym_ptr_ptr))->name,
207 relent->addend,
208 relent->howto->name);
209 }
210 break;
211
212 case 'C':
213 /* Clever filename:linenumber with function name if possible,
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 **) xmalloc (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 }
267 break;
268
269 case 's':
270 /* arbitrary string, like printf */
271 fprintf(fp,"%s", va_arg(arg, char *));
272 break;
273
274 case 'd':
275 /* integer, like printf */
276 fprintf(fp,"%d", va_arg(arg, int));
277 break;
278 }
279 }
280 }
281
282 if (fatal == true)
283 xexit(1);
284 }
285
286 /* Format info message and print on stdout. */
287
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)
292 va_dcl
293 {
294 char *fmt;
295 va_list arg;
296 va_start(arg);
297 fmt = va_arg(arg, char *);
298 vfinfo(stdout, fmt, arg);
299 va_end(arg);
300 }
301
302 /* ('e' for error.) Format info message and print on stderr. */
303
304 void einfo(va_alist)
305 va_dcl
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 }
314
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 {
327 lang_input_statement_type *inp_stat;
328 asymbol **stat_symbols;
329
330 inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (newsym)->usrdata;
331 stat_symbols = inp_stat ? inp_stat->asymbols : 0;
332
333 einfo (message1,
334 bfd_asymbol_bfd (newsym), newsym->section, stat_symbols, newsym->value,
335 demangle (newsym->name, 1));
336
337 inp_stat = (lang_input_statement_type *) bfd_asymbol_bfd (oldsym)->usrdata;
338 stat_symbols = inp_stat ? inp_stat->asymbols : 0;
339
340 einfo (message2,
341 bfd_asymbol_bfd (oldsym), oldsym->section, stat_symbols, oldsym->value);
342 }
343
344 void
345 info_assert(file, line)
346 char *file;
347 unsigned int line;
348 {
349 einfo("%F%P: internal error %s %d\n", file,line);
350 }
351
352 /* Return a newly-allocated string
353 whose contents concatenate those of S1, S2, S3. */
354
355 char *
356 concat (s1, s2, s3)
357 CONST char *s1;
358 CONST char *s2;
359 CONST char *s3;
360 {
361 size_t len1 = strlen (s1);
362 size_t len2 = strlen (s2);
363 size_t len3 = strlen (s3);
364 char *result = xmalloc (len1 + len2 + len3 + 1);
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
377 char *
378 buystring (x)
379 CONST char *CONST x;
380 {
381 size_t l = strlen(x)+1;
382 char *r = xmalloc(l);
383 memcpy(r, x,l);
384 return r;
385 }
386
387
388 /* ('m' for map) Format info message and print on map. */
389
390 void minfo(va_alist)
391 va_dcl
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
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 }
415
416
417
418 /*----------------------------------------------------------------------
419 Functions to print the link map
420 */
421
422 void
423 print_space ()
424 {
425 fprintf(config.map_file, " ");
426 }
427 void
428 print_nl ()
429 {
430 fprintf(config.map_file, "\n");
431 }
432 void
433 print_address (value)
434 bfd_vma value;
435 {
436 fprintf_vma(config.map_file, value);
437 }
This page took 0.037263 seconds and 4 git commands to generate.