Warning fix and remove extraneous hppa*-*-linux-gnu*.
[deliverable/binutils-gdb.git] / ld / ldwrite.c
1 /* ldwrite.c -- write out the linked file
2 Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
3 Free Software Foundation, Inc.
4 Written by Steve Chamberlain sac@cygnus.com
5
6 This file is part of GLD, the Gnu Linker.
7
8 This program 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 of the License, or
11 (at your option) any later version.
12
13 This program 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 this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "bfdlink.h"
25 #include "libiberty.h"
26
27 #include "ld.h"
28 #include "ldexp.h"
29 #include "ldlang.h"
30 #include "ldwrite.h"
31 #include "ldmisc.h"
32 #include "ldgram.h"
33 #include "ldmain.h"
34
35 static void build_link_order PARAMS ((lang_statement_union_type *));
36 static asection *clone_section PARAMS ((bfd *, asection *, int *));
37 static void split_sections PARAMS ((bfd *, struct bfd_link_info *));
38
39 /* Build link_order structures for the BFD linker. */
40
41 static void
42 build_link_order (statement)
43 lang_statement_union_type *statement;
44 {
45 switch (statement->header.type)
46 {
47 case lang_data_statement_enum:
48 {
49 asection *output_section;
50 struct bfd_link_order *link_order;
51 bfd_vma value;
52 boolean big_endian = false;
53
54 output_section = statement->data_statement.output_section;
55 ASSERT (output_section->owner == output_bfd);
56
57 link_order = bfd_new_link_order (output_bfd, output_section);
58 if (link_order == NULL)
59 einfo (_("%P%F: bfd_new_link_order failed\n"));
60
61 link_order->type = bfd_data_link_order;
62 link_order->offset = statement->data_statement.output_vma;
63 link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
64
65 value = statement->data_statement.value;
66
67 /* If the endianness of the output BFD is not known, then we
68 base the endianness of the data on the first input file.
69 By convention, the bfd_put routines for an unknown
70 endianness are big endian, so we must swap here if the
71 input file is little endian. */
72 if (bfd_big_endian (output_bfd))
73 big_endian = true;
74 else if (bfd_little_endian (output_bfd))
75 big_endian = false;
76 else
77 {
78 boolean swap;
79
80 swap = false;
81 if (command_line.endian == ENDIAN_BIG)
82 big_endian = true;
83 else if (command_line.endian == ENDIAN_LITTLE)
84 {
85 big_endian = false;
86 swap = true;
87 }
88 else if (command_line.endian == ENDIAN_UNSET)
89 {
90 big_endian = true;
91 {
92 LANG_FOR_EACH_INPUT_STATEMENT (s)
93 {
94 if (s->the_bfd != NULL)
95 {
96 if (bfd_little_endian (s->the_bfd))
97 {
98 big_endian = false;
99 swap = true;
100 }
101 break;
102 }
103 }
104 }
105 }
106
107 if (swap)
108 {
109 bfd_byte buffer[8];
110
111 switch (statement->data_statement.type)
112 {
113 case QUAD:
114 case SQUAD:
115 if (sizeof (bfd_vma) >= QUAD_SIZE)
116 {
117 bfd_putl64 (value, buffer);
118 value = bfd_getb64 (buffer);
119 break;
120 }
121 /* Fall through. */
122 case LONG:
123 bfd_putl32 (value, buffer);
124 value = bfd_getb32 (buffer);
125 break;
126 case SHORT:
127 bfd_putl16 (value, buffer);
128 value = bfd_getb16 (buffer);
129 break;
130 case BYTE:
131 break;
132 default:
133 abort ();
134 }
135 }
136 }
137
138 ASSERT (output_section->owner == output_bfd);
139 switch (statement->data_statement.type)
140 {
141 case QUAD:
142 case SQUAD:
143 if (sizeof (bfd_vma) >= QUAD_SIZE)
144 bfd_put_64 (output_bfd, value, link_order->u.data.contents);
145 else
146 {
147 bfd_vma high;
148
149 if (statement->data_statement.type == QUAD)
150 high = 0;
151 else if ((value & 0x80000000) == 0)
152 high = 0;
153 else
154 high = (bfd_vma) -1;
155 bfd_put_32 (output_bfd, high,
156 (link_order->u.data.contents
157 + (big_endian ? 0 : 4)));
158 bfd_put_32 (output_bfd, value,
159 (link_order->u.data.contents
160 + (big_endian ? 4 : 0)));
161 }
162 link_order->size = QUAD_SIZE;
163 break;
164 case LONG:
165 bfd_put_32 (output_bfd, value, link_order->u.data.contents);
166 link_order->size = LONG_SIZE;
167 break;
168 case SHORT:
169 bfd_put_16 (output_bfd, value, link_order->u.data.contents);
170 link_order->size = SHORT_SIZE;
171 break;
172 case BYTE:
173 bfd_put_8 (output_bfd, value, link_order->u.data.contents);
174 link_order->size = BYTE_SIZE;
175 break;
176 default:
177 abort ();
178 }
179 }
180 break;
181
182 case lang_reloc_statement_enum:
183 {
184 lang_reloc_statement_type *rs;
185 asection *output_section;
186 struct bfd_link_order *link_order;
187
188 rs = &statement->reloc_statement;
189
190 output_section = rs->output_section;
191 ASSERT (output_section->owner == output_bfd);
192
193 link_order = bfd_new_link_order (output_bfd, output_section);
194 if (link_order == NULL)
195 einfo (_("%P%F: bfd_new_link_order failed\n"));
196
197 link_order->offset = rs->output_vma;
198 link_order->size = bfd_get_reloc_size (rs->howto);
199
200 link_order->u.reloc.p =
201 ((struct bfd_link_order_reloc *)
202 xmalloc (sizeof (struct bfd_link_order_reloc)));
203
204 link_order->u.reloc.p->reloc = rs->reloc;
205 link_order->u.reloc.p->addend = rs->addend_value;
206
207 if (rs->name == NULL)
208 {
209 link_order->type = bfd_section_reloc_link_order;
210 if (rs->section->owner == output_bfd)
211 link_order->u.reloc.p->u.section = rs->section;
212 else
213 {
214 link_order->u.reloc.p->u.section = rs->section->output_section;
215 link_order->u.reloc.p->addend += rs->section->output_offset;
216 }
217 }
218 else
219 {
220 link_order->type = bfd_symbol_reloc_link_order;
221 link_order->u.reloc.p->u.name = rs->name;
222 }
223 }
224 break;
225
226 case lang_input_section_enum:
227 /* Create a new link_order in the output section with this
228 attached */
229 if (statement->input_section.ifile->just_syms_flag == false)
230 {
231 asection *i = statement->input_section.section;
232 asection *output_section = i->output_section;
233
234 ASSERT (output_section->owner == output_bfd);
235
236 if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
237 {
238 struct bfd_link_order *link_order;
239
240 link_order = bfd_new_link_order (output_bfd, output_section);
241
242 if (i->flags & SEC_NEVER_LOAD)
243 {
244 /* We've got a never load section inside one which
245 is going to be output, we'll change it into a
246 fill link_order */
247 link_order->type = bfd_fill_link_order;
248 link_order->u.fill.value = 0;
249 }
250 else
251 {
252 link_order->type = bfd_indirect_link_order;
253 link_order->u.indirect.section = i;
254 ASSERT (i->output_section == output_section);
255 }
256 if (i->_cooked_size)
257 link_order->size = i->_cooked_size;
258 else
259 link_order->size = bfd_get_section_size_before_reloc (i);
260 link_order->offset = i->output_offset;
261 }
262 }
263 break;
264
265 case lang_padding_statement_enum:
266 /* Make a new link_order with the right filler */
267 {
268 asection *output_section;
269 struct bfd_link_order *link_order;
270
271 output_section = statement->padding_statement.output_section;
272 ASSERT (statement->padding_statement.output_section->owner
273 == output_bfd);
274 if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
275 {
276 link_order = bfd_new_link_order (output_bfd, output_section);
277 link_order->type = bfd_fill_link_order;
278 link_order->size = statement->padding_statement.size;
279 link_order->offset = statement->padding_statement.output_offset;
280 link_order->u.fill.value = statement->padding_statement.fill;
281 }
282 }
283 break;
284
285 default:
286 /* All the other ones fall through */
287 break;
288 }
289 }
290
291 /* Call BFD to write out the linked file. */
292
293
294 /**********************************************************************/
295
296
297 /* Wander around the input sections, make sure that
298 we'll never try and create an output section with more relocs
299 than will fit.. Do this by always assuming the worst case, and
300 creating new output sections with all the right bits */
301 #define TESTIT 1
302 static asection *
303 clone_section (abfd, s, count)
304 bfd *abfd;
305 asection *s;
306 int *count;
307 {
308 char sname[8]; /* ?? find the name for this size */
309 asection *n;
310 struct bfd_link_hash_entry *h;
311 /* Invent a section name - use first five
312 chars of base section name and a digit suffix */
313 do
314 {
315 unsigned int i;
316 char b[6];
317 for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
318 b[i] = s->name[i];
319 b[i] = 0;
320 sprintf (sname, "%s%d", b, (*count)++);
321 }
322 while (bfd_get_section_by_name (abfd, sname));
323
324 n = bfd_make_section_anyway (abfd, xstrdup (sname));
325
326 /* Create a symbol of the same name */
327
328 h = bfd_link_hash_lookup (link_info.hash,
329 sname, true, true, false);
330 h->type = bfd_link_hash_defined;
331 h->u.def.value = 0;
332 h->u.def.section = n ;
333
334
335 n->flags = s->flags;
336 n->vma = s->vma;
337 n->user_set_vma = s->user_set_vma;
338 n->lma = s->lma;
339 n->_cooked_size = 0;
340 n->_raw_size = 0;
341 n->output_offset = s->output_offset;
342 n->output_section = n;
343 n->orelocation = 0;
344 n->reloc_count = 0;
345 n->alignment_power = s->alignment_power;
346 return n;
347 }
348
349 #if TESTING
350 static void
351 ds (s)
352 asection *s;
353 {
354 struct bfd_link_order *l = s->link_order_head;
355 printf ("vma %x size %x\n", s->vma, s->_raw_size);
356 while (l)
357 {
358 if (l->type == bfd_indirect_link_order)
359 {
360 printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
361 }
362 else
363 {
364 printf (_("%8x something else\n"), l->offset);
365 }
366 l = l->next;
367 }
368 printf ("\n");
369 }
370 dump (s, a1, a2)
371 char *s;
372 asection *a1;
373 asection *a2;
374 {
375 printf ("%s\n", s);
376 ds (a1);
377 ds (a2);
378 }
379
380 static void
381 sanity_check (abfd)
382 bfd *abfd;
383 {
384 asection *s;
385 for (s = abfd->sections; s; s = s->next)
386 {
387 struct bfd_link_order *p;
388 bfd_vma prev = 0;
389 for (p = s->link_order_head; p; p = p->next)
390 {
391 if (p->offset > 100000)
392 abort ();
393 if (p->offset < prev)
394 abort ();
395 prev = p->offset;
396 }
397 }
398 }
399 #else
400 #define sanity_check(a)
401 #define dump(a, b, c)
402 #endif
403
404 static void
405 split_sections (abfd, info)
406 bfd *abfd;
407 struct bfd_link_info *info;
408 {
409 asection *original_sec;
410 int nsecs = abfd->section_count;
411 sanity_check (abfd);
412 /* look through all the original sections */
413 for (original_sec = abfd->sections;
414 original_sec && nsecs;
415 original_sec = original_sec->next, nsecs--)
416 {
417 boolean first = true;
418 int count = 0;
419 int lines = 0;
420 int relocs = 0;
421 struct bfd_link_order **pp;
422 bfd_vma vma = original_sec->vma;
423 bfd_vma shift_offset = 0;
424 asection *cursor = original_sec;
425
426 /* count up the relocations and line entries to see if
427 anything would be too big to fit */
428 for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
429 {
430 struct bfd_link_order *p = *pp;
431 int thislines = 0;
432 int thisrelocs = 0;
433 if (p->type == bfd_indirect_link_order)
434 {
435 asection *sec;
436
437 sec = p->u.indirect.section;
438
439 if (info->strip == strip_none
440 || info->strip == strip_some)
441 thislines = sec->lineno_count;
442
443 if (info->relocateable)
444 thisrelocs = sec->reloc_count;
445
446 }
447 else if (info->relocateable
448 && (p->type == bfd_section_reloc_link_order
449 || p->type == bfd_symbol_reloc_link_order))
450 thisrelocs++;
451
452 if (! first
453 && (thisrelocs + relocs > config.split_by_reloc
454 || thislines + lines > config.split_by_reloc
455 || config.split_by_file))
456 {
457 /* create a new section and put this link order and the
458 following link orders into it */
459 struct bfd_link_order *l = p;
460 asection *n = clone_section (abfd, cursor, &count);
461 *pp = NULL; /* Snip off link orders from old section */
462 n->link_order_head = l; /* attach to new section */
463 pp = &n->link_order_head;
464
465 /* change the size of the original section and
466 update the vma of the new one */
467
468 dump ("before snip", cursor, n);
469
470 n->_raw_size = cursor->_raw_size - l->offset;
471 cursor->_raw_size = l->offset;
472
473 vma += cursor->_raw_size;
474 n->lma = n->vma = vma;
475
476 shift_offset = l->offset;
477
478 /* run down the chain and change the output section to
479 the right one, update the offsets too */
480
481 while (l)
482 {
483 l->offset -= shift_offset;
484 if (l->type == bfd_indirect_link_order)
485 {
486 l->u.indirect.section->output_section = n;
487 l->u.indirect.section->output_offset = l->offset;
488 }
489 l = l->next;
490 }
491 dump ("after snip", cursor, n);
492 cursor = n;
493 relocs = thisrelocs;
494 lines = thislines;
495 }
496 else
497 {
498 relocs += thisrelocs;
499 lines += thislines;
500 }
501
502 first = false;
503 }
504 }
505 sanity_check (abfd);
506 }
507 /**********************************************************************/
508 void
509 ldwrite ()
510 {
511 /* Reset error indicator, which can typically something like invalid
512 format from openning up the .o files */
513 bfd_set_error (bfd_error_no_error);
514 lang_for_each_statement (build_link_order);
515
516 if (config.split_by_reloc || config.split_by_file)
517 split_sections (output_bfd, &link_info);
518 if (!bfd_final_link (output_bfd, &link_info))
519 {
520 /* If there was an error recorded, print it out. Otherwise assume
521 an appropriate error message like unknown symbol was printed
522 out. */
523
524 if (bfd_get_error () != bfd_error_no_error)
525 einfo (_("%F%P: final link failed: %E\n"), output_bfd);
526 else
527 xexit(1);
528 }
529 }
This page took 0.039929 seconds and 5 git commands to generate.