/* COFF specific linker code.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
-This file is part of BFD, the Binary File Descriptor library.
+ 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
-(at your option) any later version.
+ 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 3 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.
+ 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. */
+ 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. */
/* This file contains the COFF backend linker code. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
#include "libcoff.h"
+#include "safe-ctype.h"
+
+static bfd_boolean coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info);
+static bfd_boolean coff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, bfd_boolean *pneeded);
+static bfd_boolean coff_link_add_symbols (bfd *abfd, struct bfd_link_info *info);
-static boolean coff_link_add_object_symbols
- PARAMS ((bfd *, struct bfd_link_info *));
-static boolean coff_link_check_archive_element
- PARAMS ((bfd *, struct bfd_link_info *, boolean *));
-static boolean coff_link_check_ar_symbols
- PARAMS ((bfd *, struct bfd_link_info *, boolean *));
-static boolean coff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
-static char *dores_com PARAMS ((char *, bfd *, int));
-static char *get_name PARAMS ((char *, char **));
-static int process_embedded_commands
- PARAMS ((bfd *, struct bfd_link_info *, bfd *));
-static void mark_relocs PARAMS ((struct coff_final_link_info *, bfd *));
+/* Return TRUE if SYM is a weak, external symbol. */
+#define IS_WEAK_EXTERNAL(abfd, sym) \
+ ((sym).n_sclass == C_WEAKEXT \
+ || (obj_pe (abfd) && (sym).n_sclass == C_NT_WEAK))
+
+/* Return TRUE if SYM is an external symbol. */
+#define IS_EXTERNAL(abfd, sym) \
+ ((sym).n_sclass == C_EXT || IS_WEAK_EXTERNAL (abfd, sym))
/* Define macros so that the ISFCN, et. al., macros work correctly.
These macros are defined in include/coff/internal.h in terms of
/* Create an entry in a COFF linker hash table. */
struct bfd_hash_entry *
-_bfd_coff_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+_bfd_coff_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
struct coff_link_hash_entry *ret = (struct coff_link_hash_entry *) entry;
/* Set local fields. */
ret->indx = -1;
ret->type = T_NULL;
- ret->class = C_NULL;
+ ret->symbol_class = C_NULL;
ret->numaux = 0;
ret->auxbfd = NULL;
ret->aux = NULL;
/* Initialize a COFF linker hash table. */
-boolean
-_bfd_coff_link_hash_table_init (table, abfd, newfunc)
- struct coff_link_hash_table *table;
- bfd *abfd;
- struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
- struct bfd_hash_table *,
- const char *));
+bfd_boolean
+_bfd_coff_link_hash_table_init (struct coff_link_hash_table *table,
+ bfd *abfd,
+ struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int entsize)
{
- table->stab_info = NULL;
- return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+ memset (&table->stab_info, 0, sizeof (table->stab_info));
+ return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}
/* Create a COFF linker hash table. */
struct bfd_link_hash_table *
-_bfd_coff_link_hash_table_create (abfd)
- bfd *abfd;
+_bfd_coff_link_hash_table_create (bfd *abfd)
{
struct coff_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct coff_link_hash_table);
- ret = ((struct coff_link_hash_table *)
- bfd_alloc (abfd, sizeof (struct coff_link_hash_table)));
+ ret = (struct coff_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
return NULL;
+
if (! _bfd_coff_link_hash_table_init (ret, abfd,
- _bfd_coff_link_hash_newfunc))
+ _bfd_coff_link_hash_newfunc,
+ sizeof (struct coff_link_hash_entry)))
{
- bfd_release (abfd, ret);
+ free (ret);
return (struct bfd_link_hash_table *) NULL;
}
return &ret->root;
/* Create an entry in a COFF debug merge hash table. */
struct bfd_hash_entry *
-_bfd_coff_debug_merge_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+_bfd_coff_debug_merge_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
struct coff_debug_merge_hash_entry *ret =
(struct coff_debug_merge_hash_entry *) entry;
/* Given a COFF BFD, add symbols to the global hash table as
appropriate. */
-boolean
-_bfd_coff_link_add_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+bfd_boolean
+_bfd_coff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
{
switch (bfd_get_format (abfd))
{
case bfd_object:
return coff_link_add_object_symbols (abfd, info);
case bfd_archive:
- return (_bfd_generic_link_add_archive_symbols
- (abfd, info, coff_link_check_archive_element));
+ return _bfd_generic_link_add_archive_symbols
+ (abfd, info, coff_link_check_archive_element);
default:
bfd_set_error (bfd_error_wrong_format);
- return false;
+ return FALSE;
}
}
/* Add symbols from a COFF object file. */
-static boolean
-coff_link_add_object_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+static bfd_boolean
+coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
if (! _bfd_coff_get_external_symbols (abfd))
- return false;
+ return FALSE;
if (! coff_link_add_symbols (abfd, info))
- return false;
-
- if (! info->keep_memory)
- {
- if (! _bfd_coff_free_symbols (abfd))
- return false;
- }
- return true;
-}
-
-/* Check a single archive element to see if we need to include it in
- the link. *PNEEDED is set according to whether this element is
- needed in the link or not. This is called via
- _bfd_generic_link_add_archive_symbols. */
-
-static boolean
-coff_link_check_archive_element (abfd, info, pneeded)
- bfd *abfd;
- struct bfd_link_info *info;
- boolean *pneeded;
-{
- if (! _bfd_coff_get_external_symbols (abfd))
- return false;
-
- if (! coff_link_check_ar_symbols (abfd, info, pneeded))
- return false;
+ return FALSE;
- if (*pneeded)
- {
- if (! coff_link_add_symbols (abfd, info))
- return false;
- }
-
- if (! info->keep_memory || ! *pneeded)
- {
- if (! _bfd_coff_free_symbols (abfd))
- return false;
- }
+ if (! info->keep_memory
+ && ! _bfd_coff_free_symbols (abfd))
+ return FALSE;
- return true;
+ return TRUE;
}
/* Look through the symbols to see if this object file should be
included in the link. */
-static boolean
-coff_link_check_ar_symbols (abfd, info, pneeded)
- bfd *abfd;
- struct bfd_link_info *info;
- boolean *pneeded;
+static bfd_boolean
+coff_link_check_ar_symbols (bfd *abfd,
+ struct bfd_link_info *info,
+ bfd_boolean *pneeded,
+ bfd **subsbfd)
{
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
- *pneeded = false;
+ *pneeded = FALSE;
symesz = bfd_coff_symesz (abfd);
esym = (bfd_byte *) obj_coff_external_syms (abfd);
struct internal_syment sym;
enum coff_symbol_classification classification;
- bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+ bfd_coff_swap_sym_in (abfd, esym, &sym);
classification = bfd_coff_classify_symbol (abfd, &sym);
if (classification == COFF_SYMBOL_GLOBAL
/* This symbol is externally visible, and is defined by this
object file. */
-
name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
if (name == NULL)
- return false;
- h = bfd_link_hash_lookup (info->hash, name, false, false, true);
+ return FALSE;
+ h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
+
+ /* Auto import. */
+ if (!h
+ && info->pei386_auto_import
+ && CONST_STRNEQ (name, "__imp_"))
+ h = bfd_link_hash_lookup (info->hash, name + 6, FALSE, FALSE, TRUE);
/* We are only interested in symbols that are currently
undefined. If a symbol is currently known to be common,
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_undefined)
{
- if (! (*info->callbacks->add_archive_element) (info, abfd, name))
- return false;
- *pneeded = true;
- return true;
+ if (!(*info->callbacks
+ ->add_archive_element) (info, abfd, name, subsbfd))
+ return FALSE;
+ *pneeded = TRUE;
+ return TRUE;
}
}
}
/* We do not need this object file. */
- return true;
+ return TRUE;
+}
+
+/* Check a single archive element to see if we need to include it in
+ the link. *PNEEDED is set according to whether this element is
+ needed in the link or not. This is called via
+ _bfd_generic_link_add_archive_symbols. */
+
+static bfd_boolean
+coff_link_check_archive_element (bfd *abfd,
+ struct bfd_link_info *info,
+ bfd_boolean *pneeded)
+{
+ bfd *oldbfd;
+ bfd_boolean needed;
+
+ if (!_bfd_coff_get_external_symbols (abfd))
+ return FALSE;
+
+ oldbfd = abfd;
+ if (!coff_link_check_ar_symbols (abfd, info, pneeded, &abfd))
+ return FALSE;
+
+ needed = *pneeded;
+ if (needed)
+ {
+ /* Potentially, the add_archive_element hook may have set a
+ substitute BFD for us. */
+ if (abfd != oldbfd)
+ {
+ if (!info->keep_memory
+ && !_bfd_coff_free_symbols (oldbfd))
+ return FALSE;
+ if (!_bfd_coff_get_external_symbols (abfd))
+ return FALSE;
+ }
+ if (!coff_link_add_symbols (abfd, info))
+ return FALSE;
+ }
+
+ if (!info->keep_memory || !needed)
+ {
+ if (!_bfd_coff_free_symbols (abfd))
+ return FALSE;
+ }
+ return TRUE;
}
/* Add all the symbols from an object file to the hash table. */
-static boolean
-coff_link_add_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+static bfd_boolean
+coff_link_add_symbols (bfd *abfd,
+ struct bfd_link_info *info)
{
unsigned int n_tmask = coff_data (abfd)->local_n_tmask;
unsigned int n_btshft = coff_data (abfd)->local_n_btshft;
unsigned int n_btmask = coff_data (abfd)->local_n_btmask;
- boolean keep_syms;
- boolean default_copy;
+ bfd_boolean keep_syms;
+ bfd_boolean default_copy;
bfd_size_type symcount;
struct coff_link_hash_entry **sym_hash;
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
+ bfd_size_type amt;
+
+ symcount = obj_raw_syment_count (abfd);
+
+ if (symcount == 0)
+ return TRUE; /* Nothing to do. */
/* Keep the symbols during this function, in case the linker needs
to read the generic symbols in order to report an error message. */
keep_syms = obj_coff_keep_syms (abfd);
- obj_coff_keep_syms (abfd) = true;
+ obj_coff_keep_syms (abfd) = TRUE;
if (info->keep_memory)
- default_copy = false;
+ default_copy = FALSE;
else
- default_copy = true;
-
- symcount = obj_raw_syment_count (abfd);
+ default_copy = TRUE;
/* We keep a list of the linker hash table entries that correspond
to particular symbols. */
- sym_hash = ((struct coff_link_hash_entry **)
- bfd_alloc (abfd,
- ((size_t) symcount
- * sizeof (struct coff_link_hash_entry *))));
- if (sym_hash == NULL && symcount != 0)
+ amt = symcount * sizeof (struct coff_link_hash_entry *);
+ sym_hash = (struct coff_link_hash_entry **) bfd_zalloc (abfd, amt);
+ if (sym_hash == NULL)
goto error_return;
obj_coff_sym_hashes (abfd) = sym_hash;
- memset (sym_hash, 0,
- (size_t) symcount * sizeof (struct coff_link_hash_entry *));
symesz = bfd_coff_symesz (abfd);
BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
{
struct internal_syment sym;
enum coff_symbol_classification classification;
- boolean copy;
+ bfd_boolean copy;
- bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+ bfd_coff_swap_sym_in (abfd, esym, &sym);
classification = bfd_coff_classify_symbol (abfd, &sym);
if (classification != COFF_SYMBOL_LOCAL)
flagword flags;
asection *section;
bfd_vma value;
- boolean addit;
+ bfd_boolean addit;
/* This symbol is externally visible. */
copy = default_copy;
if (sym._n._n_n._n_zeroes != 0
|| sym._n._n_n._n_offset == 0)
- copy = true;
+ copy = TRUE;
value = sym.n_value;
break;
}
- if (sym.n_sclass == C_WEAKEXT
- || (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK))
+ if (IS_WEAK_EXTERNAL (abfd, sym))
flags = BSF_WEAK;
- addit = true;
+ addit = TRUE;
/* In the PE format, section symbols actually refer to the
start of the output section. We handle them specially
if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0)
{
*sym_hash = coff_link_hash_lookup (coff_hash_table (info),
- name, false, copy, false);
+ name, FALSE, copy, FALSE);
if (*sym_hash != NULL)
{
if (((*sym_hash)->coff_link_hash_flags
("Warning: symbol `%s' is both section and non-section",
name);
- addit = false;
+ addit = FALSE;
}
}
/* The Microsoft Visual C compiler does string pooling by
hashing the constants to an internal symbol name, and
- relying on the the linker comdat support to discard
+ relying on the linker comdat support to discard
duplicate names. However, if one string is a literal and
one is a data initializer, one will end up in the .data
section and one will end up in the .rdata section. The
if (obj_pe (abfd)
&& (classification == COFF_SYMBOL_GLOBAL
|| classification == COFF_SYMBOL_PE_SECTION)
- && section->comdat != NULL
- && strncmp (name, "??_", 3) == 0
- && strcmp (name, section->comdat->name) == 0)
+ && coff_section_data (abfd, section) != NULL
+ && coff_section_data (abfd, section)->comdat != NULL
+ && CONST_STRNEQ (name, "??_")
+ && strcmp (name, coff_section_data (abfd, section)->comdat->name) == 0)
{
if (*sym_hash == NULL)
*sym_hash = coff_link_hash_lookup (coff_hash_table (info),
- name, false, copy, false);
+ name, FALSE, copy, FALSE);
if (*sym_hash != NULL
&& (*sym_hash)->root.type == bfd_link_hash_defined
- && (*sym_hash)->root.u.def.section->comdat != NULL
- && strcmp ((*sym_hash)->root.u.def.section->comdat->name,
- section->comdat->name) == 0)
- addit = false;
+ && coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat != NULL
+ && strcmp (coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat->name,
+ coff_section_data (abfd, section)->comdat->name) == 0)
+ addit = FALSE;
}
if (addit)
{
if (! (bfd_coff_link_add_one_symbol
(info, abfd, name, flags, section, value,
- (const char *) NULL, copy, false,
+ (const char *) NULL, copy, FALSE,
(struct bfd_link_hash_entry **) sym_hash)))
goto error_return;
}
(*sym_hash)->root.u.c.p->alignment_power
= bfd_coff_default_section_alignment_power (abfd);
- if (info->hash->creator->flavour == bfd_get_flavour (abfd))
+ if (bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd))
{
/* If we don't have any symbol information currently in
the hash table, or if we are looking at a symbol
definition, then update the symbol class and type in
the hash table. */
- if (((*sym_hash)->class == C_NULL
+ if (((*sym_hash)->symbol_class == C_NULL
&& (*sym_hash)->type == T_NULL)
|| sym.n_scnum != 0
|| (sym.n_value != 0
&& (*sym_hash)->root.type != bfd_link_hash_defined
&& (*sym_hash)->root.type != bfd_link_hash_defweak))
{
- (*sym_hash)->class = sym.n_sclass;
+ (*sym_hash)->symbol_class = sym.n_sclass;
if (sym.n_type != T_NULL)
{
/* We want to warn if the type changed, but not
&& (BTYPE ((*sym_hash)->type) == T_NULL
|| BTYPE (sym.n_type) == T_NULL)))
(*_bfd_error_handler)
- (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
- name, (*sym_hash)->type, sym.n_type,
- bfd_get_filename (abfd));
+ (_("Warning: type of symbol `%s' changed from %d to %d in %B"),
+ abfd, name, (*sym_hash)->type, sym.n_type);
/* We don't want to change from a meaningful
base type to a null one, but if we know
for (i = 0, eaux = esym + symesz, iaux = alloc;
i < sym.n_numaux;
i++, eaux += symesz, iaux++)
- bfd_coff_swap_aux_in (abfd, (PTR) eaux, sym.n_type,
- sym.n_sclass, i, sym.n_numaux,
- (PTR) iaux);
+ bfd_coff_swap_aux_in (abfd, eaux, sym.n_type,
+ sym.n_sclass, (int) i,
+ sym.n_numaux, iaux);
(*sym_hash)->aux = alloc;
}
}
FIXME: This is not at all the right place to do this.
For example, it won't help objdump. This needs to be
done when we swap in the section header. */
-
BFD_ASSERT ((*sym_hash)->numaux == 1);
- if (section->_raw_size == 0)
- section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen;
+ if (section->size == 0)
+ section->size = (*sym_hash)->aux[0].x_scn.x_scnlen;
/* FIXME: We could test whether the section sizes
matches the size in the aux entry, but apparently
sym_hash += sym.n_numaux + 1;
}
- /* If this is a non-traditional, non-relocateable link, try to
+ /* If this is a non-traditional, non-relocatable link, try to
optimize the handling of any .stab/.stabstr sections. */
- if (! info->relocateable
+ if (! info->relocatable
&& ! info->traditional_format
- && info->hash->creator->flavour == bfd_get_flavour (abfd)
+ && bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd)
&& (info->strip != strip_all && info->strip != strip_debugger))
{
- asection *stab, *stabstr;
+ asection *stabstr;
+
+ stabstr = bfd_get_section_by_name (abfd, ".stabstr");
- stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab != NULL)
+ if (stabstr != NULL)
{
- stabstr = bfd_get_section_by_name (abfd, ".stabstr");
+ bfd_size_type string_offset = 0;
+ asection *stab;
- if (stabstr != NULL)
+ for (stab = abfd->sections; stab; stab = stab->next)
+ if (CONST_STRNEQ (stab->name, ".stab")
+ && (!stab->name[5]
+ || (stab->name[5] == '.' && ISDIGIT (stab->name[6]))))
{
struct coff_link_hash_table *table;
- struct coff_section_tdata *secdata;
+ struct coff_section_tdata *secdata
+ = coff_section_data (abfd, stab);
- secdata = coff_section_data (abfd, stab);
if (secdata == NULL)
{
- stab->used_by_bfd =
- (PTR) bfd_zalloc (abfd,
- sizeof (struct coff_section_tdata));
+ amt = sizeof (struct coff_section_tdata);
+ stab->used_by_bfd = bfd_zalloc (abfd, amt);
if (stab->used_by_bfd == NULL)
goto error_return;
secdata = coff_section_data (abfd, stab);
if (! _bfd_link_section_stabs (abfd, &table->stab_info,
stab, stabstr,
- &secdata->stab_info))
+ &secdata->stab_info,
+ &string_offset))
goto error_return;
}
}
obj_coff_keep_syms (abfd) = keep_syms;
- return true;
+ return TRUE;
error_return:
obj_coff_keep_syms (abfd) = keep_syms;
- return false;
+ return FALSE;
}
\f
/* Do the final link step. */
-boolean
-_bfd_coff_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+bfd_boolean
+_bfd_coff_final_link (bfd *abfd,
+ struct bfd_link_info *info)
{
bfd_size_type symesz;
- struct coff_final_link_info finfo;
- boolean debug_merge_allocated;
- boolean long_section_names;
+ struct coff_final_link_info flaginfo;
+ bfd_boolean debug_merge_allocated;
+ bfd_boolean long_section_names;
asection *o;
struct bfd_link_order *p;
- size_t max_sym_count;
- size_t max_lineno_count;
- size_t max_reloc_count;
- size_t max_output_reloc_count;
- size_t max_contents_size;
+ bfd_size_type max_sym_count;
+ bfd_size_type max_lineno_count;
+ bfd_size_type max_reloc_count;
+ bfd_size_type max_output_reloc_count;
+ bfd_size_type max_contents_size;
file_ptr rel_filepos;
unsigned int relsz;
file_ptr line_filepos;
bfd *sub;
bfd_byte *external_relocs = NULL;
char strbuf[STRING_SIZE_SIZE];
+ bfd_size_type amt;
symesz = bfd_coff_symesz (abfd);
- finfo.info = info;
- finfo.output_bfd = abfd;
- finfo.strtab = NULL;
- finfo.section_info = NULL;
- finfo.last_file_index = -1;
- finfo.last_bf_index = -1;
- finfo.internal_syms = NULL;
- finfo.sec_ptrs = NULL;
- finfo.sym_indices = NULL;
- finfo.outsyms = NULL;
- finfo.linenos = NULL;
- finfo.contents = NULL;
- finfo.external_relocs = NULL;
- finfo.internal_relocs = NULL;
- finfo.global_to_static = false;
- debug_merge_allocated = false;
+ flaginfo.info = info;
+ flaginfo.output_bfd = abfd;
+ flaginfo.strtab = NULL;
+ flaginfo.section_info = NULL;
+ flaginfo.last_file_index = -1;
+ flaginfo.last_bf_index = -1;
+ flaginfo.internal_syms = NULL;
+ flaginfo.sec_ptrs = NULL;
+ flaginfo.sym_indices = NULL;
+ flaginfo.outsyms = NULL;
+ flaginfo.linenos = NULL;
+ flaginfo.contents = NULL;
+ flaginfo.external_relocs = NULL;
+ flaginfo.internal_relocs = NULL;
+ flaginfo.global_to_static = FALSE;
+ debug_merge_allocated = FALSE;
coff_data (abfd)->link_info = info;
- finfo.strtab = _bfd_stringtab_init ();
- if (finfo.strtab == NULL)
+ flaginfo.strtab = _bfd_stringtab_init ();
+ if (flaginfo.strtab == NULL)
goto error_return;
- if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
+ if (! coff_debug_merge_hash_table_init (&flaginfo.debug_merge))
goto error_return;
- debug_merge_allocated = true;
+ debug_merge_allocated = TRUE;
/* Compute the file positions for all the sections. */
if (! abfd->output_has_begun)
max_lineno_count = 0;
max_reloc_count = 0;
- long_section_names = false;
+ long_section_names = FALSE;
for (o = abfd->sections; o != NULL; o = o->next)
{
o->reloc_count = 0;
o->lineno_count = 0;
- for (p = o->link_order_head; p != NULL; p = p->next)
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
{
if (p->type == bfd_indirect_link_order)
{
link. This will normally be every section. We need
to do this so that we can identify any sections which
the linker has decided to not include. */
- sec->linker_mark = true;
+ sec->linker_mark = TRUE;
if (info->strip == strip_none
|| info->strip == strip_some)
o->lineno_count += sec->lineno_count;
- if (info->relocateable)
+ if (info->relocatable)
o->reloc_count += sec->reloc_count;
- if (sec->_raw_size > max_contents_size)
- max_contents_size = sec->_raw_size;
+ if (sec->rawsize > max_contents_size)
+ max_contents_size = sec->rawsize;
+ if (sec->size > max_contents_size)
+ max_contents_size = sec->size;
if (sec->lineno_count > max_lineno_count)
max_lineno_count = sec->lineno_count;
if (sec->reloc_count > max_reloc_count)
max_reloc_count = sec->reloc_count;
}
- else if (info->relocateable
+ else if (info->relocatable
&& (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order))
++o->reloc_count;
o->flags |= SEC_RELOC;
o->rel_filepos = rel_filepos;
rel_filepos += o->reloc_count * relsz;
+ /* In PE COFF, if there are at least 0xffff relocations an
+ extra relocation will be written out to encode the count. */
+ if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+ rel_filepos += relsz;
}
if (bfd_coff_long_section_names (abfd)
table. This must correspond to the code in
coff_write_object_contents which puts the string index
into the s_name field of the section header. That is why
- we pass hash as false. */
- if (_bfd_stringtab_add (finfo.strtab, o->name, false, false)
+ we pass hash as FALSE. */
+ if (_bfd_stringtab_add (flaginfo.strtab, o->name, FALSE, FALSE)
== (bfd_size_type) -1)
goto error_return;
- long_section_names = true;
+ long_section_names = TRUE;
}
}
- /* If doing a relocateable link, allocate space for the pointers we
+ /* If doing a relocatable link, allocate space for the pointers we
need to keep. */
- if (info->relocateable)
+ if (info->relocatable)
{
unsigned int i;
/* We use section_count + 1, rather than section_count, because
the target_index fields are 1 based. */
- finfo.section_info =
- ((struct coff_link_section_info *)
- bfd_malloc ((abfd->section_count + 1)
- * sizeof (struct coff_link_section_info)));
- if (finfo.section_info == NULL)
+ amt = abfd->section_count + 1;
+ amt *= sizeof (struct coff_link_section_info);
+ flaginfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);
+ if (flaginfo.section_info == NULL)
goto error_return;
for (i = 0; i <= abfd->section_count; i++)
{
- finfo.section_info[i].relocs = NULL;
- finfo.section_info[i].rel_hashes = NULL;
+ flaginfo.section_info[i].relocs = NULL;
+ flaginfo.section_info[i].rel_hashes = NULL;
}
}
Because of this problem, we also keep the relocs in
memory until the end of the link. This wastes memory,
- but only when doing a relocateable link, which is not the
+ but only when doing a relocatable link, which is not the
common case. */
- BFD_ASSERT (info->relocateable);
- finfo.section_info[o->target_index].relocs =
- ((struct internal_reloc *)
- bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));
- finfo.section_info[o->target_index].rel_hashes =
- ((struct coff_link_hash_entry **)
- bfd_malloc (o->reloc_count
- * sizeof (struct coff_link_hash_entry *)));
- if (finfo.section_info[o->target_index].relocs == NULL
- || finfo.section_info[o->target_index].rel_hashes == NULL)
+ BFD_ASSERT (info->relocatable);
+ amt = o->reloc_count;
+ amt *= sizeof (struct internal_reloc);
+ flaginfo.section_info[o->target_index].relocs =
+ (struct internal_reloc *) bfd_malloc (amt);
+ amt = o->reloc_count;
+ amt *= sizeof (struct coff_link_hash_entry *);
+ flaginfo.section_info[o->target_index].rel_hashes =
+ (struct coff_link_hash_entry **) bfd_malloc (amt);
+ if (flaginfo.section_info[o->target_index].relocs == NULL
+ || flaginfo.section_info[o->target_index].rel_hashes == NULL)
goto error_return;
if (o->reloc_count > max_output_reloc_count)
{
size_t sz;
- sub->output_has_begun = false;
- sz = obj_raw_syment_count (sub);
+ sub->output_has_begun = FALSE;
+ sz = bfd_family_coff (sub) ? obj_raw_syment_count (sub) : 2;
if (sz > max_sym_count)
max_sym_count = sz;
}
/* Allocate some buffers used while linking. */
- finfo.internal_syms = ((struct internal_syment *)
- bfd_malloc (max_sym_count
- * sizeof (struct internal_syment)));
- finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count
- * sizeof (asection *));
- finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
- finfo.outsyms = ((bfd_byte *)
- bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
- finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count
- * bfd_coff_linesz (abfd));
- finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
- finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
- if (! info->relocateable)
- finfo.internal_relocs = ((struct internal_reloc *)
- bfd_malloc (max_reloc_count
- * sizeof (struct internal_reloc)));
- if ((finfo.internal_syms == NULL && max_sym_count > 0)
- || (finfo.sec_ptrs == NULL && max_sym_count > 0)
- || (finfo.sym_indices == NULL && max_sym_count > 0)
- || finfo.outsyms == NULL
- || (finfo.linenos == NULL && max_lineno_count > 0)
- || (finfo.contents == NULL && max_contents_size > 0)
- || (finfo.external_relocs == NULL && max_reloc_count > 0)
- || (! info->relocateable
- && finfo.internal_relocs == NULL
+ amt = max_sym_count * sizeof (struct internal_syment);
+ flaginfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
+ amt = max_sym_count * sizeof (asection *);
+ flaginfo.sec_ptrs = (asection **) bfd_malloc (amt);
+ amt = max_sym_count * sizeof (long);
+ flaginfo.sym_indices = (long int *) bfd_malloc (amt);
+ flaginfo.outsyms = (bfd_byte *) bfd_malloc ((max_sym_count + 1) * symesz);
+ amt = max_lineno_count * bfd_coff_linesz (abfd);
+ flaginfo.linenos = (bfd_byte *) bfd_malloc (amt);
+ flaginfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ amt = max_reloc_count * relsz;
+ flaginfo.external_relocs = (bfd_byte *) bfd_malloc (amt);
+ if (! info->relocatable)
+ {
+ amt = max_reloc_count * sizeof (struct internal_reloc);
+ flaginfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
+ }
+ if ((flaginfo.internal_syms == NULL && max_sym_count > 0)
+ || (flaginfo.sec_ptrs == NULL && max_sym_count > 0)
+ || (flaginfo.sym_indices == NULL && max_sym_count > 0)
+ || flaginfo.outsyms == NULL
+ || (flaginfo.linenos == NULL && max_lineno_count > 0)
+ || (flaginfo.contents == NULL && max_contents_size > 0)
+ || (flaginfo.external_relocs == NULL && max_reloc_count > 0)
+ || (! info->relocatable
+ && flaginfo.internal_relocs == NULL
&& max_reloc_count > 0))
goto error_return;
for (o = abfd->sections; o != NULL; o = o->next)
{
- for (p = o->link_order_head; p != NULL; p = p->next)
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
{
if (p->type == bfd_indirect_link_order
- && (bfd_get_flavour (p->u.indirect.section->owner)
- == bfd_target_coff_flavour))
+ && bfd_family_coff (p->u.indirect.section->owner))
{
sub = p->u.indirect.section->owner;
- if (! bfd_coff_link_output_has_begun (sub, & finfo))
+ if (! bfd_coff_link_output_has_begun (sub, & flaginfo))
{
- if (! _bfd_coff_link_input_bfd (&finfo, sub))
+ if (! _bfd_coff_link_input_bfd (&flaginfo, sub))
goto error_return;
- sub->output_has_begun = true;
+ sub->output_has_begun = TRUE;
}
}
else if (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order)
{
- if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
+ if (! _bfd_coff_reloc_link_order (abfd, &flaginfo, o, p))
goto error_return;
}
else
}
}
- if (! bfd_coff_final_link_postscript (abfd, & finfo))
+ if (flaginfo.info->strip != strip_all && flaginfo.info->discard != discard_all)
+ {
+ /* Add local symbols from foreign inputs. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ unsigned int i;
+
+ if (bfd_family_coff (sub) || ! bfd_get_outsymbols (sub))
+ continue;
+ for (i = 0; i < bfd_get_symcount (sub); ++i)
+ {
+ asymbol *sym = bfd_get_outsymbols (sub) [i];
+ file_ptr pos;
+ struct internal_syment isym;
+ bfd_size_type string_size = 0;
+ bfd_vma written = 0;
+ bfd_boolean rewrite = FALSE;
+
+ if (! (sym->flags & BSF_LOCAL)
+ || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
+ | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC
+ | BSF_SYNTHETIC))
+ || ((sym->flags & BSF_DEBUGGING)
+ && ! (sym->flags & BSF_FILE)))
+ continue;
+
+ /* See if we are discarding symbols with this name. */
+ if ((flaginfo.info->strip == strip_some
+ && (bfd_hash_lookup (flaginfo.info->keep_hash,
+ bfd_asymbol_name(sym), FALSE, FALSE)
+ == NULL))
+ || (((flaginfo.info->discard == discard_sec_merge
+ && (bfd_get_section (sym)->flags & SEC_MERGE)
+ && ! flaginfo.info->relocatable)
+ || flaginfo.info->discard == discard_l)
+ && bfd_is_local_label_name (sub, bfd_asymbol_name(sym))))
+ continue;
+
+ pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd)
+ * symesz;
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+ goto error_return;
+ if (! coff_write_alien_symbol(abfd, sym, &isym, &written,
+ &string_size, NULL, NULL))
+ goto error_return;
+
+ if (string_size)
+ {
+ bfd_boolean hash = ! (abfd->flags & BFD_TRADITIONAL_FORMAT);
+ bfd_size_type indx;
+
+ indx = _bfd_stringtab_add (flaginfo.strtab,
+ bfd_asymbol_name (sym), hash,
+ FALSE);
+ if (indx == (bfd_size_type) -1)
+ goto error_return;
+ isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+ rewrite = TRUE;
+ }
+
+ if (isym.n_sclass == C_FILE)
+ {
+ if (flaginfo.last_file_index != -1)
+ {
+ flaginfo.last_file.n_value = obj_raw_syment_count (abfd);
+ bfd_coff_swap_sym_out (abfd, &flaginfo.last_file,
+ flaginfo.outsyms);
+ pos = obj_sym_filepos (abfd) + flaginfo.last_file_index
+ * symesz;
+ rewrite = TRUE;
+ }
+ flaginfo.last_file_index = obj_raw_syment_count (abfd);
+ flaginfo.last_file = isym;
+ }
+
+ if (rewrite
+ && (bfd_seek (abfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (flaginfo.outsyms, symesz, abfd) != symesz))
+ goto error_return;
+
+ obj_raw_syment_count (abfd) += written;
+ }
+ }
+ }
+
+ if (! bfd_coff_final_link_postscript (abfd, & flaginfo))
goto error_return;
-
+
/* Free up the buffers used by _bfd_coff_link_input_bfd. */
- coff_debug_merge_hash_table_free (&finfo.debug_merge);
- debug_merge_allocated = false;
+ coff_debug_merge_hash_table_free (&flaginfo.debug_merge);
+ debug_merge_allocated = FALSE;
- if (finfo.internal_syms != NULL)
+ if (flaginfo.internal_syms != NULL)
{
- free (finfo.internal_syms);
- finfo.internal_syms = NULL;
+ free (flaginfo.internal_syms);
+ flaginfo.internal_syms = NULL;
}
- if (finfo.sec_ptrs != NULL)
+ if (flaginfo.sec_ptrs != NULL)
{
- free (finfo.sec_ptrs);
- finfo.sec_ptrs = NULL;
+ free (flaginfo.sec_ptrs);
+ flaginfo.sec_ptrs = NULL;
}
- if (finfo.sym_indices != NULL)
+ if (flaginfo.sym_indices != NULL)
{
- free (finfo.sym_indices);
- finfo.sym_indices = NULL;
+ free (flaginfo.sym_indices);
+ flaginfo.sym_indices = NULL;
}
- if (finfo.linenos != NULL)
+ if (flaginfo.linenos != NULL)
{
- free (finfo.linenos);
- finfo.linenos = NULL;
+ free (flaginfo.linenos);
+ flaginfo.linenos = NULL;
}
- if (finfo.contents != NULL)
+ if (flaginfo.contents != NULL)
{
- free (finfo.contents);
- finfo.contents = NULL;
+ free (flaginfo.contents);
+ flaginfo.contents = NULL;
}
- if (finfo.external_relocs != NULL)
+ if (flaginfo.external_relocs != NULL)
{
- free (finfo.external_relocs);
- finfo.external_relocs = NULL;
+ free (flaginfo.external_relocs);
+ flaginfo.external_relocs = NULL;
}
- if (finfo.internal_relocs != NULL)
+ if (flaginfo.internal_relocs != NULL)
{
- free (finfo.internal_relocs);
- finfo.internal_relocs = NULL;
+ free (flaginfo.internal_relocs);
+ flaginfo.internal_relocs = NULL;
}
/* The value of the last C_FILE symbol is supposed to be the symbol
index of the first external symbol. Write it out again if
necessary. */
- if (finfo.last_file_index != -1
- && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
+ if (flaginfo.last_file_index != -1
+ && (unsigned int) flaginfo.last_file.n_value != obj_raw_syment_count (abfd))
{
- finfo.last_file.n_value = obj_raw_syment_count (abfd);
- bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
- (PTR) finfo.outsyms);
- if (bfd_seek (abfd,
- (obj_sym_filepos (abfd)
- + finfo.last_file_index * symesz),
- SEEK_SET) != 0
- || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
- return false;
+ file_ptr pos;
+
+ flaginfo.last_file.n_value = obj_raw_syment_count (abfd);
+ bfd_coff_swap_sym_out (abfd, &flaginfo.last_file,
+ flaginfo.outsyms);
+
+ pos = obj_sym_filepos (abfd) + flaginfo.last_file_index * symesz;
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (flaginfo.outsyms, symesz, abfd) != symesz)
+ return FALSE;
}
/* If doing task linking (ld --task-link) then make a pass through the
global symbols, writing out any that are defined, and making them
- static. */
+ static. */
if (info->task_link)
{
- finfo.failed = false;
- coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_task_globals,
- (PTR) &finfo);
- if (finfo.failed)
+ flaginfo.failed = FALSE;
+ coff_link_hash_traverse (coff_hash_table (info),
+ _bfd_coff_write_task_globals, &flaginfo);
+ if (flaginfo.failed)
goto error_return;
}
/* Write out the global symbols. */
- finfo.failed = false;
- coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
- (PTR) &finfo);
- if (finfo.failed)
+ flaginfo.failed = FALSE;
+ bfd_hash_traverse (&info->hash->table, _bfd_coff_write_global_sym, &flaginfo);
+ if (flaginfo.failed)
goto error_return;
/* The outsyms buffer is used by _bfd_coff_write_global_sym. */
- if (finfo.outsyms != NULL)
+ if (flaginfo.outsyms != NULL)
{
- free (finfo.outsyms);
- finfo.outsyms = NULL;
+ free (flaginfo.outsyms);
+ flaginfo.outsyms = NULL;
}
- if (info->relocateable && max_output_reloc_count > 0)
+ if (info->relocatable && max_output_reloc_count > 0)
{
/* Now that we have written out all the global symbols, we know
the symbol indices to use for relocs against them, and we can
finally write out the relocs. */
- external_relocs = ((bfd_byte *)
- bfd_malloc (max_output_reloc_count * relsz));
+ amt = max_output_reloc_count * relsz;
+ external_relocs = (bfd_byte *) bfd_malloc (amt);
if (external_relocs == NULL)
goto error_return;
if (o->reloc_count == 0)
continue;
- irel = finfo.section_info[o->target_index].relocs;
+ irel = flaginfo.section_info[o->target_index].relocs;
irelend = irel + o->reloc_count;
- rel_hash = finfo.section_info[o->target_index].rel_hashes;
+ rel_hash = flaginfo.section_info[o->target_index].rel_hashes;
erel = external_relocs;
for (; irel < irelend; irel++, rel_hash++, erel += relsz)
{
BFD_ASSERT ((*rel_hash)->indx >= 0);
irel->r_symndx = (*rel_hash)->indx;
}
- bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+ bfd_coff_swap_reloc_out (abfd, irel, erel);
}
- if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
- || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
- abfd) != relsz * o->reloc_count)
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0)
+ goto error_return;
+ if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+ {
+ /* In PE COFF, write the count of relocs as the first
+ reloc. The header overflow bit will be set
+ elsewhere. */
+ struct internal_reloc incount;
+ bfd_byte *excount = (bfd_byte *)bfd_malloc (relsz);
+
+ memset (&incount, 0, sizeof (incount));
+ incount.r_vaddr = o->reloc_count + 1;
+ bfd_coff_swap_reloc_out (abfd, &incount, excount);
+ if (bfd_bwrite (excount, relsz, abfd) != relsz)
+ /* We'll leak, but it's an error anyway. */
+ goto error_return;
+ free (excount);
+ }
+ if (bfd_bwrite (external_relocs,
+ (bfd_size_type) relsz * o->reloc_count, abfd)
+ != (bfd_size_type) relsz * o->reloc_count)
goto error_return;
}
}
/* Free up the section information. */
- if (finfo.section_info != NULL)
+ if (flaginfo.section_info != NULL)
{
unsigned int i;
for (i = 0; i < abfd->section_count; i++)
{
- if (finfo.section_info[i].relocs != NULL)
- free (finfo.section_info[i].relocs);
- if (finfo.section_info[i].rel_hashes != NULL)
- free (finfo.section_info[i].rel_hashes);
+ if (flaginfo.section_info[i].relocs != NULL)
+ free (flaginfo.section_info[i].relocs);
+ if (flaginfo.section_info[i].rel_hashes != NULL)
+ free (flaginfo.section_info[i].rel_hashes);
}
- free (finfo.section_info);
- finfo.section_info = NULL;
+ free (flaginfo.section_info);
+ flaginfo.section_info = NULL;
}
/* If we have optimized stabs strings, output them. */
- if (coff_hash_table (info)->stab_info != NULL)
+ if (coff_hash_table (info)->stab_info.stabstr != NULL)
{
if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
- return false;
+ return FALSE;
}
/* Write out the string table. */
if (obj_raw_syment_count (abfd) != 0 || long_section_names)
{
- if (bfd_seek (abfd,
- (obj_sym_filepos (abfd)
- + obj_raw_syment_count (abfd) * symesz),
- SEEK_SET) != 0)
- return false;
+ file_ptr pos;
+
+ pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+ return FALSE;
#if STRING_SIZE_SIZE == 4
- bfd_h_put_32 (abfd,
- _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
- (bfd_byte *) strbuf);
+ H_PUT_32 (abfd,
+ _bfd_stringtab_size (flaginfo.strtab) + STRING_SIZE_SIZE,
+ strbuf);
#else
- #error Change bfd_h_put_32
+ #error Change H_PUT_32 above
#endif
- if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE)
- return false;
+ if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd)
+ != STRING_SIZE_SIZE)
+ return FALSE;
- if (! _bfd_stringtab_emit (abfd, finfo.strtab))
- return false;
+ if (! _bfd_stringtab_emit (abfd, flaginfo.strtab))
+ return FALSE;
+
+ obj_coff_strings_written (abfd) = TRUE;
}
- _bfd_stringtab_free (finfo.strtab);
+ _bfd_stringtab_free (flaginfo.strtab);
/* Setting bfd_get_symcount to 0 will cause write_object_contents to
not try to write out the symbols. */
bfd_get_symcount (abfd) = 0;
- return true;
+ return TRUE;
error_return:
if (debug_merge_allocated)
- coff_debug_merge_hash_table_free (&finfo.debug_merge);
- if (finfo.strtab != NULL)
- _bfd_stringtab_free (finfo.strtab);
- if (finfo.section_info != NULL)
+ coff_debug_merge_hash_table_free (&flaginfo.debug_merge);
+ if (flaginfo.strtab != NULL)
+ _bfd_stringtab_free (flaginfo.strtab);
+ if (flaginfo.section_info != NULL)
{
unsigned int i;
for (i = 0; i < abfd->section_count; i++)
{
- if (finfo.section_info[i].relocs != NULL)
- free (finfo.section_info[i].relocs);
- if (finfo.section_info[i].rel_hashes != NULL)
- free (finfo.section_info[i].rel_hashes);
+ if (flaginfo.section_info[i].relocs != NULL)
+ free (flaginfo.section_info[i].relocs);
+ if (flaginfo.section_info[i].rel_hashes != NULL)
+ free (flaginfo.section_info[i].rel_hashes);
}
- free (finfo.section_info);
+ free (flaginfo.section_info);
}
- if (finfo.internal_syms != NULL)
- free (finfo.internal_syms);
- if (finfo.sec_ptrs != NULL)
- free (finfo.sec_ptrs);
- if (finfo.sym_indices != NULL)
- free (finfo.sym_indices);
- if (finfo.outsyms != NULL)
- free (finfo.outsyms);
- if (finfo.linenos != NULL)
- free (finfo.linenos);
- if (finfo.contents != NULL)
- free (finfo.contents);
- if (finfo.external_relocs != NULL)
- free (finfo.external_relocs);
- if (finfo.internal_relocs != NULL)
- free (finfo.internal_relocs);
+ if (flaginfo.internal_syms != NULL)
+ free (flaginfo.internal_syms);
+ if (flaginfo.sec_ptrs != NULL)
+ free (flaginfo.sec_ptrs);
+ if (flaginfo.sym_indices != NULL)
+ free (flaginfo.sym_indices);
+ if (flaginfo.outsyms != NULL)
+ free (flaginfo.outsyms);
+ if (flaginfo.linenos != NULL)
+ free (flaginfo.linenos);
+ if (flaginfo.contents != NULL)
+ free (flaginfo.contents);
+ if (flaginfo.external_relocs != NULL)
+ free (flaginfo.external_relocs);
+ if (flaginfo.internal_relocs != NULL)
+ free (flaginfo.internal_relocs);
if (external_relocs != NULL)
free (external_relocs);
- return false;
+ return FALSE;
}
-/* parse out a -heap <reserved>,<commit> line */
+/* Parse out a -heap <reserved>,<commit> line. */
static char *
-dores_com (ptr, output_bfd, heap)
- char *ptr;
- bfd *output_bfd;
- int heap;
+dores_com (char *ptr, bfd *output_bfd, int heap)
{
- if (coff_data(output_bfd)->pe)
+ if (coff_data(output_bfd)->pe)
{
int val = strtoul (ptr, &ptr, 0);
+
if (heap)
- pe_data(output_bfd)->pe_opthdr.SizeOfHeapReserve =val;
+ pe_data(output_bfd)->pe_opthdr.SizeOfHeapReserve = val;
else
- pe_data(output_bfd)->pe_opthdr.SizeOfStackReserve =val;
+ pe_data(output_bfd)->pe_opthdr.SizeOfStackReserve = val;
- if (ptr[0] == ',')
+ if (ptr[0] == ',')
{
- int val = strtoul (ptr+1, &ptr, 0);
+ val = strtoul (ptr+1, &ptr, 0);
if (heap)
- pe_data(output_bfd)->pe_opthdr.SizeOfHeapCommit =val;
+ pe_data(output_bfd)->pe_opthdr.SizeOfHeapCommit = val;
else
- pe_data(output_bfd)->pe_opthdr.SizeOfStackCommit =val;
+ pe_data(output_bfd)->pe_opthdr.SizeOfStackCommit = val;
}
}
return ptr;
}
-static char *get_name(ptr, dst)
-char *ptr;
-char **dst;
+static char *
+get_name (char *ptr, char **dst)
{
while (*ptr == ' ')
ptr++;
return ptr+1;
}
-/* Process any magic embedded commands in a section called .drectve */
-
+/* Process any magic embedded commands in a section called .drectve. */
+
static int
-process_embedded_commands (output_bfd, info, abfd)
- bfd *output_bfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- bfd *abfd;
+process_embedded_commands (bfd *output_bfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ bfd *abfd)
{
asection *sec = bfd_get_section_by_name (abfd, ".drectve");
char *s;
char *e;
- char *copy;
- if (!sec)
+ bfd_byte *copy;
+
+ if (!sec)
return 1;
-
- copy = bfd_malloc ((size_t) sec->_raw_size);
- if (!copy)
- return 0;
- if (! bfd_get_section_contents(abfd, sec, copy, 0, sec->_raw_size))
+
+ if (!bfd_malloc_and_get_section (abfd, sec, ©))
{
- free (copy);
+ if (copy != NULL)
+ free (copy);
return 0;
}
- e = copy + sec->_raw_size;
- for (s = copy; s < e ; )
+ e = (char *) copy + sec->size;
+
+ for (s = (char *) copy; s < e ; )
{
- if (s[0]!= '-') {
- s++;
- continue;
- }
- if (strncmp (s,"-attr", 5) == 0)
+ if (s[0] != '-')
+ {
+ s++;
+ continue;
+ }
+ if (CONST_STRNEQ (s, "-attr"))
{
char *name;
char *attribs;
asection *asec;
-
int loop = 1;
int had_write = 0;
- int had_read = 0;
int had_exec= 0;
- int had_shared= 0;
+
s += 5;
- s = get_name(s, &name);
- s = get_name(s, &attribs);
- while (loop) {
- switch (*attribs++)
- {
- case 'W':
- had_write = 1;
- break;
- case 'R':
- had_read = 1;
- break;
- case 'S':
- had_shared = 1;
- break;
- case 'X':
- had_exec = 1;
- break;
- default:
- loop = 0;
- }
- }
+ s = get_name (s, &name);
+ s = get_name (s, &attribs);
+
+ while (loop)
+ {
+ switch (*attribs++)
+ {
+ case 'W':
+ had_write = 1;
+ break;
+ case 'R':
+ break;
+ case 'S':
+ break;
+ case 'X':
+ had_exec = 1;
+ break;
+ default:
+ loop = 0;
+ }
+ }
asec = bfd_get_section_by_name (abfd, name);
- if (asec) {
- if (had_exec)
- asec->flags |= SEC_CODE;
- if (!had_write)
- asec->flags |= SEC_READONLY;
- }
- }
- else if (strncmp (s,"-heap", 5) == 0)
- {
- s = dores_com (s+5, output_bfd, 1);
+ if (asec)
+ {
+ if (had_exec)
+ asec->flags |= SEC_CODE;
+ if (!had_write)
+ asec->flags |= SEC_READONLY;
+ }
}
- else if (strncmp (s,"-stack", 6) == 0)
+ else if (CONST_STRNEQ (s, "-heap"))
+ s = dores_com (s + 5, output_bfd, 1);
+
+ else if (CONST_STRNEQ (s, "-stack"))
+ s = dores_com (s + 6, output_bfd, 0);
+
+ /* GNU extension for aligned commons. */
+ else if (CONST_STRNEQ (s, "-aligncomm:"))
{
- s = dores_com (s+6, output_bfd, 0);
+ /* Common symbols must be aligned on reading, as it
+ is too late to do anything here, after they have
+ already been allocated, so just skip the directive. */
+ s += 11;
}
- else
+
+ else
s++;
}
free (copy);
/* Place a marker against all symbols which are used by relocations.
This marker can be picked up by the 'do we skip this symbol ?'
loop in _bfd_coff_link_input_bfd() and used to prevent skipping
- that symbol.
- */
+ that symbol. */
static void
-mark_relocs (finfo, input_bfd)
- struct coff_final_link_info * finfo;
- bfd * input_bfd;
+mark_relocs (struct coff_final_link_info *flaginfo, bfd *input_bfd)
{
asection * a;
if ((bfd_get_file_flags (input_bfd) & HAS_SYMS) == 0)
return;
-
+
for (a = input_bfd->sections; a != (asection *) NULL; a = a->next)
{
struct internal_reloc * internal_relocs;
struct internal_reloc * irel;
struct internal_reloc * irelend;
-
- if ((a->flags & SEC_RELOC) == 0 || a->reloc_count < 1)
+ if ((a->flags & SEC_RELOC) == 0 || a->reloc_count < 1
+ || a->linker_mark == 0)
+ continue;
+ /* Don't mark relocs in excluded sections. */
+ if (a->output_section == bfd_abs_section_ptr)
continue;
/* Read in the relocs. */
internal_relocs = _bfd_coff_read_internal_relocs
- (input_bfd, a, false,
- finfo->external_relocs,
- finfo->info->relocateable,
- (finfo->info->relocateable
- ? (finfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
- : finfo->internal_relocs)
+ (input_bfd, a, FALSE,
+ flaginfo->external_relocs,
+ flaginfo->info->relocatable,
+ (flaginfo->info->relocatable
+ ? (flaginfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
+ : flaginfo->internal_relocs)
);
-
+
if (internal_relocs == NULL)
continue;
/* Place a mark in the sym_indices array (whose entries have
been initialised to 0) for all of the symbols that are used
in the relocation table. This will then be picked up in the
- skip/don't pass */
-
+ skip/don't-skip pass. */
for (; irel < irelend; irel++)
- {
- finfo->sym_indices[ irel->r_symndx ] = -1;
- }
+ flaginfo->sym_indices[ irel->r_symndx ] = -1;
}
}
/* Link an input file into the linker output file. This function
handles all the sections and relocations of the input file at once. */
-boolean
-_bfd_coff_link_input_bfd (finfo, input_bfd)
- struct coff_final_link_info *finfo;
- bfd *input_bfd;
+bfd_boolean
+_bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
{
unsigned int n_tmask = coff_data (input_bfd)->local_n_tmask;
unsigned int n_btshft = coff_data (input_bfd)->local_n_btshft;
-#if 0
- unsigned int n_btmask = coff_data (input_bfd)->local_n_btmask;
-#endif
- boolean (*adjust_symndx) PARAMS ((bfd *, struct bfd_link_info *, bfd *,
- asection *, struct internal_reloc *,
- boolean *));
+ bfd_boolean (*adjust_symndx)
+ (bfd *, struct bfd_link_info *, bfd *, asection *,
+ struct internal_reloc *, bfd_boolean *);
bfd *output_bfd;
const char *strings;
bfd_size_type syment_base;
- boolean copy, hash;
+ bfd_boolean copy, hash;
bfd_size_type isymesz;
bfd_size_type osymesz;
bfd_size_type linesz;
/* Move all the symbols to the output file. */
- output_bfd = finfo->output_bfd;
+ output_bfd = flaginfo->output_bfd;
strings = NULL;
syment_base = obj_raw_syment_count (output_bfd);
isymesz = bfd_coff_symesz (input_bfd);
linesz = bfd_coff_linesz (input_bfd);
BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
- copy = false;
- if (! finfo->info->keep_memory)
- copy = true;
- hash = true;
+ copy = FALSE;
+ if (! flaginfo->info->keep_memory)
+ copy = TRUE;
+ hash = TRUE;
if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
- hash = false;
+ hash = FALSE;
if (! _bfd_coff_get_external_symbols (input_bfd))
- return false;
+ return FALSE;
esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
- isymp = finfo->internal_syms;
- secpp = finfo->sec_ptrs;
- indexp = finfo->sym_indices;
+ isymp = flaginfo->internal_syms;
+ secpp = flaginfo->sec_ptrs;
+ indexp = flaginfo->sym_indices;
output_index = syment_base;
- outsym = finfo->outsyms;
-
- if (coff_data (output_bfd)->pe)
+ outsym = flaginfo->outsyms;
+
+ if (coff_data (output_bfd)->pe
+ && ! process_embedded_commands (output_bfd, flaginfo->info, input_bfd))
+ return FALSE;
+
+ /* If we are going to perform relocations and also strip/discard some
+ symbols then we must make sure that we do not strip/discard those
+ symbols that are going to be involved in the relocations. */
+ if (( flaginfo->info->strip != strip_none
+ || flaginfo->info->discard != discard_none)
+ && flaginfo->info->relocatable)
{
- if (! process_embedded_commands (output_bfd, finfo->info, input_bfd))
- return false;
- }
+ /* Mark the symbol array as 'not-used'. */
+ memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
- /* If we are going to perform relocations and also strip/discard some symbols
- then we must make sure that we do not strip/discard those symbols that are
- going to be involved in the relocations */
- if (( finfo->info->strip != strip_none
- || finfo->info->discard != discard_none)
- && finfo->info->relocateable)
- {
- /* mark the symbol array as 'not-used' */
- memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
-
- mark_relocs (finfo, input_bfd);
+ mark_relocs (flaginfo, input_bfd);
}
while (esym < esym_end)
{
struct internal_syment isym;
enum coff_symbol_classification classification;
- boolean skip;
- boolean global;
- boolean dont_skip_symbol;
+ bfd_boolean skip;
+ bfd_boolean global;
+ bfd_boolean dont_skip_symbol;
int add;
- bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
+ bfd_coff_swap_sym_in (input_bfd, esym, isymp);
/* Make a copy of *isymp so that the relocate_section function
always sees the original values. This is more reliable than
/* Extract the flag indicating if this symbol is used by a
relocation. */
- if ((finfo->info->strip != strip_none
- || finfo->info->discard != discard_none)
- && finfo->info->relocateable)
+ if ((flaginfo->info->strip != strip_none
+ || flaginfo->info->discard != discard_none)
+ && flaginfo->info->relocatable)
dont_skip_symbol = *indexp;
else
- dont_skip_symbol = false;
-
+ dont_skip_symbol = FALSE;
+
*indexp = -1;
- skip = false;
- global = false;
+ skip = FALSE;
+ global = FALSE;
add = 1 + isym.n_numaux;
/* If we are stripping all symbols, we want to skip this one. */
- if (finfo->info->strip == strip_all && ! dont_skip_symbol)
- skip = true;
+ if (flaginfo->info->strip == strip_all && ! dont_skip_symbol)
+ skip = TRUE;
if (! skip)
{
end of the symbol table, so skip them for now.
Locally defined function symbols, however, are an
exception, and are not moved to the end. */
- global = true;
+ global = TRUE;
if (! ISFCN (isym.n_type))
- skip = true;
+ skip = TRUE;
break;
case COFF_SYMBOL_UNDEFINED:
/* Undefined symbols are left for the end. */
- global = true;
- skip = true;
+ global = TRUE;
+ skip = TRUE;
break;
case COFF_SYMBOL_LOCAL:
/* This is a local symbol. Skip it if we are discarding
local symbols. */
- if (finfo->info->discard == discard_all && ! dont_skip_symbol)
- skip = true;
+ if (flaginfo->info->discard == discard_all && ! dont_skip_symbol)
+ skip = TRUE;
break;
}
}
+#ifndef COFF_WITH_PE
+ /* Skip section symbols for sections which are not going to be
+ emitted. */
+ if (!skip
+ && !dont_skip_symbol
+ && isym.n_sclass == C_STAT
+ && isym.n_type == T_NULL
+ && isym.n_numaux > 0
+ && ((*secpp)->output_section == bfd_abs_section_ptr
+ || bfd_section_removed_from_list (output_bfd,
+ (*secpp)->output_section)))
+ skip = TRUE;
+#endif
+
/* If we stripping debugging symbols, and this is a debugging
symbol, then skip it. FIXME: gas sets the section to N_ABS
for some types of debugging symbols; I don't know if this is
a bug or not. In any case, we handle it here. */
if (! skip
- && finfo->info->strip == strip_debugger
+ && flaginfo->info->strip == strip_debugger
&& ! dont_skip_symbol
&& (isym.n_scnum == N_DEBUG
|| (isym.n_scnum == N_ABS
|| isym.n_sclass == C_REGPARM
|| isym.n_sclass == C_FIELD
|| isym.n_sclass == C_EOS))))
- skip = true;
+ skip = TRUE;
/* If some symbols are stripped based on the name, work out the
name and decide whether to skip this symbol. */
if (! skip
- && (finfo->info->strip == strip_some
- || finfo->info->discard == discard_l))
+ && (flaginfo->info->strip == strip_some
+ || flaginfo->info->discard == discard_l))
{
const char *name;
char buf[SYMNMLEN + 1];
name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
if (name == NULL)
- return false;
+ return FALSE;
if (! dont_skip_symbol
- && ((finfo->info->strip == strip_some
- && (bfd_hash_lookup (finfo->info->keep_hash, name, false,
- false) == NULL))
+ && ((flaginfo->info->strip == strip_some
+ && (bfd_hash_lookup (flaginfo->info->keep_hash, name, FALSE,
+ FALSE) == NULL))
|| (! global
- && finfo->info->discard == discard_l
+ && flaginfo->info->discard == discard_l
&& bfd_is_local_label_name (input_bfd, name))))
- skip = true;
+ skip = TRUE;
}
/* If this is an enum, struct, or union tag, see if we have
already output an identical type. */
if (! skip
- && (finfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0
+ && (flaginfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0
&& (isym.n_sclass == C_ENTAG
|| isym.n_sclass == C_STRTAG
|| isym.n_sclass == C_UNTAG)
struct coff_debug_merge_element **epp;
bfd_byte *esl, *eslend;
struct internal_syment *islp;
+ bfd_size_type amt;
name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
if (name == NULL)
- return false;
+ return FALSE;
/* Ignore fake names invented by compiler; treat them all as
the same name. */
&& (name[1] == '~' || name[1] == '.' || name[1] == '$')))
name = "";
- mh = coff_debug_merge_hash_lookup (&finfo->debug_merge, name,
- true, true);
+ mh = coff_debug_merge_hash_lookup (&flaginfo->debug_merge, name,
+ TRUE, TRUE);
if (mh == NULL)
- return false;
+ return FALSE;
/* Allocate memory to hold type information. If this turns
out to be a duplicate, we pass this address to
bfd_release. */
- mt = ((struct coff_debug_merge_type *)
- bfd_alloc (input_bfd,
- sizeof (struct coff_debug_merge_type)));
+ amt = sizeof (struct coff_debug_merge_type);
+ mt = (struct coff_debug_merge_type *) bfd_alloc (input_bfd, amt);
if (mt == NULL)
- return false;
- mt->class = isym.n_sclass;
+ return FALSE;
+ mt->type_class = isym.n_sclass;
/* Pick up the aux entry, which points to the end of the tag
entries. */
- bfd_coff_swap_aux_in (input_bfd, (PTR) (esym + isymesz),
+ bfd_coff_swap_aux_in (input_bfd, (esym + isymesz),
isym.n_type, isym.n_sclass, 0, isym.n_numaux,
- (PTR) &aux);
+ &aux);
/* Gather the elements. */
epp = &mt->elements;
char elebuf[SYMNMLEN + 1];
char *name_copy;
- bfd_coff_swap_sym_in (input_bfd, (PTR) esl, (PTR) islp);
+ bfd_coff_swap_sym_in (input_bfd, esl, islp);
- *epp = ((struct coff_debug_merge_element *)
- bfd_alloc (input_bfd,
- sizeof (struct coff_debug_merge_element)));
+ amt = sizeof (struct coff_debug_merge_element);
+ *epp = (struct coff_debug_merge_element *)
+ bfd_alloc (input_bfd, amt);
if (*epp == NULL)
- return false;
+ return FALSE;
elename = _bfd_coff_internal_syment_name (input_bfd, islp,
elebuf);
if (elename == NULL)
- return false;
+ return FALSE;
- name_copy = (char *) bfd_alloc (input_bfd,
- strlen (elename) + 1);
+ amt = strlen (elename) + 1;
+ name_copy = (char *) bfd_alloc (input_bfd, amt);
if (name_copy == NULL)
- return false;
+ return FALSE;
strcpy (name_copy, elename);
(*epp)->name = name_copy;
union internal_auxent eleaux;
long indx;
- bfd_coff_swap_aux_in (input_bfd, (PTR) (esl + isymesz),
+ bfd_coff_swap_aux_in (input_bfd, (esl + isymesz),
islp->n_type, islp->n_sclass, 0,
- islp->n_numaux, (PTR) &eleaux);
+ islp->n_numaux, &eleaux);
indx = eleaux.x_sym.x_tagndx.l;
/* FIXME: If this tagndx entry refers to a symbol
defined later in this file, we just ignore it.
Handling this correctly would be tedious, and may
not be required. */
-
if (indx > 0
&& (indx
< ((esym -
(bfd_byte *) obj_coff_external_syms (input_bfd))
/ (long) isymesz)))
{
- (*epp)->tagndx = finfo->sym_indices[indx];
+ (*epp)->tagndx = flaginfo->sym_indices[indx];
if ((*epp)->tagndx < 0)
(*epp)->tagndx = 0;
}
type. We always output the type if it has no elements,
for simplicity. */
if (mt->elements == NULL)
- bfd_release (input_bfd, (PTR) mt);
+ bfd_release (input_bfd, mt);
else
{
struct coff_debug_merge_type *mtl;
{
struct coff_debug_merge_element *me, *mel;
- if (mtl->class != mt->class)
+ if (mtl->type_class != mt->type_class)
continue;
for (me = mt->elements, mel = mtl->elements;
else
{
/* This is a redefinition which can be merged. */
- bfd_release (input_bfd, (PTR) mt);
+ bfd_release (input_bfd, mt);
*indexp = mtl->indx;
add = (eslend - esym) / isymesz;
- skip = true;
+ skip = TRUE;
}
}
}
bfd_coff_symname_in_debug. That is only true for
XCOFF, and XCOFF requires different linking code
anyhow. */
- name = _bfd_coff_internal_syment_name (input_bfd, &isym,
- (char *) NULL);
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
if (name == NULL)
- return false;
- indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
+ return FALSE;
+ indx = _bfd_stringtab_add (flaginfo->strtab, name, hash, copy);
if (indx == (bfd_size_type) -1)
- return false;
+ return FALSE;
isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
}
isym.n_value += (*secpp)->output_offset;
if (! obj_pe (input_bfd))
isym.n_value -= (*secpp)->vma;
- if (! obj_pe (finfo->output_bfd))
+ if (! obj_pe (flaginfo->output_bfd))
isym.n_value += (*secpp)->output_section->vma;
}
break;
it). We try to get this right, below, just before we
write the symbols out, but in the general case we may
have to write the symbol out twice. */
-
- if (finfo->last_file_index != -1
- && finfo->last_file.n_value != (long) output_index)
+ if (flaginfo->last_file_index != -1
+ && flaginfo->last_file.n_value != (bfd_vma) output_index)
{
/* We must correct the value of the last C_FILE
entry. */
- finfo->last_file.n_value = output_index;
- if ((bfd_size_type) finfo->last_file_index >= syment_base)
+ flaginfo->last_file.n_value = output_index;
+ if ((bfd_size_type) flaginfo->last_file_index >= syment_base)
{
/* The last C_FILE symbol is in this input file. */
bfd_coff_swap_sym_out (output_bfd,
- (PTR) &finfo->last_file,
- (PTR) (finfo->outsyms
- + ((finfo->last_file_index
- - syment_base)
- * osymesz)));
+ &flaginfo->last_file,
+ (flaginfo->outsyms
+ + ((flaginfo->last_file_index
+ - syment_base)
+ * osymesz)));
}
else
{
+ file_ptr pos;
+
/* We have already written out the last C_FILE
symbol. We need to write it out again. We
borrow *outsym temporarily. */
bfd_coff_swap_sym_out (output_bfd,
- (PTR) &finfo->last_file,
- (PTR) outsym);
- if (bfd_seek (output_bfd,
- (obj_sym_filepos (output_bfd)
- + finfo->last_file_index * osymesz),
- SEEK_SET) != 0
- || (bfd_write (outsym, osymesz, 1, output_bfd)
- != osymesz))
- return false;
+ &flaginfo->last_file, outsym);
+ pos = obj_sym_filepos (output_bfd);
+ pos += flaginfo->last_file_index * osymesz;
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (outsym, osymesz, output_bfd) != osymesz)
+ return FALSE;
}
}
- finfo->last_file_index = output_index;
- finfo->last_file = isym;
+ flaginfo->last_file_index = output_index;
+ flaginfo->last_file = isym;
break;
}
/* If doing task linking, convert normal global function symbols to
- static functions. */
-
- if (finfo->info->task_link
- && (isym.n_sclass == C_EXT
- || isym.n_sclass == C_WEAKEXT
- || (obj_pe (input_bfd) && isym.n_sclass == C_NT_WEAK)))
+ static functions. */
+ if (flaginfo->info->task_link && IS_EXTERNAL (input_bfd, isym))
isym.n_sclass = C_STAT;
/* Output the symbol. */
-
- bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+ bfd_coff_swap_sym_out (output_bfd, &isym, outsym);
*indexp = output_index;
/* This can happen if there were errors earlier in
the link. */
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
h->indx = output_index;
}
/* Fix up the aux entries. This must be done in a separate pass,
because we don't know the correct symbol indices until we have
already decided which symbols we are going to keep. */
-
esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
- isymp = finfo->internal_syms;
- indexp = finfo->sym_indices;
+ isymp = flaginfo->internal_syms;
+ indexp = flaginfo->sym_indices;
sym_hash = obj_coff_sym_hashes (input_bfd);
- outsym = finfo->outsyms;
+ outsym = flaginfo->outsyms;
+
while (esym < esym_end)
{
int add;
generate two symbols with the same name, but only one
will have aux entries. */
BFD_ASSERT (isymp->n_numaux == 0
+ || h->numaux == 0
|| h->numaux == isymp->n_numaux);
}
union internal_auxent aux;
union internal_auxent *auxp;
- if (h != NULL)
+ if (h != NULL && h->aux != NULL && (h->numaux > i))
auxp = h->aux + i;
else
{
- bfd_coff_swap_aux_in (input_bfd, (PTR) esym, isymp->n_type,
- isymp->n_sclass, i, isymp->n_numaux,
- (PTR) &aux);
+ bfd_coff_swap_aux_in (input_bfd, esym, isymp->n_type,
+ isymp->n_sclass, i, isymp->n_numaux, &aux);
auxp = &aux;
}
{
strings = _bfd_coff_read_string_table (input_bfd);
if (strings == NULL)
- return false;
+ return FALSE;
}
filename = strings + auxp->x_file.x_n.x_offset;
- indx = _bfd_stringtab_add (finfo->strtab, filename,
+ indx = _bfd_stringtab_add (flaginfo->strtab, filename,
hash, copy);
if (indx == (bfd_size_type) -1)
- return false;
+ return FALSE;
auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
}
}
- else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+ else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+ && isymp->n_sclass != C_NT_WEAK)
{
unsigned long indx;
the index of the next symbol we are going
to include. I don't know if this is
entirely right. */
- while ((finfo->sym_indices[indx] < 0
- || ((bfd_size_type) finfo->sym_indices[indx]
+ while ((flaginfo->sym_indices[indx] < 0
+ || ((bfd_size_type) flaginfo->sym_indices[indx]
< syment_base))
&& indx < obj_raw_syment_count (input_bfd))
++indx;
if (indx >= obj_raw_syment_count (input_bfd))
indx = output_index;
else
- indx = finfo->sym_indices[indx];
+ indx = flaginfo->sym_indices[indx];
auxp->x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
}
}
{
long symindx;
- symindx = finfo->sym_indices[indx];
+ symindx = flaginfo->sym_indices[indx];
if (symindx < 0)
auxp->x_sym.x_tagndx.l = 0;
else
&& isymp->_n._n_name[2] == 'f'
&& isymp->_n._n_name[3] == '\0')
{
- if (finfo->last_bf_index != -1)
+ if (flaginfo->last_bf_index != -1)
{
- finfo->last_bf.x_sym.x_fcnary.x_fcn.x_endndx.l =
+ flaginfo->last_bf.x_sym.x_fcnary.x_fcn.x_endndx.l =
*indexp;
- if ((bfd_size_type) finfo->last_bf_index
+ if ((bfd_size_type) flaginfo->last_bf_index
>= syment_base)
{
- PTR auxout;
+ void *auxout;
/* The last .bf symbol is in this input
file. This will only happen if the
assembler did not set up the .bf
endndx symbols correctly. */
- auxout = (PTR) (finfo->outsyms
- + ((finfo->last_bf_index
- - syment_base)
- * osymesz));
+ auxout = (flaginfo->outsyms
+ + ((flaginfo->last_bf_index
+ - syment_base)
+ * osymesz));
+
bfd_coff_swap_aux_out (output_bfd,
- (PTR) &finfo->last_bf,
+ &flaginfo->last_bf,
isymp->n_type,
isymp->n_sclass,
0, isymp->n_numaux,
}
else
{
+ file_ptr pos;
+
/* We have already written out the last
.bf aux entry. We need to write it
out again. We borrow *outsym
temporarily. FIXME: This case should
be made faster. */
bfd_coff_swap_aux_out (output_bfd,
- (PTR) &finfo->last_bf,
+ &flaginfo->last_bf,
isymp->n_type,
isymp->n_sclass,
0, isymp->n_numaux,
- (PTR) outsym);
- if (bfd_seek (output_bfd,
- (obj_sym_filepos (output_bfd)
- + finfo->last_bf_index * osymesz),
- SEEK_SET) != 0
- || bfd_write (outsym, osymesz, 1,
- output_bfd) != osymesz)
- return false;
+ outsym);
+ pos = obj_sym_filepos (output_bfd);
+ pos += flaginfo->last_bf_index * osymesz;
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || (bfd_bwrite (outsym, osymesz, output_bfd)
+ != osymesz))
+ return FALSE;
}
}
if (auxp->x_sym.x_fcnary.x_fcn.x_endndx.l != 0)
- finfo->last_bf_index = -1;
+ flaginfo->last_bf_index = -1;
else
{
/* The endndx field of this aux entry must
be updated with the symbol number of the
next .bf symbol. */
- finfo->last_bf = *auxp;
- finfo->last_bf_index = (((outsym - finfo->outsyms)
+ flaginfo->last_bf = *auxp;
+ flaginfo->last_bf_index = (((outsym - flaginfo->outsyms)
/ osymesz)
+ syment_base);
}
if (h == NULL)
{
- bfd_coff_swap_aux_out (output_bfd, (PTR) auxp, isymp->n_type,
+ bfd_coff_swap_aux_out (output_bfd, auxp, isymp->n_type,
isymp->n_sclass, i, isymp->n_numaux,
- (PTR) outsym);
+ outsym);
outsym += osymesz;
}
}
/* Relocate the line numbers, unless we are stripping them. */
- if (finfo->info->strip == strip_none
- || finfo->info->strip == strip_some)
+ if (flaginfo->info->strip == strip_none
+ || flaginfo->info->strip == strip_some)
{
for (o = input_bfd->sections; o != NULL; o = o->next)
{
bfd_byte *eline;
bfd_byte *elineend;
bfd_byte *oeline;
- boolean skipping;
+ bfd_boolean skipping;
+ file_ptr pos;
+ bfd_size_type amt;
/* FIXME: If SEC_HAS_CONTENTS is not for the section, then
build_link_order in ldwrite.c will not have created a
continue;
if (bfd_seek (input_bfd, o->line_filepos, SEEK_SET) != 0
- || bfd_read (finfo->linenos, linesz, o->lineno_count,
+ || bfd_bread (flaginfo->linenos, linesz * o->lineno_count,
input_bfd) != linesz * o->lineno_count)
- return false;
+ return FALSE;
offset = o->output_section->vma + o->output_offset - o->vma;
- eline = finfo->linenos;
- oeline = finfo->linenos;
+ eline = flaginfo->linenos;
+ oeline = flaginfo->linenos;
elineend = eline + linesz * o->lineno_count;
- skipping = false;
+ skipping = FALSE;
for (; eline < elineend; eline += linesz)
{
struct internal_lineno iline;
- bfd_coff_swap_lineno_in (input_bfd, (PTR) eline, (PTR) &iline);
+ bfd_coff_swap_lineno_in (input_bfd, eline, &iline);
if (iline.l_lnno != 0)
iline.l_addr.l_paddr += offset;
{
long indx;
- indx = finfo->sym_indices[iline.l_addr.l_symndx];
+ indx = flaginfo->sym_indices[iline.l_addr.l_symndx];
if (indx < 0)
{
with symbol #0) will fail. We can't regain
the space in the output file, but at least
they're dense. */
- skipping = true;
+ skipping = TRUE;
}
else
{
of the line numbers rather than an absolute
file index. */
bfd_coff_swap_sym_in (output_bfd,
- (PTR) (finfo->outsyms
- + ((indx - syment_base)
- * osymesz)),
- (PTR) &is);
+ (flaginfo->outsyms
+ + ((indx - syment_base)
+ * osymesz)), &is);
if ((ISFCN (is.n_type)
|| is.n_sclass == C_BLOCK)
&& is.n_numaux >= 1)
{
- PTR auxptr;
+ void *auxptr;
- auxptr = (PTR) (finfo->outsyms
- + ((indx - syment_base + 1)
- * osymesz));
+ auxptr = (flaginfo->outsyms
+ + ((indx - syment_base + 1)
+ * osymesz));
bfd_coff_swap_aux_in (output_bfd, auxptr,
is.n_type, is.n_sclass,
- 0, is.n_numaux, (PTR) &ia);
+ 0, is.n_numaux, &ia);
ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
(o->output_section->line_filepos
+ o->output_section->lineno_count * linesz
- + eline - finfo->linenos);
- bfd_coff_swap_aux_out (output_bfd, (PTR) &ia,
+ + eline - flaginfo->linenos);
+ bfd_coff_swap_aux_out (output_bfd, &ia,
is.n_type, is.n_sclass, 0,
is.n_numaux, auxptr);
}
- skipping = false;
+ skipping = FALSE;
}
iline.l_addr.l_symndx = indx;
if (!skipping)
{
- bfd_coff_swap_lineno_out (output_bfd, (PTR) &iline,
- (PTR) oeline);
+ bfd_coff_swap_lineno_out (output_bfd, &iline, oeline);
oeline += linesz;
}
}
- if (bfd_seek (output_bfd,
- (o->output_section->line_filepos
- + o->output_section->lineno_count * linesz),
- SEEK_SET) != 0
- || (bfd_write (finfo->linenos, 1, oeline - finfo->linenos,
- output_bfd)
- != (bfd_size_type) (oeline - finfo->linenos)))
- return false;
-
- o->output_section->lineno_count +=
- (oeline - finfo->linenos) / linesz;
+ pos = o->output_section->line_filepos;
+ pos += o->output_section->lineno_count * linesz;
+ amt = oeline - flaginfo->linenos;
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (flaginfo->linenos, amt, output_bfd) != amt)
+ return FALSE;
+
+ o->output_section->lineno_count += amt / linesz;
}
}
symbol will be the first symbol in the next input file. In the
normal case, this will save us from writing out the C_FILE symbol
again. */
- if (finfo->last_file_index != -1
- && (bfd_size_type) finfo->last_file_index >= syment_base)
+ if (flaginfo->last_file_index != -1
+ && (bfd_size_type) flaginfo->last_file_index >= syment_base)
{
- finfo->last_file.n_value = output_index;
- bfd_coff_swap_sym_out (output_bfd, (PTR) &finfo->last_file,
- (PTR) (finfo->outsyms
- + ((finfo->last_file_index - syment_base)
- * osymesz)));
+ flaginfo->last_file.n_value = output_index;
+ bfd_coff_swap_sym_out (output_bfd, &flaginfo->last_file,
+ (flaginfo->outsyms
+ + ((flaginfo->last_file_index - syment_base)
+ * osymesz)));
}
/* Write the modified symbols to the output file. */
- if (outsym > finfo->outsyms)
+ if (outsym > flaginfo->outsyms)
{
- if (bfd_seek (output_bfd,
- obj_sym_filepos (output_bfd) + syment_base * osymesz,
- SEEK_SET) != 0
- || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
- output_bfd)
- != (bfd_size_type) (outsym - finfo->outsyms)))
- return false;
+ file_ptr pos;
+ bfd_size_type amt;
+
+ pos = obj_sym_filepos (output_bfd) + syment_base * osymesz;
+ amt = outsym - flaginfo->outsyms;
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (flaginfo->outsyms, amt, output_bfd) != amt)
+ return FALSE;
BFD_ASSERT ((obj_raw_syment_count (output_bfd)
- + (outsym - finfo->outsyms) / osymesz)
+ + (outsym - flaginfo->outsyms) / osymesz)
== output_index);
obj_raw_syment_count (output_bfd) = output_index;
struct coff_section_tdata *secdata;
if (! o->linker_mark)
- {
- /* This section was omitted from the link. */
- continue;
- }
+ /* This section was omitted from the link. */
+ continue;
+
+ if ((o->flags & SEC_LINKER_CREATED) != 0)
+ continue;
if ((o->flags & SEC_HAS_CONTENTS) == 0
- || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0))
+ || (o->size == 0 && (o->flags & SEC_RELOC) == 0))
{
if ((o->flags & SEC_RELOC) != 0
&& o->reloc_count != 0)
{
- ((*_bfd_error_handler)
- (_("%s: relocs in section `%s', but it has no contents"),
- bfd_get_filename (input_bfd),
- bfd_get_section_name (input_bfd, o)));
+ (*_bfd_error_handler)
+ (_("%B: relocs in section `%A', but it has no contents"),
+ input_bfd, o);
bfd_set_error (bfd_error_no_contents);
- return false;
+ return FALSE;
}
continue;
contents = secdata->contents;
else
{
- if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
- (file_ptr) 0, o->_raw_size))
- return false;
- contents = finfo->contents;
+ contents = flaginfo->contents;
+ if (! bfd_get_full_section_contents (input_bfd, o, &contents))
+ return FALSE;
}
if ((o->flags & SEC_RELOC) != 0)
/* Read in the relocs. */
target_index = o->output_section->target_index;
internal_relocs = (_bfd_coff_read_internal_relocs
- (input_bfd, o, false, finfo->external_relocs,
- finfo->info->relocateable,
- (finfo->info->relocateable
- ? (finfo->section_info[target_index].relocs
+ (input_bfd, o, FALSE, flaginfo->external_relocs,
+ flaginfo->info->relocatable,
+ (flaginfo->info->relocatable
+ ? (flaginfo->section_info[target_index].relocs
+ o->output_section->reloc_count)
- : finfo->internal_relocs)));
- if (internal_relocs == NULL)
- return false;
+ : flaginfo->internal_relocs)));
+ if (internal_relocs == NULL
+ && o->reloc_count > 0)
+ return FALSE;
+
+ /* Run through the relocs looking for relocs against symbols
+ coming from discarded sections and complain about them. */
+ irel = internal_relocs;
+ for (; irel < &internal_relocs[o->reloc_count]; irel++)
+ {
+ struct coff_link_hash_entry *h;
+ asection *ps = NULL;
+ long symndx = irel->r_symndx;
+ if (symndx < 0)
+ continue;
+ h = obj_coff_sym_hashes (input_bfd)[symndx];
+ if (h == NULL)
+ continue;
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct coff_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ ps = h->root.u.def.section;
+ if (ps == NULL)
+ continue;
+ /* Complain if definition comes from an excluded section. */
+ if (ps->flags & SEC_EXCLUDE)
+ (*flaginfo->info->callbacks->einfo)
+ (_("%X`%s' referenced in section `%A' of %B: "
+ "defined in discarded section `%A' of %B\n"),
+ h->root.root.string, o, input_bfd, ps, ps->owner);
+ }
/* Call processor specific code to relocate the section
contents. */
- if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+ if (! bfd_coff_relocate_section (output_bfd, flaginfo->info,
input_bfd, o,
contents,
internal_relocs,
- finfo->internal_syms,
- finfo->sec_ptrs))
- return false;
+ flaginfo->internal_syms,
+ flaginfo->sec_ptrs))
+ return FALSE;
- if (finfo->info->relocateable)
+ if (flaginfo->info->relocatable)
{
bfd_vma offset;
struct internal_reloc *irelend;
offset = o->output_section->vma + o->output_offset - o->vma;
irel = internal_relocs;
irelend = irel + o->reloc_count;
- rel_hash = (finfo->section_info[target_index].rel_hashes
+ rel_hash = (flaginfo->section_info[target_index].rel_hashes
+ o->output_section->reloc_count);
for (; irel < irelend; irel++, rel_hash++)
{
struct coff_link_hash_entry *h;
- boolean adjusted;
+ bfd_boolean adjusted;
*rel_hash = NULL;
/* Adjust the reloc address and symbol index. */
-
irel->r_vaddr += offset;
if (irel->r_symndx == -1)
if (adjust_symndx)
{
- if (! (*adjust_symndx) (output_bfd, finfo->info,
+ if (! (*adjust_symndx) (output_bfd, flaginfo->info,
input_bfd, o, irel,
&adjusted))
- return false;
+ return FALSE;
if (adjusted)
continue;
}
{
long indx;
- indx = finfo->sym_indices[irel->r_symndx];
+ indx = flaginfo->sym_indices[irel->r_symndx];
if (indx != -1)
irel->r_symndx = indx;
else
/* This reloc is against a symbol we are
stripping. This should have been handled
by the 'dont_skip_symbol' code in the while
- loop at the top of this function. */
-
- is = finfo->internal_syms + irel->r_symndx;
+ loop at the top of this function. */
+ is = flaginfo->internal_syms + irel->r_symndx;
name = (_bfd_coff_internal_syment_name
(input_bfd, is, buf));
if (name == NULL)
- return false;
+ return FALSE;
- if (! ((*finfo->info->callbacks->unattached_reloc)
- (finfo->info, name, input_bfd, o,
+ if (! ((*flaginfo->info->callbacks->unattached_reloc)
+ (flaginfo->info, name, input_bfd, o,
irel->r_vaddr)))
- return false;
+ return FALSE;
}
}
}
/* Write out the modified section contents. */
if (secdata == NULL || secdata->stab_info == NULL)
{
+ file_ptr loc = o->output_offset * bfd_octets_per_byte (output_bfd);
if (! bfd_set_section_contents (output_bfd, o->output_section,
- contents, o->output_offset,
- (o->_cooked_size != 0
- ? o->_cooked_size
- : o->_raw_size)))
- return false;
+ contents, loc, o->size))
+ return FALSE;
}
else
{
if (! (_bfd_write_section_stabs
- (output_bfd, &coff_hash_table (finfo->info)->stab_info,
+ (output_bfd, &coff_hash_table (flaginfo->info)->stab_info,
o, &secdata->stab_info, contents)))
- return false;
+ return FALSE;
}
}
- if (! finfo->info->keep_memory)
- {
- if (! _bfd_coff_free_symbols (input_bfd))
- return false;
- }
+ if (! flaginfo->info->keep_memory
+ && ! _bfd_coff_free_symbols (input_bfd))
+ return FALSE;
- return true;
+ return TRUE;
}
-/* Write out a global symbol. Called via coff_link_hash_traverse. */
+/* Write out a global symbol. Called via bfd_hash_traverse. */
-boolean
-_bfd_coff_write_global_sym (h, data)
- struct coff_link_hash_entry *h;
- PTR data;
+bfd_boolean
+_bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data)
{
- struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
+ struct coff_link_hash_entry *h = (struct coff_link_hash_entry *) bh;
+ struct coff_final_link_info *flaginfo = (struct coff_final_link_info *) data;
bfd *output_bfd;
struct internal_syment isym;
bfd_size_type symesz;
unsigned int i;
+ file_ptr pos;
- output_bfd = finfo->output_bfd;
+ output_bfd = flaginfo->output_bfd;
+
+ if (h->root.type == bfd_link_hash_warning)
+ {
+ h = (struct coff_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_new)
+ return TRUE;
+ }
if (h->indx >= 0)
- return true;
+ return TRUE;
if (h->indx != -2
- && (finfo->info->strip == strip_all
- || (finfo->info->strip == strip_some
- && (bfd_hash_lookup (finfo->info->keep_hash,
- h->root.root.string, false, false)
+ && (flaginfo->info->strip == strip_all
+ || (flaginfo->info->strip == strip_some
+ && (bfd_hash_lookup (flaginfo->info->keep_hash,
+ h->root.root.string, FALSE, FALSE)
== NULL))))
- return true;
+ return TRUE;
switch (h->root.type)
{
default:
case bfd_link_hash_new:
+ case bfd_link_hash_warning:
abort ();
- return false;
+ return FALSE;
case bfd_link_hash_undefined:
case bfd_link_hash_undefweak:
isym.n_scnum = sec->target_index;
isym.n_value = (h->root.u.def.value
+ h->root.u.def.section->output_offset);
- if (! obj_pe (finfo->output_bfd))
+ if (! obj_pe (flaginfo->output_bfd))
isym.n_value += sec->vma;
}
break;
break;
case bfd_link_hash_indirect:
- case bfd_link_hash_warning:
/* Just ignore these. They can't be handled anyhow. */
- return true;
+ return TRUE;
}
if (strlen (h->root.root.string) <= SYMNMLEN)
strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
else
{
- boolean hash;
+ bfd_boolean hash;
bfd_size_type indx;
- hash = true;
+ hash = TRUE;
if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
- hash = false;
- indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
- false);
+ hash = FALSE;
+ indx = _bfd_stringtab_add (flaginfo->strtab, h->root.root.string, hash,
+ FALSE);
if (indx == (bfd_size_type) -1)
{
- finfo->failed = true;
- return false;
+ flaginfo->failed = TRUE;
+ return FALSE;
}
isym._n._n_n._n_zeroes = 0;
isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
}
- isym.n_sclass = h->class;
+ isym.n_sclass = h->symbol_class;
isym.n_type = h->type;
if (isym.n_sclass == C_NULL)
/* If doing task linking and this is the pass where we convert
defined globals to statics, then do that conversion now. If the
symbol is not being converted, just ignore it and it will be
- output during a later pass. */
- if (finfo->global_to_static)
+ output during a later pass. */
+ if (flaginfo->global_to_static)
{
- if (isym.n_sclass != C_EXT
- && isym.n_sclass != C_WEAKEXT
- && (! obj_pe (output_bfd) || isym.n_sclass != C_NT_WEAK))
- {
- return true;
- }
+ if (! IS_EXTERNAL (output_bfd, isym))
+ return TRUE;
+
isym.n_sclass = C_STAT;
}
+ /* When a weak symbol is not overridden by a strong one,
+ turn it into an external symbol when not building a
+ shared or relocatable object. */
+ if (! flaginfo->info->shared
+ && ! flaginfo->info->relocatable
+ && IS_WEAK_EXTERNAL (flaginfo->output_bfd, isym))
+ isym.n_sclass = C_EXT;
+
isym.n_numaux = h->numaux;
-
- bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) finfo->outsyms);
+
+ bfd_coff_swap_sym_out (output_bfd, &isym, flaginfo->outsyms);
symesz = bfd_coff_symesz (output_bfd);
- if (bfd_seek (output_bfd,
- (obj_sym_filepos (output_bfd)
- + obj_raw_syment_count (output_bfd) * symesz),
- SEEK_SET) != 0
- || bfd_write (finfo->outsyms, symesz, 1, output_bfd) != symesz)
+ pos = obj_sym_filepos (output_bfd);
+ pos += obj_raw_syment_count (output_bfd) * symesz;
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (flaginfo->outsyms, symesz, output_bfd) != symesz)
{
- finfo->failed = true;
- return false;
+ flaginfo->failed = TRUE;
+ return FALSE;
}
h->indx = obj_raw_syment_count (output_bfd);
sec = h->root.u.def.section->output_section;
if (sec != NULL)
{
- auxp->x_scn.x_scnlen = (sec->_cooked_size != 0
- ? sec->_cooked_size
- : sec->_raw_size);
+ auxp->x_scn.x_scnlen = sec->size;
/* For PE, an overflow on the final link reportedly does
not matter. FIXME: Why not? */
-
if (sec->reloc_count > 0xffff
&& (! obj_pe (output_bfd)
- || finfo->info->relocateable))
+ || flaginfo->info->relocatable))
(*_bfd_error_handler)
(_("%s: %s: reloc overflow: 0x%lx > 0xffff"),
bfd_get_filename (output_bfd),
if (sec->lineno_count > 0xffff
&& (! obj_pe (output_bfd)
- || finfo->info->relocateable))
+ || flaginfo->info->relocatable))
(*_bfd_error_handler)
(_("%s: warning: %s: line number overflow: 0x%lx > 0xffff"),
bfd_get_filename (output_bfd),
}
}
- bfd_coff_swap_aux_out (output_bfd, (PTR) auxp, isym.n_type,
- isym.n_sclass, i, isym.n_numaux,
- (PTR) finfo->outsyms);
- if (bfd_write (finfo->outsyms, symesz, 1, output_bfd) != symesz)
+ bfd_coff_swap_aux_out (output_bfd, auxp, isym.n_type,
+ isym.n_sclass, (int) i, isym.n_numaux,
+ flaginfo->outsyms);
+ if (bfd_bwrite (flaginfo->outsyms, symesz, output_bfd) != symesz)
{
- finfo->failed = true;
- return false;
+ flaginfo->failed = TRUE;
+ return FALSE;
}
++obj_raw_syment_count (output_bfd);
}
- return true;
+ return TRUE;
}
/* Write out task global symbols, converting them to statics. Called
via coff_link_hash_traverse. Calls bfd_coff_write_global_sym to do
- the dirty work, if the symbol we are processing needs conversion. */
+ the dirty work, if the symbol we are processing needs conversion. */
-boolean
-_bfd_coff_write_task_globals (h, data)
- struct coff_link_hash_entry *h;
- PTR data;
+bfd_boolean
+_bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
{
- struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
- boolean rtnval = true;
- boolean save_global_to_static;
+ struct coff_final_link_info *flaginfo = (struct coff_final_link_info *) data;
+ bfd_boolean rtnval = TRUE;
+ bfd_boolean save_global_to_static;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct coff_link_hash_entry *) h->root.u.i.link;
if (h->indx < 0)
{
{
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
- save_global_to_static = finfo->global_to_static;
- finfo->global_to_static = true;
- rtnval = _bfd_coff_write_global_sym (h, data);
- finfo->global_to_static = save_global_to_static;
+ save_global_to_static = flaginfo->global_to_static;
+ flaginfo->global_to_static = TRUE;
+ rtnval = _bfd_coff_write_global_sym (&h->root.root, data);
+ flaginfo->global_to_static = save_global_to_static;
break;
default:
break;
/* Handle a link order which is supposed to generate a reloc. */
-boolean
-_bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
- bfd *output_bfd;
- struct coff_final_link_info *finfo;
- asection *output_section;
- struct bfd_link_order *link_order;
+bfd_boolean
+_bfd_coff_reloc_link_order (bfd *output_bfd,
+ struct coff_final_link_info *flaginfo,
+ asection *output_section,
+ struct bfd_link_order *link_order)
{
reloc_howto_type *howto;
struct internal_reloc *irel;
if (howto == NULL)
{
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
if (link_order->u.reloc.p->addend != 0)
bfd_size_type size;
bfd_byte *buf;
bfd_reloc_status_type rstat;
- boolean ok;
+ bfd_boolean ok;
+ file_ptr loc;
size = bfd_get_reloc_size (howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL)
- return false;
+ return FALSE;
rstat = _bfd_relocate_contents (howto, output_bfd,
- link_order->u.reloc.p->addend, buf);
+ (bfd_vma) link_order->u.reloc.p->addend,\
+ buf);
switch (rstat)
{
case bfd_reloc_ok:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
- if (! ((*finfo->info->callbacks->reloc_overflow)
- (finfo->info,
+ if (! ((*flaginfo->info->callbacks->reloc_overflow)
+ (flaginfo->info, NULL,
(link_order->type == bfd_section_reloc_link_order
? bfd_section_name (output_bfd,
link_order->u.reloc.p->u.section)
(bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
{
free (buf);
- return false;
+ return FALSE;
}
break;
}
- ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
- (file_ptr) link_order->offset, size);
+ loc = link_order->offset * bfd_octets_per_byte (output_bfd);
+ ok = bfd_set_section_contents (output_bfd, output_section, buf,
+ loc, size);
free (buf);
if (! ok)
- return false;
+ return FALSE;
}
/* Store the reloc information in the right place. It will get
swapped and written out at the end of the final_link routine. */
-
- irel = (finfo->section_info[output_section->target_index].relocs
+ irel = (flaginfo->section_info[output_section->target_index].relocs
+ output_section->reloc_count);
- rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
+ rel_hash_ptr = (flaginfo->section_info[output_section->target_index].rel_hashes
+ output_section->reloc_count);
memset (irel, 0, sizeof (struct internal_reloc));
struct coff_link_hash_entry *h;
h = ((struct coff_link_hash_entry *)
- bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
+ bfd_wrapped_link_hash_lookup (output_bfd, flaginfo->info,
link_order->u.reloc.p->u.name,
- false, false, true));
+ FALSE, FALSE, TRUE));
if (h != NULL)
{
if (h->indx >= 0)
}
else
{
- if (! ((*finfo->info->callbacks->unattached_reloc)
- (finfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+ if (! ((*flaginfo->info->callbacks->unattached_reloc)
+ (flaginfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
(asection *) NULL, (bfd_vma) 0)))
- return false;
+ return FALSE;
irel->r_symndx = 0;
}
}
routines anyhow. r_extern is only used for ECOFF. */
/* FIXME: What is the right value for r_offset? Is zero OK? */
-
++output_section->reloc_count;
- return true;
+ return TRUE;
}
/* A basic reloc handling routine which may be used by processors with
simple relocs. */
-boolean
-_bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
- input_section, contents, relocs, syms,
- sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- struct internal_reloc *relocs;
- struct internal_syment *syms;
- asection **sections;
+bfd_boolean
+_bfd_coff_generic_relocate_section (bfd *output_bfd,
+ struct bfd_link_info *info,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ struct internal_reloc *relocs,
+ struct internal_syment *syms,
+ asection **sections)
{
struct internal_reloc *rel;
struct internal_reloc *relend;
|| (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
{
(*_bfd_error_handler)
- ("%s: illegal symbol index %ld in relocs",
- bfd_get_filename (input_bfd), symndx);
- return false;
+ ("%B: illegal symbol index %ld in relocs", input_bfd, symndx);
+ return FALSE;
}
else
- {
+ {
h = obj_coff_sym_hashes (input_bfd)[symndx];
sym = syms + symndx;
}
size of the symbol is included in the section contents, or it
is not. We assume that the size is not included, and force
the rtype_to_howto function to adjust the addend as needed. */
-
if (sym != NULL && sym->n_scnum != 0)
addend = - sym->n_value;
else
addend = 0;
-
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
sym, &addend);
if (howto == NULL)
- return false;
+ return FALSE;
- /* If we are doing a relocateable link, then we can just ignore
+ /* If we are doing a relocatable link, then we can just ignore
a PC relative reloc that is pcrel_offset. It will already
- have the correct value. If this is not a relocateable link,
+ have the correct value. If this is not a relocatable link,
then we should ignore the symbol value. */
if (howto->pc_relative && howto->pcrel_offset)
{
- if (info->relocateable)
+ if (info->relocatable)
continue;
if (sym != NULL && sym->n_scnum != 0)
addend += sym->n_value;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
+ /* Defined weak symbols are a GNU extension. */
asection *sec;
sec = h->root.u.def.section;
val = (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
- }
+ }
+
+ else if (h->root.type == bfd_link_hash_undefweak)
+ {
+ if (h->symbol_class == C_NT_WEAK && h->numaux == 1)
+ {
+ /* See _Microsoft Portable Executable and Common Object
+ File Format Specification_, section 5.5.3.
+ Note that weak symbols without aux records are a GNU
+ extension.
+ FIXME: All weak externals are treated as having
+ characteristic IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY (1).
+ These behave as per SVR4 ABI: A library member
+ will resolve a weak external only if a normal
+ external causes the library member to be linked.
+ See also linker.c: generic_link_check_archive_element. */
+ asection *sec;
+ struct coff_link_hash_entry *h2 =
+ h->auxbfd->tdata.coff_obj_data->sym_hashes[
+ h->aux->x_sym.x_tagndx.l];
+
+ if (!h2 || h2->root.type == bfd_link_hash_undefined)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = h2->root.u.def.section;
+ val = h2->root.u.def.value
+ + sec->output_section->vma + sec->output_offset;
+ }
+ }
+ else
+ /* This is a GNU extension. */
+ val = 0;
+ }
- else if (! info->relocateable)
+ else if (! info->relocatable)
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma)))
- return false;
+ rel->r_vaddr - input_section->vma, TRUE)))
+ return FALSE;
}
}
if (info->base_file)
{
- /* Emit a reloc if the backend thinks it needs it. */
+ /* Emit a reloc if the backend thinks it needs it. */
if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
{
/* Relocation to a symbol in a section which isn't
absolute. We output the address here to a file.
This file is then read by dlltool when generating the
reloc section. Note that the base file is not
- portable between systems. We write out a long here,
- and dlltool reads in a long. */
- long addr = (rel->r_vaddr
- - input_section->vma
- + input_section->output_offset
+ portable between systems. We write out a bfd_vma here,
+ and dlltool reads in a bfd_vma. */
+ bfd_vma addr = (rel->r_vaddr
+ - input_section->vma
+ + input_section->output_offset
+ input_section->output_section->vma);
if (coff_data (output_bfd)->pe)
addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
- if (fwrite (&addr, 1, sizeof (long), (FILE *) info->base_file)
- != sizeof (long))
+ if (fwrite (&addr, 1, sizeof (bfd_vma), (FILE *) info->base_file)
+ != sizeof (bfd_vma))
{
bfd_set_error (bfd_error_system_call);
- return false;
+ return FALSE;
}
}
}
-
+
rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents,
rel->r_vaddr - input_section->vma,
break;
case bfd_reloc_outofrange:
(*_bfd_error_handler)
- (_("%s: bad reloc address 0x%lx in section `%s'"),
- bfd_get_filename (input_bfd),
- (unsigned long) rel->r_vaddr,
- bfd_get_section_name (input_bfd, input_section));
- return false;
+ (_("%B: bad reloc address 0x%lx in section `%A'"),
+ input_bfd, input_section, (unsigned long) rel->r_vaddr);
+ return FALSE;
case bfd_reloc_overflow:
{
const char *name;
if (symndx == -1)
name = "*ABS*";
else if (h != NULL)
- name = h->root.root.string;
+ name = NULL;
else
{
name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
if (name == NULL)
- return false;
+ return FALSE;
}
if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_vaddr - input_section->vma)))
- return false;
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return FALSE;
}
}
}
- return true;
+ return TRUE;
}
-