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