diff options
Diffstat (limited to 'bfd/linker.c')
-rw-r--r-- | bfd/linker.c | 117 |
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; } |