aboutsummaryrefslogtreecommitdiff
path: root/bfd/linker.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/linker.c')
-rw-r--r--bfd/linker.c117
1 files changed, 84 insertions, 33 deletions
diff --git a/bfd/linker.c b/bfd/linker.c
index 8b3579d..a9a23e5 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1378,7 +1378,25 @@ hash_entry_bfd (struct bfd_link_hash_entry *h)
/*NOTREACHED*/
}
-/* Add a symbol to the global hash table.
+/*
+FUNCTION
+ _bfd_generic_link_add_one_symbol
+
+SYNOPSIS
+ bool _bfd_generic_link_add_one_symbol
+ (struct bfd_link_info *info,
+ bfd *abfd,
+ const char *name,
+ flagword flags,
+ asection *section,
+ bfd_vma value,
+ const char *string,
+ bool copy,
+ bool collect,
+ struct bfd_link_hash_entry **hashp);
+
+DESCRIPTION
+ Add a symbol to the global hash table.
ABFD is the BFD the symbol comes from.
NAME is the name of the symbol.
FLAGS is the BSF_* bits associated with the symbol.
@@ -1854,7 +1872,47 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
return true;
}
-
+
+/*
+FUNCTION
+ bfd_link_align_section
+
+SYNOPSIS
+ bool bfd_link_align_section (asection *, unsigned int);
+
+DESCRIPTION
+ Increase section alignment if the current section alignment is
+ less than the requested value. Adjust output section
+ alignment too, so that linker layout adjusts for alignment on
+ the current lang_size_sections pass. This is important for
+ lang_size_relro_segment. If the output section alignment
+ isn't adjusted, the linker will place the output section at an
+ address depending on its current alignment. When sizing the
+ output section, input sections attached transfer any increase
+ in alignment to the output section, which will affect layout
+ for the next sizing pass. Which is all well and good except
+ that lang_size_relro_segment for the current sizing pass uses
+ that possibly increased alignment with a layout that doesn't
+ suit.
+*/
+
+bool
+bfd_link_align_section (asection *sec, unsigned int align_p2)
+{
+ if (align_p2 > bfd_section_alignment (sec))
+ {
+ if (!bfd_set_section_alignment (sec, align_p2))
+ return false;
+ asection *osec = sec->output_section;
+ if (osec && align_p2 > bfd_section_alignment (osec))
+ {
+ if (!bfd_set_section_alignment (osec, align_p2))
+ return false;
+ }
+ }
+ return true;
+}
+
/* Generic final link routine. */
bool
@@ -2066,7 +2124,6 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
{
asymbol *sym;
struct generic_link_hash_entry *h;
- bool output;
h = NULL;
sym = *sym_ptr;
@@ -2160,12 +2217,20 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
}
}
+ bool output = false;
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;
+ ;
+ /* If this symbol is in a section which is not being included
+ in the output file, then we don't want to output the
+ symbol. */
+ else if (!bfd_is_abs_section (sym->section)
+ && bfd_section_removed_from_list (output_bfd,
+ sym->section->output_section))
+ ;
else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
{
/* If this symbol is marked as occurring now, rather
@@ -2175,34 +2240,27 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
if (bfd_asymbol_bfd (sym) == input_bfd
&& (sym->flags & BSF_NOT_AT_END) != 0)
output = true;
- else
- output = false;
}
else if ((sym->flags & BSF_KEEP) != 0)
output = true;
else if (bfd_is_ind_section (sym->section))
- output = false;
+ ;
else if ((sym->flags & BSF_DEBUGGING) != 0)
{
if (info->strip == strip_none)
output = true;
- else
- output = false;
}
else if (bfd_is_und_section (sym->section)
|| bfd_is_com_section (sym->section))
- output = false;
+ ;
else if ((sym->flags & BSF_LOCAL) != 0)
{
- if ((sym->flags & BSF_WARNING) != 0)
- output = false;
- else
+ if ((sym->flags & BSF_WARNING) == 0)
{
switch (info->discard)
{
default:
case discard_all:
- output = false;
break;
case discard_sec_merge:
output = true;
@@ -2211,9 +2269,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
break;
/* FALLTHROUGH */
case discard_l:
- if (bfd_is_local_label (input_bfd, sym))
- output = false;
- else
+ if (!bfd_is_local_label (input_bfd, sym))
output = true;
break;
case discard_none:
@@ -2226,25 +2282,15 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
{
if (info->strip != strip_all)
output = true;
- else
- output = false;
}
- else if (sym->flags == 0
- && (sym->section->owner->flags & BFD_PLUGIN) != 0)
+ else if (sym->flags == 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;
+ needs to be global. We also get here on fuzzed ELF objects
+ with bogus symbol type and binding. */
+ ;
else
- abort ();
-
- /* If this symbol is in a section which is not being included
- in the output file, then we don't want to output the
- symbol. */
- if (!bfd_is_abs_section (sym->section)
- && bfd_section_removed_from_list (output_bfd,
- sym->section->output_section))
- output = false;
+ BFD_FAIL ();
if (output)
{
@@ -2997,6 +3043,8 @@ _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
name = bfd_section_name (sec);
already_linked_list = bfd_section_already_linked_table_lookup (name);
+ if (!already_linked_list)
+ goto bad;
l = already_linked_list->entry;
if (l != NULL)
@@ -3008,7 +3056,10 @@ _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
/* 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"));
+ {
+ bad:
+ info->callbacks->fatal (_("%P: already_linked_table: %E\n"));
+ }
return false;
}