/* linker.c -- BFD linker routines
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "bfdlink.h"
#include "genlink.h"
Sometimes the <<_bfd_link_add_symbols>> function must store
some information in the hash table entry to be used by the
- <<_bfd_final_link>> function. In such a case the <<creator>>
- field of the hash table must be checked to make sure that the
- hash table was created by an object file of the same format.
+ <<_bfd_final_link>> function. In such a case the output bfd
+ xvec must be checked to make sure that the hash table was
+ created by an object file of the same format.
The <<_bfd_final_link>> routine must be prepared to handle a
hash entry without any extra information added by the
initialization function.
See <<ecoff_link_add_externals>> for an example of how to
- check the <<creator>> field before saving information (in this
+ check the output bfd before saving information (in this
case, the ECOFF external symbol debugging information) in a
hash table entry.
bfd_boolean
_bfd_link_hash_table_init
(struct bfd_link_hash_table *table,
- bfd *abfd,
+ bfd *abfd ATTRIBUTE_UNUSED,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
unsigned int entsize)
{
- table->creator = abfd->xvec;
table->undefs = NULL;
table->undefs_tail = NULL;
table->type = bfd_link_generic_hash_table;
the hash table pointing to different instances of the symbol
structure. */
-static bfd_boolean
-generic_link_read_symbols (bfd *abfd)
+bfd_boolean
+bfd_generic_link_read_symbols (bfd *abfd)
{
if (bfd_get_outsymbols (abfd) == NULL)
{
bfd_size_type symcount;
struct bfd_symbol **outsyms;
- if (! generic_link_read_symbols (abfd))
+ if (!bfd_generic_link_read_symbols (abfd))
return FALSE;
symcount = _bfd_generic_link_get_symcount (abfd);
outsyms = _bfd_generic_link_get_symbols (abfd);
*pneeded = FALSE;
- if (! generic_link_read_symbols (abfd))
+ if (!bfd_generic_link_read_symbols (abfd))
return FALSE;
pp = _bfd_generic_link_get_symbols (abfd);
struct generic_link_hash_entry *h;
struct bfd_link_hash_entry *bh;
- name = bfd_asymbol_name (p);
+ string = name = bfd_asymbol_name (p);
if (((p->flags & BSF_INDIRECT) != 0
|| bfd_is_ind_section (p->section))
&& pp + 1 < ppend)
{
/* The name of P is actually the warning string, and the
next symbol is the one to warn about. */
- string = name;
pp++;
name = bfd_asymbol_name (*pp);
}
- else
- string = NULL;
bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
hash table other than the generic hash table, so we only
do this if we are certain that the hash table is a
generic one. */
- if (info->hash->creator == abfd->xvec)
+ if (info->output_bfd->xvec == abfd->xvec)
{
if (h->sym == NULL
|| (! bfd_is_und_section (bfd_get_section (p))
asymbol **sym_ptr;
asymbol **sym_end;
- if (! generic_link_read_symbols (input_bfd))
+ if (!bfd_generic_link_read_symbols (input_bfd))
return FALSE;
/* Create a filename symbol if we are supposed to. */
this routine will be called with a hash table
other than a generic hash table, so we double
check that. */
- if (info->hash->creator == input_bfd->xvec)
+ if (info->output_bfd->xvec == input_bfd->xvec)
{
if (h->sym != NULL)
*sym_ptr = sym = h->sym;
have retrieved them by this point, but we are being called by
a specific linker, presumably because we are linking
different types of object files together. */
- if (! generic_link_read_symbols (input_bfd))
+ if (!bfd_generic_link_read_symbols (input_bfd))
return FALSE;
/* Since we have been called by a specific linker, rather than
}
}
- /* Get and relocate the section contents. */
- sec_size = (input_section->rawsize > input_section->size
- ? input_section->rawsize
- : input_section->size);
- contents = bfd_malloc (sec_size);
- if (contents == NULL && sec_size != 0)
- goto error_return;
- new_contents = (bfd_get_relocated_section_contents
- (output_bfd, info, link_order, contents, info->relocatable,
- _bfd_generic_link_get_symbols (input_bfd)));
- if (!new_contents)
- goto error_return;
+ if ((output_section->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP
+ && input_section->size != 0)
+ {
+ /* Group section contents are set by bfd_elf_set_group_contents. */
+ if (!output_bfd->output_has_begun)
+ {
+ /* FIXME: This hack ensures bfd_elf_set_group_contents is called. */
+ if (!bfd_set_section_contents (output_bfd, output_section, "", 0, 1))
+ goto error_return;
+ }
+ new_contents = output_section->contents;
+ BFD_ASSERT (new_contents != NULL);
+ BFD_ASSERT (input_section->output_offset == 0);
+ }
+ else
+ {
+ /* Get and relocate the section contents. */
+ sec_size = (input_section->rawsize > input_section->size
+ ? input_section->rawsize
+ : input_section->size);
+ contents = bfd_malloc (sec_size);
+ if (contents == NULL && sec_size != 0)
+ goto error_return;
+ new_contents = (bfd_get_relocated_section_contents
+ (output_bfd, info, link_order, contents,
+ info->relocatable,
+ _bfd_generic_link_get_symbols (input_bfd)));
+ if (!new_contents)
+ goto error_return;
+ }
/* Output the section contents. */
loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
bfd_section_already_linked
SYNOPSIS
- void bfd_section_already_linked (bfd *abfd, asection *sec);
+ void bfd_section_already_linked (bfd *abfd, asection *sec,
+ struct bfd_link_info *info);
DESCRIPTION
Check if @var{sec} has been already linked during a reloceatable
or final link.
-.#define bfd_section_already_linked(abfd, sec) \
-. BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.#define bfd_section_already_linked(abfd, sec, info) \
+. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
.
*/
TRUE, FALSE));
}
-void
+bfd_boolean
bfd_section_already_linked_table_insert
(struct bfd_section_already_linked_hash_entry *already_linked_list,
asection *sec)
/* Allocate the memory from the same obstack as the hash table is
kept in. */
l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+ if (l == NULL)
+ return FALSE;
l->sec = sec;
l->next = already_linked_list->entry;
already_linked_list->entry = l;
+ return TRUE;
}
static struct bfd_hash_entry *
struct bfd_section_already_linked_hash_entry *ret =
bfd_hash_allocate (table, sizeof *ret);
+ if (ret == NULL)
+ return NULL;
+
ret->entry = NULL;
return &ret->root;
/* This is used on non-ELF inputs. */
void
-_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec,
+ struct bfd_link_info *info)
{
flagword flags;
const char *name;
}
/* This is the first section with this name. Record it. */
- bfd_section_already_linked_table_insert (already_linked_list, sec);
+ if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
+ info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
}
/* Convert symbols in excluded output sections to use a kept section. */