/* ldwrite.c -- write out the linked file
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 2000
- Free Software Foundation, Inc.
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
+ 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Steve Chamberlain sac@cygnus.com
This file is part of GLD, the Gnu Linker.
#include "sysdep.h"
#include "bfdlink.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include "ld.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldwrite.h"
#include "ldmisc.h"
-#include "ldgram.h"
+#include <ldgram.h>
#include "ldmain.h"
-static void build_link_order PARAMS ((lang_statement_union_type *));
-static asection *clone_section PARAMS ((bfd *, asection *, const char *, 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;
+build_link_order (lang_statement_union_type *statement)
{
switch (statement->header.type)
{
asection *output_section;
struct bfd_link_order *link_order;
bfd_vma value;
- boolean big_endian = false;
+ bfd_boolean big_endian = FALSE;
output_section = statement->data_statement.output_section;
ASSERT (output_section->owner == output_bfd);
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);
+ link_order->u.data.contents = xmalloc (QUAD_SIZE);
value = statement->data_statement.value;
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;
+ big_endian = TRUE;
else if (bfd_little_endian (output_bfd))
- big_endian = false;
+ big_endian = FALSE;
else
{
- boolean swap;
+ bfd_boolean swap;
- swap = false;
+ swap = FALSE;
if (command_line.endian == ENDIAN_BIG)
- big_endian = true;
+ big_endian = TRUE;
else if (command_line.endian == ENDIAN_LITTLE)
{
- big_endian = false;
- swap = true;
+ big_endian = FALSE;
+ swap = TRUE;
}
else if (command_line.endian == ENDIAN_UNSET)
{
- big_endian = true;
+ big_endian = TRUE;
{
LANG_FOR_EACH_INPUT_STATEMENT (s)
{
{
if (bfd_little_endian (s->the_bfd))
{
- big_endian = false;
- swap = true;
+ big_endian = FALSE;
+ swap = TRUE;
}
break;
}
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 = xmalloc (sizeof (struct bfd_link_order_reloc));
link_order->u.reloc.p->reloc = rs->reloc;
link_order->u.reloc.p->addend = rs->addend_value;
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)
+ if (!statement->input_section.ifile->just_syms_flag
+ && (statement->input_section.section->flags & SEC_EXCLUDE) == 0)
{
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)
+ if ((output_section->flags & SEC_HAS_CONTENTS) != 0
+ || ((output_section->flags & SEC_LOAD) != 0
+ && (output_section->flags & SEC_THREAD_LOCAL)))
{
struct bfd_link_order *link_order;
{
/* 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;
+ fill. */
+ link_order->type = bfd_data_link_order;
+ link_order->u.data.contents = (unsigned char *) "";
+ link_order->u.data.size = 1;
}
else
{
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->size = i->size;
link_order->offset = i->output_offset;
}
}
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->type = bfd_data_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;
+ link_order->u.data.contents = statement->padding_statement.fill->data;
+ link_order->u.data.size = statement->padding_statement.fill->size;
}
}
break;
}
}
-/* Call BFD to write out the linked file. */
-
-
-/**********************************************************************/
+/* Return true if NAME is the name of an unsplittable section. These
+ are the stabs strings, dwarf strings. */
+static bfd_boolean
+unsplittable_name (const char *name)
+{
+ if (strncmp (name, ".stab", 5) == 0)
+ {
+ /* There are several stab like string sections. We pattern match on
+ ".stab...str" */
+ unsigned len = strlen (name);
+ if (strcmp (&name[len-3], "str") == 0)
+ return TRUE;
+ }
+ else if (strcmp (name, "$GDB_STRINGS$") == 0)
+ return TRUE;
+ return FALSE;
+}
/* Wander around the input sections, make sure that
we'll never try and create an output section with more relocs
creating new output sections with all the right bits. */
#define TESTIT 1
static asection *
-clone_section (abfd, s, name, count)
- bfd *abfd;
- asection *s;
- const char *name;
- int *count;
+clone_section (bfd *abfd, asection *s, const char *name, int *count)
{
- char template[6];
+ char *tname;
char *sname;
+ unsigned int len;
asection *n;
struct bfd_link_hash_entry *h;
- /* Invent a section name from the first five chars of the base
- section name and a digit suffix. */
- strncpy (template, name, sizeof (template) - 1);
- template[sizeof (template) - 1] = '\0';
- sname = bfd_get_unique_section_name (abfd, template, count);
-
- n = bfd_make_section_anyway (abfd, sname);
-
- /* Create a symbol of the same name. */
-
- h = bfd_link_hash_lookup (link_info.hash,
- sname, true, true, false);
+ /* Invent a section name from the section name and a dotted numeric
+ suffix. */
+ len = strlen (name);
+ tname = xmalloc (len + 1);
+ memcpy (tname, name, len + 1);
+ /* Remove a dotted number suffix, from a previous split link. */
+ while (len && ISDIGIT (tname[len-1]))
+ len--;
+ if (len > 1 && tname[len-1] == '.')
+ /* It was a dotted number. */
+ tname[len-1] = 0;
+
+ /* We want to use the whole of the original section name for the
+ split name, but coff can be restricted to 8 character names. */
+ if (bfd_family_coff (abfd) && strlen (tname) > 5)
+ {
+ /* Some section names cannot be truncated, as the name is
+ used to locate some other section. */
+ if (strncmp (name, ".stab", 5) == 0
+ || strcmp (name, "$GDB_SYMBOLS$") == 0)
+ {
+ einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
+ /* Silence gcc warnings. einfo exits, so we never reach here. */
+ return NULL;
+ }
+ tname[5] = 0;
+ }
+
+ if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
+ || (n = bfd_make_section_anyway (abfd, sname)) == NULL
+ || (h = bfd_link_hash_lookup (link_info.hash,
+ sname, TRUE, TRUE, FALSE)) == NULL)
+ {
+ einfo (_("%F%P: clone section failed: %E\n"));
+ /* Silence gcc warnings. einfo exits, so we never reach here. */
+ return NULL;
+ }
+ free (tname);
+
+ /* Set up section symbol. */
h->type = bfd_link_hash_defined;
h->u.def.value = 0;
h->u.def.section = n;
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->size = 0;
n->output_offset = s->output_offset;
n->output_section = n;
n->orelocation = 0;
}
#if TESTING
-static void
-ds (s)
- asection *s;
+static void
+ds (asection *s)
{
struct bfd_link_order *l = s->link_order_head;
- printf ("vma %x size %x\n", s->vma, s->_raw_size);
+ printf ("vma %x size %x\n", s->vma, s->size);
while (l)
{
if (l->type == bfd_indirect_link_order)
}
printf ("\n");
}
-dump (s, a1, a2)
- char *s;
- asection *a1;
- asection *a2;
+
+dump (char *s, asection *a1, asection *a2)
{
printf ("%s\n", s);
ds (a1);
ds (a2);
}
-static void
-sanity_check (abfd)
- bfd *abfd;
+static void
+sanity_check (bfd *abfd)
{
asection *s;
for (s = abfd->sections; s; s = s->next)
#define dump(a, b, c)
#endif
-static void
-split_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+static void
+split_sections (bfd *abfd, struct bfd_link_info *info)
{
asection *original_sec;
int nsecs = abfd->section_count;
|| info->strip == strip_some)
thislines = sec->lineno_count;
- if (info->relocateable)
+ if (info->relocatable)
thisrelocs = sec->reloc_count;
- if (sec->_cooked_size != 0)
- thissize = sec->_cooked_size;
- else
- thissize = sec->_raw_size;
+ thissize = sec->size;
}
- else if (info->relocateable
+ else if (info->relocatable
&& (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order))
thisrelocs++;
if (l != NULL
&& (thisrelocs + relocs >= config.split_by_reloc
|| thislines + lines >= config.split_by_reloc
- || thissize + sec_size >= config.split_by_file))
+ || (thissize + sec_size >= config.split_by_file))
+ && !unsplittable_name (cursor->name))
{
/* Create a new section and put this link order and the
following link orders into it. */
dump ("before snip", cursor, n);
shift_offset = p->offset;
- if (cursor->_cooked_size != 0)
- {
- n->_cooked_size = cursor->_cooked_size - shift_offset;
- cursor->_cooked_size = shift_offset;
- }
- n->_raw_size = cursor->_raw_size - shift_offset;
- cursor->_raw_size = shift_offset;
+ n->size = cursor->size - shift_offset;
+ cursor->size = shift_offset;
vma += shift_offset;
n->lma = n->vma = vma;
}
sanity_check (abfd);
}
-/**********************************************************************/
+
+/* Call BFD to write out the linked file. */
+
void
-ldwrite ()
+ldwrite (void)
{
/* Reset error indicator, which can typically something like invalid
format from opening up the .o files. */
out. */
if (bfd_get_error () != bfd_error_no_error)
- einfo (_("%F%P: final link failed: %E\n"), output_bfd);
+ einfo (_("%F%P: final link failed: %E\n"));
else
- xexit(1);
+ xexit (1);
}
}