/* linker.c -- BFD linker routines
- Copyright (C) 1993-2015 Free Software Foundation, Inc.
+ Copyright (C) 1993-2021 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
file at the end of <<NAME(aout,final_link)>>.
*/
-static bfd_boolean generic_link_add_object_symbols
- (bfd *, struct bfd_link_info *, bfd_boolean collect);
-static bfd_boolean generic_link_add_symbols
- (bfd *, struct bfd_link_info *, bfd_boolean);
-static bfd_boolean generic_link_check_archive_element_no_collect
+static bool generic_link_add_object_symbols
+ (bfd *, struct bfd_link_info *);
+static bool generic_link_check_archive_element
(bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
- bfd_boolean *);
-static bfd_boolean generic_link_check_archive_element_collect
- (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
- bfd_boolean *);
-static bfd_boolean generic_link_check_archive_element
- (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
- bfd_boolean *, bfd_boolean);
-static bfd_boolean generic_link_add_symbol_list
- (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **,
- bfd_boolean);
-static bfd_boolean generic_add_output_symbol
+ bool *);
+static bool generic_link_add_symbol_list
+ (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **);
+static bool generic_add_output_symbol
(bfd *, size_t *psymalloc, asymbol *);
-static bfd_boolean default_data_link_order
+static bool default_data_link_order
(bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
-static bfd_boolean default_indirect_link_order
+static bool default_indirect_link_order
(bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *,
- bfd_boolean);
+ bool);
/* The link hash table structure is defined in bfdlink.h. It provides
a base hash table which the backend specific hash tables are built
if (entry == NULL)
{
entry = (struct bfd_hash_entry *)
- bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
+ bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
if (entry == NULL)
return entry;
}
/* Initialize a link hash table. The BFD argument is the one
responsible for creating this table. */
-bfd_boolean
+bool
_bfd_link_hash_table_init
(struct bfd_link_hash_table *table,
bfd *abfd ATTRIBUTE_UNUSED,
const char *),
unsigned int entsize)
{
- bfd_boolean ret;
+ bool ret;
BFD_ASSERT (!abfd->is_linker_output && !abfd->link.hash);
table->undefs = NULL;
/* Arrange for destruction of this hash table on closing ABFD. */
table->hash_table_free = _bfd_generic_link_hash_table_free;
abfd->link.hash = table;
- abfd->is_linker_output = TRUE;
+ abfd->is_linker_output = true;
}
return ret;
}
/* Look up a symbol in a link hash table. If follow is TRUE, we
follow bfd_link_hash_indirect and bfd_link_hash_warning links to
- the real symbol. */
+ the real symbol.
+
+.{* Return TRUE if the symbol described by a linker hash entry H
+. is going to be absolute. Linker-script defined symbols can be
+. converted from absolute to section-relative ones late in the
+. link. Use this macro to correctly determine whether the symbol
+. will actually end up absolute in output. *}
+.#define bfd_is_abs_symbol(H) \
+. (((H)->type == bfd_link_hash_defined \
+. || (H)->type == bfd_link_hash_defweak) \
+. && bfd_is_abs_section ((H)->u.def.section) \
+. && !(H)->rel_from_abs)
+.
+*/
struct bfd_link_hash_entry *
bfd_link_hash_lookup (struct bfd_link_hash_table *table,
const char *string,
- bfd_boolean create,
- bfd_boolean copy,
- bfd_boolean follow)
+ bool create,
+ bool copy,
+ bool follow)
{
struct bfd_link_hash_entry *ret;
+ if (table == NULL || string == NULL)
+ return NULL;
+
ret = ((struct bfd_link_hash_entry *)
bfd_hash_lookup (&table->table, string, create, copy));
bfd_wrapped_link_hash_lookup (bfd *abfd,
struct bfd_link_info *info,
const char *string,
- bfd_boolean create,
- bfd_boolean copy,
- bfd_boolean follow)
+ bool create,
+ bool copy,
+ bool follow)
{
- bfd_size_type amt;
+ size_t amt;
if (info->wrap_hash != NULL)
{
#undef WRAP
#define WRAP "__wrap_"
- if (bfd_hash_lookup (info->wrap_hash, l, FALSE, FALSE) != NULL)
+ if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL)
{
char *n;
struct bfd_link_hash_entry *h;
/* This symbol is being wrapped. We want to replace all
- references to SYM with references to __wrap_SYM. */
+ references to SYM with references to __wrap_SYM. */
amt = strlen (l) + sizeof WRAP + 1;
n = (char *) bfd_malloc (amt);
n[1] = '\0';
strcat (n, WRAP);
strcat (n, l);
- h = bfd_link_hash_lookup (info->hash, n, create, TRUE, follow);
+ h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
free (n);
return h;
}
#define REAL "__real_"
if (*l == '_'
- && CONST_STRNEQ (l, REAL)
+ && startswith (l, REAL)
&& bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1,
- FALSE, FALSE) != NULL)
+ false, false) != NULL)
{
char *n;
struct bfd_link_hash_entry *h;
/* This is a reference to __real_SYM, where SYM is being
- wrapped. We want to replace all references to __real_SYM
- with references to SYM. */
+ wrapped. We want to replace all references to __real_SYM
+ with references to SYM. */
amt = strlen (l + sizeof REAL - 1) + 2;
n = (char *) bfd_malloc (amt);
n[0] = prefix;
n[1] = '\0';
strcat (n, l + sizeof REAL - 1);
- h = bfd_link_hash_lookup (info->hash, n, create, TRUE, follow);
+ h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
free (n);
return h;
}
|| *l == info->wrap_char)
++l;
- if (CONST_STRNEQ (l, WRAP))
+ if (startswith (l, WRAP))
{
l += sizeof WRAP - 1;
- if (bfd_hash_lookup (info->wrap_hash, l, FALSE, FALSE) != NULL)
+ if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL)
{
char save = 0;
if (l - (sizeof WRAP - 1) != h->root.string)
save = *l;
*(char *) l = *h->root.string;
}
- h = bfd_link_hash_lookup (info->hash, l, FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (info->hash, l, false, false, false);
if (save)
*(char *) l = save;
}
/* Traverse a generic link hash table. Differs from bfd_hash_traverse
in the treatment of warning symbols. When warning symbols are
created they replace the real symbol, so you don't get to see the
- real symbol in a bfd_hash_travere. This traversal calls func with
+ real symbol in a bfd_hash_traverse. This traversal calls func with
the real symbol. */
void
bfd_link_hash_traverse
(struct bfd_link_hash_table *htab,
- bfd_boolean (*func) (struct bfd_link_hash_entry *, void *),
+ bool (*func) (struct bfd_link_hash_entry *, void *),
void *info)
{
unsigned int i;
/* Set local fields. */
ret = (struct generic_link_hash_entry *) entry;
- ret->written = FALSE;
+ ret->written = false;
ret->sym = NULL;
}
_bfd_generic_link_hash_table_create (bfd *abfd)
{
struct generic_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct generic_link_hash_table);
+ size_t amt = sizeof (struct generic_link_hash_table);
ret = (struct generic_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
bfd_hash_table_free (&ret->root.table);
free (ret);
obfd->link.hash = NULL;
- obfd->is_linker_output = FALSE;
+ obfd->is_linker_output = false;
}
/* Grab the symbols for an object file when doing a generic link. We
the hash table pointing to different instances of the symbol
structure. */
-bfd_boolean
+bool
bfd_generic_link_read_symbols (bfd *abfd)
{
if (bfd_get_outsymbols (abfd) == NULL)
symsize = bfd_get_symtab_upper_bound (abfd);
if (symsize < 0)
- return FALSE;
- bfd_get_outsymbols (abfd) = (struct bfd_symbol **) bfd_alloc (abfd,
- symsize);
+ return false;
+ abfd->outsymbols = bfd_alloc (abfd, symsize);
if (bfd_get_outsymbols (abfd) == NULL && symsize != 0)
- return FALSE;
+ return false;
symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd));
if (symcount < 0)
- return FALSE;
- bfd_get_symcount (abfd) = symcount;
+ return false;
+ abfd->symcount = symcount;
}
- return TRUE;
+ return true;
}
\f
-/* Generic function to add symbols to from an object file to the
- global hash table. This version does not automatically collect
- constructors by name. */
-
-bfd_boolean
-_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
-{
- return generic_link_add_symbols (abfd, info, FALSE);
-}
-
-/* Generic function to add symbols from an object file to the global
- hash table. This version automatically collects constructors by
- name, as the collect2 program does. It should be used for any
- target which does not provide some other mechanism for setting up
- constructors and destructors; these are approximately those targets
- for which gcc uses collect2 and do not support stabs. */
-
-bfd_boolean
-_bfd_generic_link_add_symbols_collect (bfd *abfd, struct bfd_link_info *info)
-{
- return generic_link_add_symbols (abfd, info, TRUE);
-}
-
/* Indicate that we are only retrieving symbol values from this
section. We want the symbols to act as though the values in the
file are absolute. */
{
}
-/* Add symbols from an object file to the global hash table. */
+/* Generic function to add symbols from an object file to the
+ global hash table. */
-static bfd_boolean
-generic_link_add_symbols (bfd *abfd,
- struct bfd_link_info *info,
- bfd_boolean collect)
+bool
+_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
{
- bfd_boolean ret;
+ bool ret;
switch (bfd_get_format (abfd))
{
case bfd_object:
- ret = generic_link_add_object_symbols (abfd, info, collect);
+ ret = generic_link_add_object_symbols (abfd, info);
break;
case bfd_archive:
ret = (_bfd_generic_link_add_archive_symbols
- (abfd, info,
- (collect
- ? generic_link_check_archive_element_collect
- : generic_link_check_archive_element_no_collect)));
+ (abfd, info, generic_link_check_archive_element));
break;
default:
bfd_set_error (bfd_error_wrong_format);
- ret = FALSE;
+ ret = false;
}
return ret;
/* Add symbols from an object file to the global hash table. */
-static bfd_boolean
+static bool
generic_link_add_object_symbols (bfd *abfd,
- struct bfd_link_info *info,
- bfd_boolean collect)
+ struct bfd_link_info *info)
{
bfd_size_type symcount;
struct bfd_symbol **outsyms;
if (!bfd_generic_link_read_symbols (abfd))
- return FALSE;
+ return false;
symcount = _bfd_generic_link_get_symcount (abfd);
outsyms = _bfd_generic_link_get_symbols (abfd);
- return generic_link_add_symbol_list (abfd, info, symcount, outsyms, collect);
+ return generic_link_add_symbol_list (abfd, info, symcount, outsyms);
}
\f
/* Generic function to add symbols from an archive file to the global
those symbols instead if it does so. CHECKFN should only return
FALSE if some sort of error occurs. */
-bfd_boolean
+bool
_bfd_generic_link_add_archive_symbols
(bfd *abfd,
struct bfd_link_info *info,
- bfd_boolean (*checkfn) (bfd *, struct bfd_link_info *,
- struct bfd_link_hash_entry *, const char *,
- bfd_boolean *))
+ bool (*checkfn) (bfd *, struct bfd_link_info *,
+ struct bfd_link_hash_entry *, const char *, bool *))
{
- bfd_boolean loop;
+ bool loop;
bfd_size_type amt;
unsigned char *included;
{
/* An empty archive is a special case. */
if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
- return TRUE;
+ return true;
bfd_set_error (bfd_error_no_armap);
- return FALSE;
+ return false;
}
amt = bfd_ardata (abfd)->symdef_count;
if (amt == 0)
- return TRUE;
+ return true;
amt *= sizeof (*included);
included = (unsigned char *) bfd_zmalloc (amt);
if (included == NULL)
- return FALSE;
+ return false;
do
{
carsym *arsym;
unsigned int indx;
file_ptr last_ar_offset = -1;
- bfd_boolean needed = FALSE;
+ bool needed = false;
bfd *element = NULL;
- loop = FALSE;
+ loop = false;
arsyms = bfd_ardata (abfd)->symdefs;
arsym_end = arsyms + bfd_ardata (abfd)->symdef_count;
for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++)
continue;
}
+ if (arsym->name == NULL)
+ goto error_return;
+
h = bfd_link_hash_lookup (info->hash, arsym->name,
- FALSE, FALSE, TRUE);
+ false, false, true);
if (h == NULL
&& info->pei386_auto_import
- && CONST_STRNEQ (arsym->name, "__imp_"))
+ && startswith (arsym->name, "__imp_"))
h = bfd_link_hash_lookup (info->hash, arsym->name + 6,
- FALSE, FALSE, TRUE);
+ false, false, true);
if (h == NULL)
continue;
while (arsyms[mark].file_offset == last_ar_offset);
if (undefs_tail != info->hash->undefs_tail)
- loop = TRUE;
+ loop = true;
}
}
} while (loop);
free (included);
- return TRUE;
+ return true;
error_return:
free (included);
- return FALSE;
+ return false;
}
\f
-/* See if we should include an archive element. This version is used
- when we do not want to automatically collect constructors based on
- the symbol name, presumably because we have some other mechanism
- for finding them. */
+/* See if we should include an archive element. */
-static bfd_boolean
-generic_link_check_archive_element_no_collect (bfd *abfd,
- struct bfd_link_info *info,
- struct bfd_link_hash_entry *h,
- const char *name,
- bfd_boolean *pneeded)
-{
- return generic_link_check_archive_element (abfd, info, h, name, pneeded,
- FALSE);
-}
-
-/* See if we should include an archive element. This version is used
- when we want to automatically collect constructors based on the
- symbol name, as collect2 does. */
-
-static bfd_boolean
-generic_link_check_archive_element_collect (bfd *abfd,
- struct bfd_link_info *info,
- struct bfd_link_hash_entry *h,
- const char *name,
- bfd_boolean *pneeded)
-{
- return generic_link_check_archive_element (abfd, info, h, name, pneeded,
- TRUE);
-}
-
-/* See if we should include an archive element. Optionally collect
- constructors. */
-
-static bfd_boolean
+static bool
generic_link_check_archive_element (bfd *abfd,
struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
const char *name ATTRIBUTE_UNUSED,
- bfd_boolean *pneeded,
- bfd_boolean collect)
+ bool *pneeded)
{
asymbol **pp, **ppend;
- *pneeded = FALSE;
+ *pneeded = false;
if (!bfd_generic_link_read_symbols (abfd))
- return FALSE;
+ return false;
pp = _bfd_generic_link_get_symbols (abfd);
ppend = pp + _bfd_generic_link_get_symcount (abfd);
symbol (type bfd_link_hash_undefweak) is not considered to be
a reference when pulling files out of an archive. See the
SVR4 ABI, p. 4-27. */
- h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), FALSE,
- FALSE, TRUE);
+ h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
+ false, true);
if (h == NULL
|| (h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common))
/* P is not a common symbol, or an undefined reference was
created from outside BFD such as from a linker -u option.
This object file defines the symbol, so pull it in. */
- *pneeded = TRUE;
+ *pneeded = true;
if (!(*info->callbacks
->add_archive_element) (info, abfd, bfd_asymbol_name (p),
&abfd))
- return FALSE;
+ return false;
/* Potentially, the add_archive_element hook may have set a
substitute BFD for us. */
- return generic_link_add_object_symbols (abfd, info, collect);
+ return bfd_link_add_symbols (abfd, info);
}
/* P is a common symbol. */
bfd_hash_allocate (&info->hash->table,
sizeof (struct bfd_link_hash_common_entry));
if (h->u.c.p == NULL)
- return FALSE;
+ return false;
size = bfd_asymbol_value (p);
h->u.c.size = size;
}
/* This archive element is not needed. */
- return TRUE;
+ return true;
}
/* Add the symbols from an object file to the global hash table. ABFD
is the object file. INFO is the linker information. SYMBOL_COUNT
- is the number of symbols. SYMBOLS is the list of symbols. COLLECT
- is TRUE if constructors should be automatically collected by name
- as is done by collect2. */
+ is the number of symbols. SYMBOLS is the list of symbols. */
-static bfd_boolean
+static bool
generic_link_add_symbol_list (bfd *abfd,
struct bfd_link_info *info,
bfd_size_type symbol_count,
- asymbol **symbols,
- bfd_boolean collect)
+ asymbol **symbols)
{
asymbol **pp, **ppend;
| BSF_GLOBAL
| BSF_CONSTRUCTOR
| BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (p))
- || bfd_is_com_section (bfd_get_section (p))
- || bfd_is_ind_section (bfd_get_section (p)))
+ || bfd_is_und_section (bfd_asymbol_section (p))
+ || bfd_is_com_section (bfd_asymbol_section (p))
+ || bfd_is_ind_section (bfd_asymbol_section (p)))
{
const char *name;
const char *string;
bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, name, p->flags, bfd_get_section (p),
- p->value, string, FALSE, collect, &bh)))
- return FALSE;
+ (info, abfd, name, p->flags, bfd_asymbol_section (p),
+ p->value, string, false, false, &bh)))
+ return false;
h = (struct generic_link_hash_entry *) bh;
/* If this is a constructor symbol, and the linker didn't do
- anything with it, then we want to just pass the symbol
- through to the output file. This will happen when
- linking with -r. */
+ anything with it, then we want to just pass the symbol
+ through to the output file. This will happen when
+ linking with -r. */
if ((p->flags & BSF_CONSTRUCTOR) != 0
&& (h == NULL || h->root.type == bfd_link_hash_new))
{
if (info->output_bfd->xvec == abfd->xvec)
{
if (h->sym == NULL
- || (! bfd_is_und_section (bfd_get_section (p))
- && (! bfd_is_com_section (bfd_get_section (p))
- || bfd_is_und_section (bfd_get_section (h->sym)))))
+ || (! bfd_is_und_section (bfd_asymbol_section (p))
+ && (! bfd_is_com_section (bfd_asymbol_section (p))
+ || bfd_is_und_section (bfd_asymbol_section (h->sym)))))
{
h->sym = p;
/* BSF_OLD_COMMON is a hack to support COFF reloc
reading, and it should go away when the COFF
linker is switched to the new version. */
- if (bfd_is_com_section (bfd_get_section (p)))
+ if (bfd_is_com_section (bfd_asymbol_section (p)))
p->flags |= BSF_OLD_COMMON;
}
}
}
}
- return TRUE;
+ return true;
}
\f
/* We use a state table to deal with adding symbols from an object
static const enum link_action link_action[8][8] =
{
/* current\prev new undef undefw def defw com indr warn */
- /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC },
+ /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC },
/* UNDEFW_ROW */ {WEAK, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC },
- /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE },
- /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
+ /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MIND, CYCLE },
+ /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
/* COMMON_ROW */ {COM, COM, COM, CREF, COM, BIG, REFC, WARNC },
/* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE },
/* WARN_ROW */ {MWARN, WARN, WARN, WARN, WARN, WARN, WARN, NOACT },
entry; if *HASHP is not NULL, the caller has already looked up
the hash table entry, and stored it in *HASHP. */
-bfd_boolean
+bool
_bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
bfd *abfd,
const char *name,
asection *section,
bfd_vma value,
const char *string,
- bfd_boolean copy,
- bfd_boolean collect,
+ bool copy,
+ bool collect,
struct bfd_link_hash_entry **hashp)
{
enum link_row row;
struct bfd_link_hash_entry *h;
struct bfd_link_hash_entry *inh = NULL;
- bfd_boolean cycle;
+ bool cycle;
BFD_ASSERT (section != NULL);
/* Create the indirect symbol here. This is for the benefit of
the plugin "notice" function.
STRING is the name of the symbol we want to indirect to. */
- inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
- copy, FALSE);
+ inh = bfd_wrapped_link_hash_lookup (abfd, info, string, true,
+ copy, false);
if (inh == NULL)
- return FALSE;
+ return false;
}
else if ((flags & BSF_WARNING) != 0)
row = WARN_ROW;
else if (bfd_is_com_section (section))
{
row = COMMON_ROW;
- if (strcmp (name, "__gnu_lto_slim") == 0)
- (*_bfd_error_handler)
- (_("%s: plugin needed to handle lto object"),
- bfd_get_filename (abfd));
+ if (!bfd_link_relocatable (info)
+ && name[0] == '_'
+ && name[1] == '_'
+ && strcmp (name + (name[2] == '_'), "__gnu_lto_slim") == 0)
+ _bfd_error_handler
+ (_("%pB: plugin needed to handle lto object"), abfd);
}
else
row = DEF_ROW;
else
{
if (row == UNDEF_ROW || row == UNDEFW_ROW)
- h = bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, copy, FALSE);
+ h = bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false);
else
- h = bfd_link_hash_lookup (info->hash, name, TRUE, copy, FALSE);
+ h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
if (h == NULL)
{
if (hashp != NULL)
*hashp = NULL;
- return FALSE;
+ return false;
}
}
if (info->notice_all
|| (info->notice_hash != NULL
- && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
+ && bfd_hash_lookup (info->notice_hash, name, false, false) != NULL))
{
if (! (*info->callbacks->notice) (info, h, inh,
abfd, section, value, flags))
- return FALSE;
+ return false;
}
if (hashp != NULL)
do
{
enum link_action action;
-
- cycle = FALSE;
- action = link_action[(int) row][(int) h->type];
+ int prev;
+
+ prev = h->type;
+ /* Treat symbols defined by early linker script pass as undefined. */
+ if (h->ldscript_def)
+ prev = bfd_link_hash_undefined;
+ cycle = false;
+ action = link_action[(int) row][prev];
switch (action)
{
case FAIL:
/* We have found a definition for a symbol which was
previously common. */
BFD_ASSERT (h->type == bfd_link_hash_common);
- if (! ((*info->callbacks->multiple_common)
- (info, h, abfd, bfd_link_hash_defined, 0)))
- return FALSE;
+ (*info->callbacks->multiple_common) (info, h, abfd,
+ bfd_link_hash_defined, 0);
/* Fall through. */
case DEF:
case DEFW:
h->u.def.section = section;
h->u.def.value = value;
h->linker_def = 0;
+ h->ldscript_def = 0;
/* If we have been asked to, we act like collect2 and
identify all functions that might be global
s = name + 1;
while (*s == '_')
++s;
- if (s[0] == 'G' && CONST_STRNEQ (s, CONS_PREFIX))
+ if (s[0] == 'G' && startswith (s, CONS_PREFIX))
{
char c;
&& s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
{
/* If this is a definition of a symbol which
- was previously weakly defined, we are in
- trouble. We have already added a
- constructor entry for the weak defined
- symbol, and now we are trying to add one
- for the new symbol. Fortunately, this case
- should never arise in practice. */
+ was previously weakly defined, we are in
+ trouble. We have already added a
+ constructor entry for the weak defined
+ symbol, and now we are trying to add one
+ for the new symbol. Fortunately, this case
+ should never arise in practice. */
if (oldtype == bfd_link_hash_defweak)
abort ();
- if (! ((*info->callbacks->constructor)
- (info, c == 'I',
- h->root.string, abfd, section, value)))
- return FALSE;
+ (*info->callbacks->constructor) (info, c == 'I',
+ h->root.string, abfd,
+ section, value);
}
}
}
bfd_hash_allocate (&info->hash->table,
sizeof (struct bfd_link_hash_common_entry));
if (h->u.c.p == NULL)
- return FALSE;
+ return false;
h->u.c.size = value;
/* Select a default alignment based on the size. This may
- be overridden by the caller. */
+ be overridden by the caller. */
{
unsigned int power;
}
/* The section of a common symbol is only used if the common
- symbol is actually allocated. It basically provides a
- hook for the linker script to decide which output section
- the common symbols should be put in. In most cases, the
- section of a common symbol will be bfd_com_section_ptr,
- the code here will choose a common symbol section named
- "COMMON", and the linker script will contain *(COMMON) in
- the appropriate place. A few targets use separate common
- sections for small symbols, and they require special
- handling. */
+ symbol is actually allocated. It basically provides a
+ hook for the linker script to decide which output section
+ the common symbols should be put in. In most cases, the
+ section of a common symbol will be bfd_com_section_ptr,
+ the code here will choose a common symbol section named
+ "COMMON", and the linker script will contain *(COMMON) in
+ the appropriate place. A few targets use separate common
+ sections for small symbols, and they require special
+ handling. */
if (section == bfd_com_section_ptr)
{
h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
else
h->u.c.p->section = section;
h->linker_def = 0;
+ h->ldscript_def = 0;
break;
case REF:
already had a common definition. Use the maximum of the
two sizes, and use the section required by the larger symbol. */
BFD_ASSERT (h->type == bfd_link_hash_common);
- if (! ((*info->callbacks->multiple_common)
- (info, h, abfd, bfd_link_hash_common, value)))
- return FALSE;
+ (*info->callbacks->multiple_common) (info, h, abfd,
+ bfd_link_hash_common, value);
if (value > h->u.c.size)
{
unsigned int power;
case CREF:
/* We have found a common definition for a symbol which
was already defined. */
- if (! ((*info->callbacks->multiple_common)
- (info, h, abfd, bfd_link_hash_common, value)))
- return FALSE;
+ (*info->callbacks->multiple_common) (info, h, abfd,
+ bfd_link_hash_common, value);
break;
case MIND:
/* Multiple indirect symbols. This is OK if they both point
to the same symbol. */
+ if (h->u.i.link->type == bfd_link_hash_defweak)
+ {
+ /* It is also OK to redefine a symbol that indirects to
+ a weak definition. So for sym@ver -> sym@@ver where
+ sym@@ver is weak and we have a new strong sym@ver,
+ redefine sym@@ver. Of course if there exists
+ sym -> sym@@ver then this also redefines sym. */
+ h = h->u.i.link;
+ cycle = true;
+ break;
+ }
if (strcmp (h->u.i.link->root.string, string) == 0)
break;
/* Fall through. */
case MDEF:
/* Handle a multiple definition. */
- if (! ((*info->callbacks->multiple_definition)
- (info, h, abfd, section, value)))
- return FALSE;
+ (*info->callbacks->multiple_definition) (info, h,
+ abfd, section, value);
break;
case CIND:
/* Create an indirect symbol from an existing common symbol. */
BFD_ASSERT (h->type == bfd_link_hash_common);
- if (! ((*info->callbacks->multiple_common)
- (info, h, abfd, bfd_link_hash_indirect, 0)))
- return FALSE;
+ (*info->callbacks->multiple_common) (info, h, abfd,
+ bfd_link_hash_indirect, 0);
/* Fall through. */
case IND:
if (inh->type == bfd_link_hash_indirect
&& inh->u.i.link == h)
{
- (*_bfd_error_handler)
- (_("%B: indirect symbol `%s' to `%s' is a loop"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: indirect symbol `%s' to `%s' is a loop"),
abfd, name, string);
bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
+ return false;
}
if (inh->type == bfd_link_hash_new)
{
/* ??? If inh->type == bfd_link_hash_undefweak this
converts inh to bfd_link_hash_undefined. */
row = UNDEF_ROW;
- cycle = TRUE;
+ cycle = true;
}
h->type = bfd_link_hash_indirect;
case SET:
/* Add an entry to a set. */
- if (! (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,
- abfd, section, value))
- return FALSE;
+ (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,
+ abfd, section, value);
break;
case WARNC:
if (h->u.i.warning != NULL
&& (abfd->flags & BFD_PLUGIN) == 0)
{
- if (! (*info->callbacks->warning) (info, h->u.i.warning,
- h->root.string, abfd,
- NULL, 0))
- return FALSE;
+ (*info->callbacks->warning) (info, h->u.i.warning,
+ h->root.string, abfd, NULL, 0);
/* Only issue a warning once. */
h->u.i.warning = NULL;
}
case CYCLE:
/* Try again with the referenced symbol. */
h = h->u.i.link;
- cycle = TRUE;
+ cycle = true;
break;
case REFC:
if (h->u.undef.next == NULL && info->hash->undefs_tail != h)
h->u.undef.next = h;
h = h->u.i.link;
- cycle = TRUE;
+ cycle = true;
break;
case WARN:
otherwise add a warning. */
if ((!info->lto_plugin_active
&& (h->u.undef.next != NULL || info->hash->undefs_tail == h))
- || h->non_ir_ref)
+ || h->non_ir_ref_regular
+ || h->non_ir_ref_dynamic)
{
- if (! (*info->callbacks->warning) (info, string, h->root.string,
- hash_entry_bfd (h), NULL, 0))
- return FALSE;
+ (*info->callbacks->warning) (info, string, h->root.string,
+ hash_entry_bfd (h), NULL, 0);
break;
}
/* Fall through. */
((*info->hash->table.newfunc)
(NULL, &info->hash->table, h->root.string)));
if (sub == NULL)
- return FALSE;
+ return false;
*sub = *h;
sub->type = bfd_link_hash_warning;
sub->u.i.link = h;
w = (char *) bfd_hash_allocate (&info->hash->table, len);
if (w == NULL)
- return FALSE;
+ return false;
memcpy (w, string, len);
sub->u.i.warning = w;
}
}
while (cycle);
- return TRUE;
+ return true;
}
\f
/* Generic final link routine. */
-bfd_boolean
+bool
_bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
{
bfd *sub;
size_t outsymalloc;
struct generic_write_global_symbol_info wginfo;
- bfd_get_outsymbols (abfd) = NULL;
- bfd_get_symcount (abfd) = 0;
+ abfd->outsymbols = NULL;
+ abfd->symcount = 0;
outsymalloc = 0;
/* Mark all sections which will be included in the output file. */
for (o = abfd->sections; o != NULL; o = o->next)
for (p = o->map_head.link_order; p != NULL; p = p->next)
if (p->type == bfd_indirect_link_order)
- p->u.indirect.section->linker_mark = TRUE;
+ p->u.indirect.section->linker_mark = true;
/* Build the output symbol table. */
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
- return FALSE;
+ return false;
/* Accumulate the global symbols. */
wginfo.info = info;
shouldn't really need one, since we have SYMCOUNT, but some old
code still expects one. */
if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
- return FALSE;
+ return false;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
/* Allocate space for the output relocs for each section. */
for (o = abfd->sections; o != NULL; o = o->next)
relsize = bfd_get_reloc_upper_bound (input_bfd,
input_section);
if (relsize < 0)
- return FALSE;
+ return false;
relocs = (arelent **) bfd_malloc (relsize);
if (!relocs && relsize != 0)
- return FALSE;
+ return false;
symbols = _bfd_generic_link_get_symbols (input_bfd);
reloc_count = bfd_canonicalize_reloc (input_bfd,
input_section,
symbols);
free (relocs);
if (reloc_count < 0)
- return FALSE;
+ return false;
BFD_ASSERT ((unsigned long) reloc_count
== input_section->reloc_count);
o->reloc_count += reloc_count;
amt *= sizeof (arelent *);
o->orelocation = (struct reloc_cache_entry **) bfd_alloc (abfd, amt);
if (!o->orelocation)
- return FALSE;
+ return false;
o->flags |= SEC_RELOC;
/* Reset the count so that it can be used as an index
when putting in the output relocs. */
case bfd_section_reloc_link_order:
case bfd_symbol_reloc_link_order:
if (! _bfd_generic_reloc_link_order (abfd, info, o, p))
- return FALSE;
+ return false;
break;
case bfd_indirect_link_order:
- if (! default_indirect_link_order (abfd, info, o, p, TRUE))
- return FALSE;
+ if (! default_indirect_link_order (abfd, info, o, p, true))
+ return false;
break;
default:
if (! _bfd_default_link_order (abfd, info, o, p))
- return FALSE;
+ return false;
break;
}
}
}
- return TRUE;
+ return true;
}
/* Add an output symbol to the output BFD. */
-static bfd_boolean
+static bool
generic_add_output_symbol (bfd *output_bfd, size_t *psymalloc, asymbol *sym)
{
if (bfd_get_symcount (output_bfd) >= *psymalloc)
amt *= sizeof (asymbol *);
newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
if (newsyms == NULL)
- return FALSE;
- bfd_get_outsymbols (output_bfd) = newsyms;
+ return false;
+ output_bfd->outsymbols = newsyms;
}
- bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym;
+ output_bfd->outsymbols[output_bfd->symcount] = sym;
if (sym != NULL)
- ++ bfd_get_symcount (output_bfd);
+ ++output_bfd->symcount;
- return TRUE;
+ return true;
}
/* Handle the symbols for an input BFD. */
-bfd_boolean
+bool
_bfd_generic_link_output_symbols (bfd *output_bfd,
bfd *input_bfd,
struct bfd_link_info *info,
asymbol **sym_end;
if (!bfd_generic_link_read_symbols (input_bfd))
- return FALSE;
+ return false;
/* Create a filename symbol if we are supposed to. */
if (info->create_object_symbols_section != NULL)
newsym = bfd_make_empty_symbol (input_bfd);
if (!newsym)
- return FALSE;
- newsym->name = input_bfd->filename;
+ return false;
+ newsym->name = bfd_get_filename (input_bfd);
newsym->value = 0;
newsym->flags = BSF_LOCAL | BSF_FILE;
newsym->section = sec;
if (! generic_add_output_symbol (output_bfd, psymalloc,
newsym))
- return FALSE;
+ return false;
break;
}
{
asymbol *sym;
struct generic_link_hash_entry *h;
- bfd_boolean output;
+ bool output;
h = NULL;
sym = *sym_ptr;
| BSF_GLOBAL
| BSF_CONSTRUCTOR
| BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (sym))
- || bfd_is_com_section (bfd_get_section (sym))
- || bfd_is_ind_section (bfd_get_section (sym)))
+ || bfd_is_und_section (bfd_asymbol_section (sym))
+ || bfd_is_com_section (bfd_asymbol_section (sym))
+ || bfd_is_ind_section (bfd_asymbol_section (sym)))
{
if (sym->udata.p != NULL)
h = (struct generic_link_hash_entry *) sym->udata.p;
else if ((sym->flags & BSF_CONSTRUCTOR) != 0)
{
/* This case normally means that the main linker code
- deliberately ignored this constructor symbol. We
- should just pass it through. This will screw up if
- the constructor symbol is from a different,
- non-generic, object file format, but the case will
- only arise when linking with -r, which will probably
- fail anyhow, since there will be no way to represent
- the relocs in the output format being used. */
+ deliberately ignored this constructor symbol. We
+ should just pass it through. This will screw up if
+ the constructor symbol is from a different,
+ non-generic, object file format, but the case will
+ only arise when linking with -r, which will probably
+ fail anyhow, since there will be no way to represent
+ the relocs in the output format being used. */
h = NULL;
}
- else if (bfd_is_und_section (bfd_get_section (sym)))
+ else if (bfd_is_und_section (bfd_asymbol_section (sym)))
h = ((struct generic_link_hash_entry *)
bfd_wrapped_link_hash_lookup (output_bfd, info,
bfd_asymbol_name (sym),
- FALSE, FALSE, TRUE));
+ false, false, true));
else
h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
bfd_asymbol_name (sym),
- FALSE, FALSE, TRUE);
+ false, false, true);
if (h != NULL)
{
}
}
- /* This switch is straight from the old code in
- write_file_locals in ldsym.c. */
- if (info->strip == strip_all
- || (info->strip == strip_some
- && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
- FALSE, FALSE) == NULL))
- output = FALSE;
- else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
+ if ((sym->flags & BSF_KEEP) == 0
+ && (info->strip == strip_all
+ || (info->strip == strip_some
+ && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
+ false, false) == NULL)))
+ output = false;
+ else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
{
/* If this symbol is marked as occurring now, rather
than at the end, output it now. This is used for
better way. */
if (bfd_asymbol_bfd (sym) == input_bfd
&& (sym->flags & BSF_NOT_AT_END) != 0)
- output = TRUE;
+ output = true;
else
- output = FALSE;
+ output = false;
}
+ else if ((sym->flags & BSF_KEEP) != 0)
+ output = true;
else if (bfd_is_ind_section (sym->section))
- output = FALSE;
+ output = false;
else if ((sym->flags & BSF_DEBUGGING) != 0)
{
if (info->strip == strip_none)
- output = TRUE;
+ output = true;
else
- output = FALSE;
+ output = false;
}
else if (bfd_is_und_section (sym->section)
|| bfd_is_com_section (sym->section))
- output = FALSE;
+ output = false;
else if ((sym->flags & BSF_LOCAL) != 0)
{
if ((sym->flags & BSF_WARNING) != 0)
- output = FALSE;
+ output = false;
else
{
switch (info->discard)
{
default:
case discard_all:
- output = FALSE;
+ output = false;
break;
case discard_sec_merge:
- output = TRUE;
- if (info->relocatable
+ output = true;
+ if (bfd_link_relocatable (info)
|| ! (sym->section->flags & SEC_MERGE))
break;
/* FALLTHROUGH */
case discard_l:
if (bfd_is_local_label (input_bfd, sym))
- output = FALSE;
+ output = false;
else
- output = TRUE;
+ output = true;
break;
case discard_none:
- output = TRUE;
+ output = true;
break;
}
}
else if ((sym->flags & BSF_CONSTRUCTOR))
{
if (info->strip != strip_all)
- output = TRUE;
+ output = true;
else
- output = FALSE;
+ output = false;
}
else if (sym->flags == 0
&& (sym->section->owner->flags & BFD_PLUGIN) != 0)
/* LTO doesn't set symbol information. We get here with the
generic linker for a symbol that was "common" but no longer
needs to be global. */
- output = FALSE;
+ output = false;
else
abort ();
if (!bfd_is_abs_section (sym->section)
&& bfd_section_removed_from_list (output_bfd,
sym->section->output_section))
- output = FALSE;
+ output = false;
if (output)
{
if (! generic_add_output_symbol (output_bfd, psymalloc, sym))
- return FALSE;
+ return false;
if (h != NULL)
- h->written = TRUE;
+ h->written = true;
}
}
- return TRUE;
+ return true;
}
/* Set the section and value of a generic BFD symbol based on a linker
break;
case bfd_link_hash_new:
/* This can happen when a constructor symbol is seen but we are
- not building constructors. */
+ not building constructors. */
if (sym->section != NULL)
{
BFD_ASSERT ((sym->flags & BSF_CONSTRUCTOR) != 0);
/* Write out a global symbol, if it hasn't already been written out.
This is called for each symbol in the hash table. */
-bfd_boolean
+bool
_bfd_generic_link_write_global_symbol (struct generic_link_hash_entry *h,
void *data)
{
asymbol *sym;
if (h->written)
- return TRUE;
+ return true;
- h->written = TRUE;
+ h->written = true;
if (wginfo->info->strip == strip_all
|| (wginfo->info->strip == strip_some
&& bfd_hash_lookup (wginfo->info->keep_hash, h->root.root.string,
- FALSE, FALSE) == NULL))
- return TRUE;
+ false, false) == NULL))
+ return true;
if (h->sym != NULL)
sym = h->sym;
{
sym = bfd_make_empty_symbol (wginfo->output_bfd);
if (!sym)
- return FALSE;
+ return false;
sym->name = h->root.root.string;
sym->flags = 0;
}
abort ();
}
- return TRUE;
+ return true;
}
/* Create a relocation. */
-bfd_boolean
+bool
_bfd_generic_reloc_link_order (bfd *abfd,
struct bfd_link_info *info,
asection *sec,
{
arelent *r;
- if (! info->relocatable)
+ if (! bfd_link_relocatable (info))
abort ();
if (sec->orelocation == NULL)
abort ();
r = (arelent *) bfd_alloc (abfd, sizeof (arelent));
if (r == NULL)
- return FALSE;
+ return false;
r->address = link_order->offset;
r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
if (r->howto == 0)
{
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
/* Get the symbol to use for the relocation. */
h = ((struct generic_link_hash_entry *)
bfd_wrapped_link_hash_lookup (abfd, info,
link_order->u.reloc.p->u.name,
- FALSE, FALSE, TRUE));
+ false, false, true));
if (h == NULL
|| ! h->written)
{
- if (! ((*info->callbacks->unattached_reloc)
- (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
- return FALSE;
+ (*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, NULL, NULL, 0);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
r->sym_ptr_ptr = &h->sym;
}
bfd_size_type size;
bfd_reloc_status_type rstat;
bfd_byte *buf;
- bfd_boolean ok;
+ bool ok;
file_ptr loc;
size = bfd_get_reloc_size (r->howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL && size != 0)
- return FALSE;
+ return false;
rstat = _bfd_relocate_contents (r->howto, abfd,
(bfd_vma) link_order->u.reloc.p->addend,
buf);
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
- if (! ((*info->callbacks->reloc_overflow)
- (info, NULL,
- (link_order->type == bfd_section_reloc_link_order
- ? bfd_section_name (abfd, link_order->u.reloc.p->u.section)
- : link_order->u.reloc.p->u.name),
- r->howto->name, link_order->u.reloc.p->addend,
- NULL, NULL, 0)))
- {
- free (buf);
- return FALSE;
- }
+ (*info->callbacks->reloc_overflow)
+ (info, NULL,
+ (link_order->type == bfd_section_reloc_link_order
+ ? bfd_section_name (link_order->u.reloc.p->u.section)
+ : link_order->u.reloc.p->u.name),
+ r->howto->name, link_order->u.reloc.p->addend,
+ NULL, NULL, 0);
break;
}
- loc = link_order->offset * bfd_octets_per_byte (abfd);
+ loc = link_order->offset * bfd_octets_per_byte (abfd, sec);
ok = bfd_set_section_contents (abfd, sec, buf, loc, size);
free (buf);
if (! ok)
- return FALSE;
+ return false;
r->addend = 0;
}
sec->orelocation[sec->reloc_count] = r;
++sec->reloc_count;
- return TRUE;
+ return true;
}
\f
/* Allocate a new link_order for a section. */
struct bfd_link_order *
bfd_new_link_order (bfd *abfd, asection *section)
{
- bfd_size_type amt = sizeof (struct bfd_link_order);
+ size_t amt = sizeof (struct bfd_link_order);
struct bfd_link_order *new_lo;
new_lo = (struct bfd_link_order *) bfd_zalloc (abfd, amt);
the reloc_link_order types here, since they depend upon the details
of how the particular backends generates relocs. */
-bfd_boolean
+bool
_bfd_default_link_order (bfd *abfd,
struct bfd_link_info *info,
asection *sec,
abort ();
case bfd_indirect_link_order:
return default_indirect_link_order (abfd, info, sec, link_order,
- FALSE);
+ false);
case bfd_data_link_order:
return default_data_link_order (abfd, info, sec, link_order);
}
/* Default routine to handle a bfd_data_link_order. */
-static bfd_boolean
+static bool
default_data_link_order (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
asection *sec,
struct bfd_link_order *link_order)
{
size_t fill_size;
bfd_byte *fill;
file_ptr loc;
- bfd_boolean result;
+ bool result;
BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0);
size = link_order->size;
if (size == 0)
- return TRUE;
+ return true;
fill = link_order->u.data.contents;
fill_size = link_order->u.data.size;
if (fill_size == 0)
{
- fill = abfd->arch_info->fill (size, bfd_big_endian (abfd),
+ fill = abfd->arch_info->fill (size, info->big_endian,
(sec->flags & SEC_CODE) != 0);
if (fill == NULL)
- return FALSE;
+ return false;
}
else if (fill_size < size)
{
bfd_byte *p;
fill = (bfd_byte *) bfd_malloc (size);
if (fill == NULL)
- return FALSE;
+ return false;
p = fill;
if (fill_size == 1)
memset (p, (int) link_order->u.data.contents[0], (size_t) size);
}
}
- loc = link_order->offset * bfd_octets_per_byte (abfd);
+ loc = link_order->offset * bfd_octets_per_byte (abfd, sec);
result = bfd_set_section_contents (abfd, sec, fill, loc, size);
if (fill != link_order->u.data.contents)
/* Default routine to handle a bfd_indirect_link_order. */
-static bfd_boolean
+static bool
default_indirect_link_order (bfd *output_bfd,
struct bfd_link_info *info,
asection *output_section,
struct bfd_link_order *link_order,
- bfd_boolean generic_linker)
+ bool generic_linker)
{
asection *input_section;
bfd *input_bfd;
input_section = link_order->u.indirect.section;
input_bfd = input_section->owner;
if (input_section->size == 0)
- return TRUE;
+ return true;
BFD_ASSERT (input_section->output_section == output_section);
BFD_ASSERT (input_section->output_offset == link_order->offset);
BFD_ASSERT (input_section->size == link_order->size);
- if (info->relocatable
+ if (bfd_link_relocatable (info)
&& input_section->reloc_count > 0
&& output_section->orelocation == NULL)
{
because somebody is attempting to link together different
types of object files. Handling this case correctly is
difficult, and sometimes impossible. */
- (*_bfd_error_handler)
- (_("Attempt to do relocatable link with %s input and %s output"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("attempt to do relocatable link with %s input and %s output"),
bfd_get_target (input_bfd), bfd_get_target (output_bfd));
bfd_set_error (bfd_error_wrong_format);
- return FALSE;
+ return false;
}
if (! generic_linker)
a specific linker, presumably because we are linking
different types of object files together. */
if (!bfd_generic_link_read_symbols (input_bfd))
- return FALSE;
+ return false;
/* Since we have been called by a specific linker, rather than
the generic linker, the values of the symbols will not be
| BSF_GLOBAL
| BSF_CONSTRUCTOR
| BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (sym))
- || bfd_is_com_section (bfd_get_section (sym))
- || bfd_is_ind_section (bfd_get_section (sym)))
+ || bfd_is_und_section (bfd_asymbol_section (sym))
+ || bfd_is_com_section (bfd_asymbol_section (sym))
+ || bfd_is_ind_section (bfd_asymbol_section (sym)))
{
/* sym->udata may have been set by
generic_link_add_symbol_list. */
if (sym->udata.p != NULL)
h = (struct bfd_link_hash_entry *) sym->udata.p;
- else if (bfd_is_und_section (bfd_get_section (sym)))
+ else if (bfd_is_und_section (bfd_asymbol_section (sym)))
h = bfd_wrapped_link_hash_lookup (output_bfd, info,
bfd_asymbol_name (sym),
- FALSE, FALSE, TRUE);
+ false, false, true);
else
h = bfd_link_hash_lookup (info->hash,
bfd_asymbol_name (sym),
- FALSE, FALSE, TRUE);
+ false, false, true);
if (h != NULL)
set_symbol_from_hash (sym, h);
}
goto error_return;
new_contents = (bfd_get_relocated_section_contents
(output_bfd, info, link_order, contents,
- info->relocatable,
+ bfd_link_relocatable (info),
_bfd_generic_link_get_symbols (input_bfd)));
if (!new_contents)
goto error_return;
}
/* Output the section contents. */
- loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
+ loc = (input_section->output_offset
+ * bfd_octets_per_byte (output_bfd, output_section));
if (! bfd_set_section_contents (output_bfd, output_section,
new_contents, loc, input_section->size))
goto error_return;
- if (contents != NULL)
- free (contents);
- return TRUE;
+ free (contents);
+ return true;
error_return:
- if (contents != NULL)
- free (contents);
- return FALSE;
+ free (contents);
+ return false;
}
/* A little routine to count the number of relocs in a link_order
bfd_link_split_section
SYNOPSIS
- bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
+ bool bfd_link_split_section (bfd *abfd, asection *sec);
DESCRIPTION
Return nonzero if @var{sec} should be split during a
reloceatable or final link.
.#define bfd_link_split_section(abfd, sec) \
-. BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+. BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
.
*/
-bfd_boolean
+bool
_bfd_generic_link_split_section (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec ATTRIBUTE_UNUSED)
{
- return FALSE;
+ return false;
}
/*
bfd_section_already_linked
SYNOPSIS
- bfd_boolean bfd_section_already_linked (bfd *abfd,
- asection *sec,
- struct bfd_link_info *info);
+ bool bfd_section_already_linked (bfd *abfd,
+ asection *sec,
+ struct bfd_link_info *info);
DESCRIPTION
Check if @var{data} has been already linked during a reloceatable
or final link. Return TRUE if it has.
.#define bfd_section_already_linked(abfd, sec, info) \
-. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
+. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
.
*/
void
bfd_section_already_linked_table_traverse
- (bfd_boolean (*func) (struct bfd_section_already_linked_hash_entry *,
- void *), void *info)
+ (bool (*func) (struct bfd_section_already_linked_hash_entry *, void *),
+ void *info)
{
bfd_hash_traverse (&_bfd_section_already_linked_table,
- (bfd_boolean (*) (struct bfd_hash_entry *,
- void *)) func,
+ (bool (*) (struct bfd_hash_entry *, void *)) func,
info);
}
{
return ((struct bfd_section_already_linked_hash_entry *)
bfd_hash_lookup (&_bfd_section_already_linked_table, name,
- TRUE, FALSE));
+ true, false));
}
-bfd_boolean
+bool
bfd_section_already_linked_table_insert
(struct bfd_section_already_linked_hash_entry *already_linked_list,
asection *sec)
l = (struct bfd_section_already_linked *)
bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
if (l == NULL)
- return FALSE;
+ return false;
l->sec = sec;
l->next = already_linked_list->entry;
already_linked_list->entry = l;
- return TRUE;
+ return true;
}
static struct bfd_hash_entry *
return &ret->root;
}
-bfd_boolean
+bool
bfd_section_already_linked_table_init (void)
{
return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
/* Report warnings as appropriate for duplicate section SEC.
Return FALSE if we decide to keep SEC after all. */
-bfd_boolean
+bool
_bfd_handle_already_linked (asection *sec,
struct bfd_section_already_linked *l,
struct bfd_link_info *info)
&& (l->sec->owner->flags & BFD_PLUGIN) != 0)
{
l->sec = sec;
- return FALSE;
+ return false;
}
break;
case SEC_LINK_DUPLICATES_ONE_ONLY:
info->callbacks->einfo
- (_("%B: ignoring duplicate section `%A'\n"),
+ /* xgettext:c-format */
+ (_("%pB: ignoring duplicate section `%pA'\n"),
sec->owner, sec);
break;
;
else if (sec->size != l->sec->size)
info->callbacks->einfo
- (_("%B: duplicate section `%A' has different size\n"),
+ /* xgettext:c-format */
+ (_("%pB: duplicate section `%pA' has different size\n"),
sec->owner, sec);
break;
;
else if (sec->size != l->sec->size)
info->callbacks->einfo
- (_("%B: duplicate section `%A' has different size\n"),
+ /* xgettext:c-format */
+ (_("%pB: duplicate section `%pA' has different size\n"),
sec->owner, sec);
else if (sec->size != 0)
{
if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents))
info->callbacks->einfo
- (_("%B: could not read contents of section `%A'\n"),
+ /* xgettext:c-format */
+ (_("%pB: could not read contents of section `%pA'\n"),
sec->owner, sec);
else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
&l_sec_contents))
info->callbacks->einfo
- (_("%B: could not read contents of section `%A'\n"),
+ /* xgettext:c-format */
+ (_("%pB: could not read contents of section `%pA'\n"),
l->sec->owner, l->sec);
else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
info->callbacks->einfo
- (_("%B: duplicate section `%A' has different contents\n"),
+ /* xgettext:c-format */
+ (_("%pB: duplicate section `%pA' has different contents\n"),
sec->owner, sec);
- if (sec_contents)
- free (sec_contents);
- if (l_sec_contents)
- free (l_sec_contents);
+ free (sec_contents);
+ free (l_sec_contents);
}
break;
}
which we are really going to use. */
sec->output_section = bfd_abs_section_ptr;
sec->kept_section = l->sec;
- return TRUE;
+ return true;
}
/* This is used on non-ELF inputs. */
-bfd_boolean
+bool
_bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec,
struct bfd_link_info *info)
struct bfd_section_already_linked_hash_entry *already_linked_list;
if ((sec->flags & SEC_LINK_ONCE) == 0)
- return FALSE;
+ return false;
/* The generic linker doesn't handle section groups. */
if ((sec->flags & SEC_GROUP) != 0)
- return FALSE;
+ return false;
/* FIXME: When doing a relocatable link, we may have trouble
copying relocations in other sections that refer to local symbols
into a single large link once section, which defeats the purpose
of having link once sections in the first place. */
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_section_name (sec);
already_linked_list = bfd_section_already_linked_table_lookup (name);
/* This is the first section with this name. Record it. */
if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
- return FALSE;
+ return false;
}
/* Choose a neighbouring section to S in OBFD that will be output, or
/* Convert symbols in excluded output sections to use a kept section. */
-static bfd_boolean
+static bool
fix_syms (struct bfd_link_hash_entry *h, void *data)
{
bfd *obfd = (bfd *) data;
}
}
- return TRUE;
+ return true;
}
void
bfd_generic_define_common_symbol
SYNOPSIS
- bfd_boolean bfd_generic_define_common_symbol
+ bool bfd_generic_define_common_symbol
(bfd *output_bfd, struct bfd_link_info *info,
struct bfd_link_hash_entry *h);
Return TRUE on success and FALSE on failure.
.#define bfd_define_common_symbol(output_bfd, info, h) \
-. BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h))
+. BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h))
.
*/
-bfd_boolean
+bool
bfd_generic_define_common_symbol (bfd *output_bfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
struct bfd_link_hash_entry *h)
section = h->u.c.p->section;
/* Increase the size of the section to align the common symbol.
- The alignment must be a power of two. */
- alignment = bfd_octets_per_byte (output_bfd) << power_of_two;
+ The alignment must be a power of two. But if the section does
+ not have any alignment requirement then do not increase the
+ alignment unnecessarily. */
+ if (power_of_two)
+ alignment = bfd_octets_per_byte (output_bfd, section) << power_of_two;
+ else
+ alignment = 1;
BFD_ASSERT (alignment != 0 && (alignment & -alignment) == alignment);
section->size += alignment - 1;
section->size &= -alignment;
/* Make sure the section is allocated in memory, and make sure that
it is no longer a common section. */
section->flags |= SEC_ALLOC;
- section->flags &= ~SEC_IS_COMMON;
- return TRUE;
+ section->flags &= ~(SEC_IS_COMMON | SEC_HAS_CONTENTS);
+ return true;
+}
+
+/*
+FUNCTION
+ _bfd_generic_link_hide_symbol
+
+SYNOPSIS
+ void _bfd_generic_link_hide_symbol
+ (bfd *output_bfd, struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h);
+
+DESCRIPTION
+ Hide symbol @var{h}.
+ This is an internal function. It should not be called from
+ outside the BFD library.
+
+.#define bfd_link_hide_symbol(output_bfd, info, h) \
+. BFD_SEND (output_bfd, _bfd_link_hide_symbol, (output_bfd, info, h))
+.
+*/
+
+void
+_bfd_generic_link_hide_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+}
+
+/*
+FUNCTION
+ bfd_generic_define_start_stop
+
+SYNOPSIS
+ struct bfd_link_hash_entry *bfd_generic_define_start_stop
+ (struct bfd_link_info *info,
+ const char *symbol, asection *sec);
+
+DESCRIPTION
+ Define a __start, __stop, .startof. or .sizeof. symbol.
+ Return the symbol or NULL if no such undefined symbol exists.
+
+.#define bfd_define_start_stop(output_bfd, info, symbol, sec) \
+. BFD_SEND (output_bfd, _bfd_define_start_stop, (info, symbol, sec))
+.
+*/
+
+struct bfd_link_hash_entry *
+bfd_generic_define_start_stop (struct bfd_link_info *info,
+ const char *symbol, asection *sec)
+{
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (info->hash, symbol, false, false, true);
+ if (h != NULL
+ && !h->ldscript_def
+ && (h->type == bfd_link_hash_undefined
+ || h->type == bfd_link_hash_undefweak))
+ {
+ h->type = bfd_link_hash_defined;
+ h->u.def.section = sec;
+ h->u.def.value = 0;
+ return h;
+ }
+ return NULL;
}
/*
SYNOPSIS
struct bfd_elf_version_tree * bfd_find_version_for_sym
(struct bfd_elf_version_tree *verdefs,
- const char *sym_name, bfd_boolean *hide);
+ const char *sym_name, bool *hide);
DESCRIPTION
Search an elf version script tree for symbol versioning
struct bfd_elf_version_tree *
bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs,
const char *sym_name,
- bfd_boolean *hide)
+ bool *hide)
{
struct bfd_elf_version_tree *t;
struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
if (local_ver != NULL)
{
- *hide = TRUE;
+ *hide = true;
return local_ver;
}
bfd_hide_sym_by_version
SYNOPSIS
- bfd_boolean bfd_hide_sym_by_version
+ bool bfd_hide_sym_by_version
(struct bfd_elf_version_tree *verdefs, const char *sym_name);
DESCRIPTION
*/
-bfd_boolean
+bool
bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs,
const char *sym_name)
{
- bfd_boolean hidden = FALSE;
+ bool hidden = false;
bfd_find_version_for_sym (verdefs, sym_name, &hidden);
return hidden;
}
+
+/*
+FUNCTION
+ bfd_link_check_relocs
+
+SYNOPSIS
+ bool bfd_link_check_relocs
+ (bfd *abfd, struct bfd_link_info *info);
+
+DESCRIPTION
+ Checks the relocs in ABFD for validity.
+ Does not execute the relocs.
+ Return TRUE if everything is OK, FALSE otherwise.
+ This is the external entry point to this code.
+*/
+
+bool
+bfd_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+ return BFD_SEND (abfd, _bfd_link_check_relocs, (abfd, info));
+}
+
+/*
+FUNCTION
+ _bfd_generic_link_check_relocs
+
+SYNOPSIS
+ bool _bfd_generic_link_check_relocs
+ (bfd *abfd, struct bfd_link_info *info);
+
+DESCRIPTION
+ Stub function for targets that do not implement reloc checking.
+ Return TRUE.
+ This is an internal function. It should not be called from
+ outside the BFD library.
+*/
+
+bool
+_bfd_generic_link_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_merge_private_bfd_data
+
+SYNOPSIS
+ bool bfd_merge_private_bfd_data
+ (bfd *ibfd, struct bfd_link_info *info);
+
+DESCRIPTION
+ Merge private BFD information from the BFD @var{ibfd} to the
+ the output file BFD when linking. Return <<TRUE>> on success,
+ <<FALSE>> on error. Possible error returns are:
+
+ o <<bfd_error_no_memory>> -
+ Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_merge_private_bfd_data(ibfd, info) \
+. BFD_SEND ((info)->output_bfd, _bfd_merge_private_bfd_data, \
+. (ibfd, info))
+*/
+
+/*
+INTERNAL_FUNCTION
+ _bfd_generic_verify_endian_match
+
+SYNOPSIS
+ bool _bfd_generic_verify_endian_match
+ (bfd *ibfd, struct bfd_link_info *info);
+
+DESCRIPTION
+ Can be used from / for bfd_merge_private_bfd_data to check that
+ endianness matches between input and output file. Returns
+ TRUE for a match, otherwise returns FALSE and emits an error.
+*/
+
+bool
+_bfd_generic_verify_endian_match (bfd *ibfd, struct bfd_link_info *info)
+{
+ bfd *obfd = info->output_bfd;
+
+ if (ibfd->xvec->byteorder != obfd->xvec->byteorder
+ && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
+ && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
+ {
+ if (bfd_big_endian (ibfd))
+ _bfd_error_handler (_("%pB: compiled for a big endian system "
+ "and target is little endian"), ibfd);
+ else
+ _bfd_error_handler (_("%pB: compiled for a little endian system "
+ "and target is big endian"), ibfd);
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ return true;
+}
+
+int
+_bfd_nolink_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+bool
+_bfd_nolink_bfd_relax_section (bfd *abfd,
+ asection *section ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+ bool *again ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+bfd_byte *
+_bfd_nolink_bfd_get_relocated_section_contents
+ (bfd *abfd,
+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+ struct bfd_link_order *link_order ATTRIBUTE_UNUSED,
+ bfd_byte *data ATTRIBUTE_UNUSED,
+ bool relocatable ATTRIBUTE_UNUSED,
+ asymbol **symbols ATTRIBUTE_UNUSED)
+{
+ return (bfd_byte *) _bfd_ptr_bfd_null_error (abfd);
+}
+
+bool
+_bfd_nolink_bfd_lookup_section_flags
+ (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct flag_info *flaginfo ATTRIBUTE_UNUSED,
+ asection *section)
+{
+ return _bfd_bool_bfd_false_error (section->owner);
+}
+
+bool
+_bfd_nolink_bfd_is_group_section (bfd *abfd,
+ const asection *sec ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+const char *
+_bfd_nolink_bfd_group_name (bfd *abfd,
+ const asection *sec ATTRIBUTE_UNUSED)
+{
+ return _bfd_ptr_bfd_null_error (abfd);
+}
+
+bool
+_bfd_nolink_bfd_discard_group (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+struct bfd_link_hash_table *
+_bfd_nolink_bfd_link_hash_table_create (bfd *abfd)
+{
+ return (struct bfd_link_hash_table *) _bfd_ptr_bfd_null_error (abfd);
+}
+
+void
+_bfd_nolink_bfd_link_just_syms (asection *sec ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+}
+
+void
+_bfd_nolink_bfd_copy_link_hash_symbol_type
+ (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry *from ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry *to ATTRIBUTE_UNUSED)
+{
+}
+
+bool
+_bfd_nolink_bfd_link_split_section (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+bool
+_bfd_nolink_section_already_linked (bfd *abfd,
+ asection *sec ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+bool
+_bfd_nolink_bfd_define_common_symbol
+ (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+ return _bfd_bool_bfd_false_error (abfd);
+}
+
+struct bfd_link_hash_entry *
+_bfd_nolink_bfd_define_start_stop (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED,
+ asection *sec)
+{
+ return (struct bfd_link_hash_entry *) _bfd_ptr_bfd_null_error (sec->owner);
+}