1 /* ldwrite.c -- write out the linked file
2 Copyright (C) 1993 Free Software Foundation, Inc.
3 Written by Steve Chamberlain sac@cygnus.com
5 This file is part of GLD, the Gnu Linker.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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));
38 extern char *strdup();
40 /* Build link_order structures for the BFD linker. */
43 build_link_order (statement)
44 lang_statement_union_type *statement;
46 switch (statement->header.type)
48 case lang_data_statement_enum:
50 asection *output_section;
51 struct bfd_link_order *link_order;
54 output_section = statement->data_statement.output_section;
55 ASSERT (output_section->owner == output_bfd);
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");
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);
65 value = statement->data_statement.value;
67 ASSERT (output_section->owner == output_bfd);
68 switch (statement->data_statement.type)
71 bfd_put_64 (output_bfd, value, link_order->u.data.contents);
72 link_order->size = QUAD_SIZE;
75 bfd_put_32 (output_bfd, value, link_order->u.data.contents);
76 link_order->size = LONG_SIZE;
79 bfd_put_16 (output_bfd, value, link_order->u.data.contents);
80 link_order->size = SHORT_SIZE;
83 bfd_put_8 (output_bfd, value, link_order->u.data.contents);
84 link_order->size = BYTE_SIZE;
92 case lang_reloc_statement_enum:
94 lang_reloc_statement_type *rs;
95 asection *output_section;
96 struct bfd_link_order *link_order;
98 rs = &statement->reloc_statement;
100 output_section = rs->output_section;
101 ASSERT (output_section->owner == output_bfd);
103 link_order = bfd_new_link_order (output_bfd, output_section);
104 if (link_order == NULL)
105 einfo ("%P%F: bfd_new_link_order failed\n");
107 link_order->offset = rs->output_vma;
108 link_order->size = bfd_get_reloc_size (rs->howto);
110 link_order->u.reloc.p =
111 ((struct bfd_link_order_reloc *)
112 xmalloc (sizeof (struct bfd_link_order_reloc)));
114 link_order->u.reloc.p->reloc = rs->reloc;
115 link_order->u.reloc.p->addend = rs->addend_value;
117 if (rs->section != (asection *) NULL)
119 ASSERT (rs->name == (const char *) NULL);
120 link_order->type = bfd_section_reloc_link_order;
121 if (rs->section->owner == output_bfd)
122 link_order->u.reloc.p->u.section = rs->section;
125 link_order->u.reloc.p->u.section = rs->section->output_section;
126 link_order->u.reloc.p->addend += rs->section->output_offset;
131 ASSERT (rs->name != (const char *) NULL);
132 link_order->type = bfd_symbol_reloc_link_order;
133 link_order->u.reloc.p->u.name = rs->name;
138 case lang_input_section_enum:
139 /* Create a new link_order in the output section with this
141 if (statement->input_section.ifile->just_syms_flag == false)
143 asection *i = statement->input_section.section;
144 asection *output_section = i->output_section;
146 ASSERT (output_section->owner == output_bfd);
148 if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
150 struct bfd_link_order *link_order;
152 link_order = bfd_new_link_order (output_bfd, output_section);
154 if (i->flags & SEC_NEVER_LOAD)
156 /* We've got a never load section inside one which
157 is going to be output, we'll change it into a
159 link_order->type = bfd_fill_link_order;
160 link_order->u.fill.value = 0;
164 link_order->type = bfd_indirect_link_order;
165 link_order->u.indirect.section = i;
166 ASSERT (i->output_section == output_section);
169 link_order->size = i->_cooked_size;
171 link_order->size = bfd_get_section_size_before_reloc (i);
172 link_order->offset = i->output_offset;
177 case lang_padding_statement_enum:
178 /* Make a new link_order with the right filler */
180 asection *output_section;
181 struct bfd_link_order *link_order;
183 output_section = statement->padding_statement.output_section;
184 ASSERT (statement->padding_statement.output_section->owner
186 if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
188 link_order = bfd_new_link_order (output_bfd, output_section);
189 link_order->type = bfd_fill_link_order;
190 link_order->size = statement->padding_statement.size;
191 link_order->offset = statement->padding_statement.output_offset;
192 link_order->u.fill.value = statement->padding_statement.fill;
198 /* All the other ones fall through */
203 /* Call BFD to write out the linked file. */
206 /**********************************************************************/
209 /* Wander around the input sections, make sure that
210 we'll never try and create an output section with more relocs
211 than will fit.. Do this by always assuming the worst case, and
212 creating new output sections with all the right bits */
215 clone_section (abfd, s, count)
221 char sname[SSIZE]; /* ?? find the name for this size */
223 struct bfd_link_hash_entry *h;
224 /* Invent a section name - use first five
225 chars of base section name and a digit suffix */
230 for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
233 sprintf (sname, "%s%d", b, (*count)++);
235 while (bfd_get_section_by_name (abfd, sname));
237 n = bfd_make_section_anyway (abfd, strdup (sname));
239 /* Create a symbol of the same name */
241 h = bfd_link_hash_lookup (link_info.hash,
242 sname, true, true, false);
243 h->type = bfd_link_hash_defined;
245 h->u.def.section = n ;
250 n->user_set_vma = s->user_set_vma;
254 n->output_offset = s->output_offset;
255 n->output_section = n;
258 n->alignment_power = s->alignment_power;
267 struct bfd_link_order *l = s->link_order_head;
268 printf ("vma %x size %x\n", s->vma, s->_raw_size);
271 if (l->type == bfd_indirect_link_order)
273 printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
277 printf ("%8x something else\n", l->offset);
298 for (s = abfd->sections; s; s = s->next)
300 struct bfd_link_order *p;
302 for (p = s->link_order_head; p; p = p->next)
304 if (p->offset > 100000)
306 if (p->offset < prev)
313 #define sanity_check(a)
314 #define dump(a, b, c)
319 split_sections (abfd, info)
321 struct bfd_link_info *info;
323 asection *original_sec;
324 int nsecs = abfd->section_count;
326 /* look through all the original sections */
327 for (original_sec = abfd->sections;
328 original_sec && nsecs;
329 original_sec = original_sec->next, nsecs--)
331 boolean first = true;
335 struct bfd_link_order **pp;
336 bfd_vma vma = original_sec->vma;
337 bfd_vma shift_offset = 0;
338 asection *cursor = original_sec;
340 /* count up the relocations and line entries to see if
341 anything would be too big to fit */
342 for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
344 struct bfd_link_order *p = *pp;
347 if (p->type == bfd_indirect_link_order)
351 sec = p->u.indirect.section;
353 if (info->strip == strip_none
354 || info->strip == strip_some)
355 thislines = sec->lineno_count;
357 if (info->relocateable)
358 thisrelocs = sec->reloc_count;
361 else if (info->relocateable
362 && (p->type == bfd_section_reloc_link_order
363 || p->type == bfd_symbol_reloc_link_order))
367 && (thisrelocs + relocs > config.split_by_reloc
368 || thislines + lines > config.split_by_reloc
369 || config.split_by_file))
371 /* create a new section and put this link order and the
372 following link orders into it */
373 struct bfd_link_order *l = p;
374 asection *n = clone_section (abfd, cursor, &count);
375 *pp = NULL; /* Snip off link orders from old section */
376 n->link_order_head = l; /* attach to new section */
377 pp = &n->link_order_head;
379 /* change the size of the original section and
380 update the vma of the new one */
382 dump ("before snip", cursor, n);
384 n->_raw_size = cursor->_raw_size - l->offset;
385 cursor->_raw_size = l->offset;
387 vma += cursor->_raw_size;
388 n->lma = n->vma = vma;
390 shift_offset = l->offset;
392 /* run down the chain and change the output section to
393 the right one, update the offsets too */
397 l->offset -= shift_offset;
398 if (l->type == bfd_indirect_link_order)
400 l->u.indirect.section->output_section = n;
401 l->u.indirect.section->output_offset = l->offset;
405 dump ("after snip", cursor, n);
412 relocs += thisrelocs;
421 /**********************************************************************/
425 /* Reset error indicator, which can typically something like invalid
426 format from openning up the .o files */
427 bfd_set_error (bfd_error_no_error);
428 lang_for_each_statement (build_link_order);
430 if (config.split_by_reloc || config.split_by_file)
431 split_sections (output_bfd, &link_info);
432 if (!bfd_final_link (output_bfd, &link_info))
434 /* If there was an error recorded, print it out. Otherwise assume
435 an appropriate error message like unknown symbol was printed
438 if (bfd_get_error () != bfd_error_no_error)
439 einfo ("%F%P: final link failed: %E\n", output_bfd);
446 print_symbol_table ();
451 /* Print the symbol table. */
454 print_symbol_table ()
456 fprintf (config.map_file, "**FILES**\n\n");
457 lang_for_each_file (print_file_stuff);
459 fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
460 fprintf (config.map_file, "offset section offset symbol\n");
461 bfd_link_hash_traverse (link_info.hash, print_symbol, (PTR) NULL);
464 /* Print information about a file. */
468 lang_input_statement_type *f;
470 fprintf (config.map_file, " %s\n", f->filename);
471 if (f->just_syms_flag)
473 fprintf (config.map_file, " symbols only\n");
480 for (s = f->the_bfd->sections;
481 s != (asection *) NULL;
485 /* Don't include any information that goes into the '.junk'
486 section. This includes the code view .debug$ data and
487 stuff from .drectve sections */
488 if (strcmp (s->name, ".drectve") == 0 ||
489 strncmp (s->name, ".debug$", 7) == 0)
492 print_address (s->output_offset);
495 fprintf (config.map_file, " %08x 2**%2ud %s\n",
496 (unsigned) bfd_get_section_size_after_reloc (s),
497 s->alignment_power, s->name);
502 fprintf (config.map_file, " %08x 2**%2ud %s\n",
503 (unsigned) bfd_get_section_size_before_reloc (s),
504 s->alignment_power, s->name);
510 for (s = f->the_bfd->sections;
511 s != (asection *) NULL;
514 fprintf (config.map_file, "%s ", s->name);
515 print_address (s->output_offset);
516 fprintf (config.map_file, "(%x)",
517 (unsigned) bfd_get_section_size_after_reloc (s));
519 fprintf (config.map_file, "hex \n");
525 /* Print a symbol. */
529 print_symbol (p, ignore)
530 struct bfd_link_hash_entry *p;
533 while (p->type == bfd_link_hash_indirect
534 || p->type == bfd_link_hash_warning)
539 case bfd_link_hash_new:
542 case bfd_link_hash_undefined:
543 fprintf (config.map_file, "undefined ");
544 fprintf (config.map_file, "%s ", p->root.string);
548 case bfd_link_hash_undefweak:
549 fprintf (config.map_file, "weak ");
550 fprintf (config.map_file, "%s ", p->root.string);
554 case bfd_link_hash_defined:
555 case bfd_link_hash_defweak:
557 asection *defsec = p->u.def.section;
559 print_address (p->u.def.value);
562 fprintf (config.map_file, " %-10s",
563 bfd_section_name (output_bfd, defsec));
565 print_address (p->u.def.value + defsec->vma);
569 fprintf (config.map_file, " .......");
571 fprintf (config.map_file, " %s", p->root.string);
572 if (p->type == bfd_link_hash_defweak)
573 fprintf (config.map_file, " [weak]");
578 case bfd_link_hash_common:
579 fprintf (config.map_file, "common ");
580 print_address (p->u.c.size);
581 fprintf (config.map_file, " %s ", p->root.string);