summaryrefslogtreecommitdiff
path: root/ld/ldwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldwrite.c')
-rw-r--r--ld/ldwrite.c530
1 files changed, 0 insertions, 530 deletions
diff --git a/ld/ldwrite.c b/ld/ldwrite.c
deleted file mode 100644
index b56119a39ac..00000000000
--- a/ld/ldwrite.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/* ldwrite.c -- write out the linked file
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
- Free Software Foundation, Inc.
- Written by Steve Chamberlain sac@cygnus.com
-
-This file is part of GLD, the Gnu Linker.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "bfd.h"
-#include "sysdep.h"
-#include "bfdlink.h"
-#include "libiberty.h"
-
-#include "ld.h"
-#include "ldexp.h"
-#include "ldlang.h"
-#include "ldwrite.h"
-#include "ldmisc.h"
-#include "ldgram.h"
-#include "ldmain.h"
-
-static void build_link_order PARAMS ((lang_statement_union_type *));
-static asection *clone_section PARAMS ((bfd *, asection *, int *));
-static void split_sections PARAMS ((bfd *, struct bfd_link_info *));
-
-/* Build link_order structures for the BFD linker. */
-
-static void
-build_link_order (statement)
- lang_statement_union_type *statement;
-{
- switch (statement->header.type)
- {
- case lang_data_statement_enum:
- {
- asection *output_section;
- struct bfd_link_order *link_order;
- bfd_vma value;
- boolean big_endian = false;
-
- output_section = statement->data_statement.output_section;
- ASSERT (output_section->owner == output_bfd);
-
- link_order = bfd_new_link_order (output_bfd, output_section);
- if (link_order == NULL)
- einfo (_("%P%F: bfd_new_link_order failed\n"));
-
- link_order->type = bfd_data_link_order;
- link_order->offset = statement->data_statement.output_vma;
- link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
-
- value = statement->data_statement.value;
-
- /* If the endianness of the output BFD is not known, then we
- base the endianness of the data on the first input file.
- By convention, the bfd_put routines for an unknown
- endianness are big endian, so we must swap here if the
- input file is little endian. */
- if (bfd_big_endian (output_bfd))
- big_endian = true;
- else if (bfd_little_endian (output_bfd))
- big_endian = false;
- else
- {
- boolean swap;
-
- swap = false;
- if (command_line.endian == ENDIAN_BIG)
- big_endian = true;
- else if (command_line.endian == ENDIAN_LITTLE)
- {
- big_endian = false;
- swap = true;
- }
- else if (command_line.endian == ENDIAN_UNSET)
- {
- big_endian = true;
- {
- LANG_FOR_EACH_INPUT_STATEMENT (s)
- {
- if (s->the_bfd != NULL)
- {
- if (bfd_little_endian (s->the_bfd))
- {
- big_endian = false;
- swap = true;
- }
- break;
- }
- }
- }
- }
-
- if (swap)
- {
- bfd_byte buffer[8];
-
- switch (statement->data_statement.type)
- {
- case QUAD:
- case SQUAD:
- if (sizeof (bfd_vma) >= QUAD_SIZE)
- {
- bfd_putl64 (value, buffer);
- value = bfd_getb64 (buffer);
- break;
- }
- /* Fall through. */
- case LONG:
- bfd_putl32 (value, buffer);
- value = bfd_getb32 (buffer);
- break;
- case SHORT:
- bfd_putl16 (value, buffer);
- value = bfd_getb16 (buffer);
- break;
- case BYTE:
- break;
- default:
- abort ();
- }
- }
- }
-
- ASSERT (output_section->owner == output_bfd);
- switch (statement->data_statement.type)
- {
- case QUAD:
- case SQUAD:
- if (sizeof (bfd_vma) >= QUAD_SIZE)
- bfd_put_64 (output_bfd, value, link_order->u.data.contents);
- else
- {
- bfd_vma high;
-
- if (statement->data_statement.type == QUAD)
- high = 0;
- else if ((value & 0x80000000) == 0)
- high = 0;
- else
- high = (bfd_vma) -1;
- bfd_put_32 (output_bfd, high,
- (link_order->u.data.contents
- + (big_endian ? 0 : 4)));
- bfd_put_32 (output_bfd, value,
- (link_order->u.data.contents
- + (big_endian ? 4 : 0)));
- }
- link_order->size = QUAD_SIZE;
- break;
- case LONG:
- bfd_put_32 (output_bfd, value, link_order->u.data.contents);
- link_order->size = LONG_SIZE;
- break;
- case SHORT:
- bfd_put_16 (output_bfd, value, link_order->u.data.contents);
- link_order->size = SHORT_SIZE;
- break;
- case BYTE:
- bfd_put_8 (output_bfd, value, link_order->u.data.contents);
- link_order->size = BYTE_SIZE;
- break;
- default:
- abort ();
- }
- }
- break;
-
- case lang_reloc_statement_enum:
- {
- lang_reloc_statement_type *rs;
- asection *output_section;
- struct bfd_link_order *link_order;
-
- rs = &statement->reloc_statement;
-
- output_section = rs->output_section;
- ASSERT (output_section->owner == output_bfd);
-
- link_order = bfd_new_link_order (output_bfd, output_section);
- if (link_order == NULL)
- einfo (_("%P%F: bfd_new_link_order failed\n"));
-
- link_order->offset = rs->output_vma;
- link_order->size = bfd_get_reloc_size (rs->howto);
-
- link_order->u.reloc.p =
- ((struct bfd_link_order_reloc *)
- xmalloc (sizeof (struct bfd_link_order_reloc)));
-
- link_order->u.reloc.p->reloc = rs->reloc;
- link_order->u.reloc.p->addend = rs->addend_value;
-
- if (rs->name == NULL)
- {
- link_order->type = bfd_section_reloc_link_order;
- if (rs->section->owner == output_bfd)
- link_order->u.reloc.p->u.section = rs->section;
- else
- {
- link_order->u.reloc.p->u.section = rs->section->output_section;
- link_order->u.reloc.p->addend += rs->section->output_offset;
- }
- }
- else
- {
- link_order->type = bfd_symbol_reloc_link_order;
- link_order->u.reloc.p->u.name = rs->name;
- }
- }
- break;
-
- case lang_input_section_enum:
- /* Create a new link_order in the output section with this
- attached */
- if (statement->input_section.ifile->just_syms_flag == false)
- {
- asection *i = statement->input_section.section;
- asection *output_section = i->output_section;
-
- ASSERT (output_section->owner == output_bfd);
-
- if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
- {
- struct bfd_link_order *link_order;
-
- link_order = bfd_new_link_order (output_bfd, output_section);
-
- if (i->flags & SEC_NEVER_LOAD)
- {
- /* We've got a never load section inside one which
- is going to be output, we'll change it into a
- fill link_order */
- link_order->type = bfd_fill_link_order;
- link_order->u.fill.value = 0;
- }
- else
- {
- link_order->type = bfd_indirect_link_order;
- link_order->u.indirect.section = i;
- ASSERT (i->output_section == output_section);
- }
- if (i->_cooked_size)
- link_order->size = i->_cooked_size;
- else
- link_order->size = bfd_get_section_size_before_reloc (i);
- link_order->offset = i->output_offset;
- }
- }
- break;
-
- case lang_padding_statement_enum:
- /* Make a new link_order with the right filler */
- {
- asection *output_section;
- struct bfd_link_order *link_order;
-
- output_section = statement->padding_statement.output_section;
- ASSERT (statement->padding_statement.output_section->owner
- == output_bfd);
- if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
- {
- link_order = bfd_new_link_order (output_bfd, output_section);
- link_order->type = bfd_fill_link_order;
- link_order->size = statement->padding_statement.size;
- link_order->offset = statement->padding_statement.output_offset;
- link_order->u.fill.value = statement->padding_statement.fill;
- }
- }
- break;
-
- default:
- /* All the other ones fall through */
- break;
- }
-}
-
-/* Call BFD to write out the linked file. */
-
-
-/**********************************************************************/
-
-
-/* Wander around the input sections, make sure that
- we'll never try and create an output section with more relocs
- than will fit.. Do this by always assuming the worst case, and
- creating new output sections with all the right bits */
-#define TESTIT 1
-static asection *
-clone_section (abfd, s, count)
- bfd *abfd;
- asection *s;
- int *count;
-{
-#define SSIZE 8
- char sname[SSIZE]; /* ?? find the name for this size */
- asection *n;
- struct bfd_link_hash_entry *h;
- /* Invent a section name - use first five
- chars of base section name and a digit suffix */
- do
- {
- unsigned int i;
- char b[6];
- for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
- b[i] = s->name[i];
- b[i] = 0;
- sprintf (sname, "%s%d", b, (*count)++);
- }
- while (bfd_get_section_by_name (abfd, sname));
-
- n = bfd_make_section_anyway (abfd, xstrdup (sname));
-
- /* Create a symbol of the same name */
-
- h = bfd_link_hash_lookup (link_info.hash,
- sname, true, true, false);
- h->type = bfd_link_hash_defined;
- h->u.def.value = 0;
- h->u.def.section = n ;
-
-
- n->flags = s->flags;
- n->vma = s->vma;
- n->user_set_vma = s->user_set_vma;
- n->lma = s->lma;
- n->_cooked_size = 0;
- n->_raw_size = 0;
- n->output_offset = s->output_offset;
- n->output_section = n;
- n->orelocation = 0;
- n->reloc_count = 0;
- n->alignment_power = s->alignment_power;
- return n;
-}
-
-#if TESTING
-static void
-ds (s)
- asection *s;
-{
- struct bfd_link_order *l = s->link_order_head;
- printf ("vma %x size %x\n", s->vma, s->_raw_size);
- while (l)
- {
- if (l->type == bfd_indirect_link_order)
- {
- printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
- }
- else
- {
- printf (_("%8x something else\n"), l->offset);
- }
- l = l->next;
- }
- printf ("\n");
-}
-dump (s, a1, a2)
- char *s;
- asection *a1;
- asection *a2;
-{
- printf ("%s\n", s);
- ds (a1);
- ds (a2);
-}
-
-static void
-sanity_check (abfd)
- bfd *abfd;
-{
- asection *s;
- for (s = abfd->sections; s; s = s->next)
- {
- struct bfd_link_order *p;
- bfd_vma prev = 0;
- for (p = s->link_order_head; p; p = p->next)
- {
- if (p->offset > 100000)
- abort ();
- if (p->offset < prev)
- abort ();
- prev = p->offset;
- }
- }
-}
-#else
-#define sanity_check(a)
-#define dump(a, b, c)
-#endif
-
-static void
-split_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- asection *original_sec;
- int nsecs = abfd->section_count;
- sanity_check (abfd);
- /* look through all the original sections */
- for (original_sec = abfd->sections;
- original_sec && nsecs;
- original_sec = original_sec->next, nsecs--)
- {
- boolean first = true;
- int count = 0;
- int lines = 0;
- int relocs = 0;
- struct bfd_link_order **pp;
- bfd_vma vma = original_sec->vma;
- bfd_vma shift_offset = 0;
- asection *cursor = original_sec;
-
- /* count up the relocations and line entries to see if
- anything would be too big to fit */
- for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
- {
- struct bfd_link_order *p = *pp;
- int thislines = 0;
- int thisrelocs = 0;
- if (p->type == bfd_indirect_link_order)
- {
- asection *sec;
-
- sec = p->u.indirect.section;
-
- if (info->strip == strip_none
- || info->strip == strip_some)
- thislines = sec->lineno_count;
-
- if (info->relocateable)
- thisrelocs = sec->reloc_count;
-
- }
- else if (info->relocateable
- && (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order))
- thisrelocs++;
-
- if (! first
- && (thisrelocs + relocs > config.split_by_reloc
- || thislines + lines > config.split_by_reloc
- || config.split_by_file))
- {
- /* create a new section and put this link order and the
- following link orders into it */
- struct bfd_link_order *l = p;
- asection *n = clone_section (abfd, cursor, &count);
- *pp = NULL; /* Snip off link orders from old section */
- n->link_order_head = l; /* attach to new section */
- pp = &n->link_order_head;
-
- /* change the size of the original section and
- update the vma of the new one */
-
- dump ("before snip", cursor, n);
-
- n->_raw_size = cursor->_raw_size - l->offset;
- cursor->_raw_size = l->offset;
-
- vma += cursor->_raw_size;
- n->lma = n->vma = vma;
-
- shift_offset = l->offset;
-
- /* run down the chain and change the output section to
- the right one, update the offsets too */
-
- while (l)
- {
- l->offset -= shift_offset;
- if (l->type == bfd_indirect_link_order)
- {
- l->u.indirect.section->output_section = n;
- l->u.indirect.section->output_offset = l->offset;
- }
- l = l->next;
- }
- dump ("after snip", cursor, n);
- cursor = n;
- relocs = thisrelocs;
- lines = thislines;
- }
- else
- {
- relocs += thisrelocs;
- lines += thislines;
- }
-
- first = false;
- }
- }
- sanity_check (abfd);
-}
-/**********************************************************************/
-void
-ldwrite ()
-{
- /* Reset error indicator, which can typically something like invalid
- format from openning up the .o files */
- bfd_set_error (bfd_error_no_error);
- lang_for_each_statement (build_link_order);
-
- if (config.split_by_reloc || config.split_by_file)
- split_sections (output_bfd, &link_info);
- if (!bfd_final_link (output_bfd, &link_info))
- {
- /* If there was an error recorded, print it out. Otherwise assume
- an appropriate error message like unknown symbol was printed
- out. */
-
- if (bfd_get_error () != bfd_error_no_error)
- einfo (_("%F%P: final link failed: %E\n"), output_bfd);
- else
- xexit(1);
- }
-}