aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfnn-riscv.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elfnn-riscv.c')
-rw-r--r--bfd/elfnn-riscv.c131
1 files changed, 74 insertions, 57 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 9f4bc0a..af08f7d 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -1441,11 +1441,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return false;
- }
+ && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
+ && !bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
{
@@ -1497,21 +1496,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (h->got.refcount > 0)
{
asection *s;
- bool dyn;
+ bool dyn = htab->elf.dynamic_sections_created;
int tls_type = riscv_elf_hash_entry (h)->tls_type;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return false;
- }
+ if (dyn
+ && h->dynindx == -1
+ && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
+ && !bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
s = htab->elf.sgot;
h->got.offset = s->size;
- dyn = htab->elf.dynamic_sections_created;
if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLSDESC))
{
int indx = 0;
@@ -1545,7 +1543,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
else
{
s->size += GOT_ENTRY_SIZE;
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
+ if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak)
+ && (bfd_link_pic (info)
+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
&& ! UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
}
@@ -1591,11 +1592,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Make sure undefined weak symbols are output as a dynamic
symbol in PIEs. */
else if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return false;
- }
+ && !h->forced_local
+ && !bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
}
}
else
@@ -1614,11 +1613,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return false;
- }
+ && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
+ && !bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
/* If that succeeded, we know we'll be keeping all the
relocs. */
@@ -1634,6 +1632,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Finally, allocate space. */
for (p = h->dyn_relocs; p != NULL; p = p->next)
{
+ if (discarded_section (p->sec))
+ continue;
asection *sreloc = elf_section_data (p->sec)->sreloc;
sreloc->size += p->count * sizeof (ElfNN_External_Rela);
}
@@ -2459,6 +2459,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
const char *msg = NULL;
bool resolved_to_zero;
bool via_plt = false;
+ bool relative_got = false;
if (howto == NULL)
continue;
@@ -2873,6 +2874,15 @@ riscv_elf_relocate_section (bfd *output_bfd,
off &= ~1;
else
{
+ /* If a symbol is not dynamic and is not undefined weak,
+ bind it locally and generate a RELATIVE relocation
+ under PIC mode. */
+ if (h->dynindx == -1
+ && !h->forced_local
+ && h->root.type != bfd_link_hash_undefweak
+ && bfd_link_pic (info))
+ relative_got = true;
+
bfd_put_NN (output_bfd, relocation,
htab->elf.sgot->contents + off);
h->got.offset |= 1;
@@ -2896,22 +2906,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
else
{
if (bfd_link_pic (info))
- {
- asection *s;
- Elf_Internal_Rela outrel;
-
- /* We need to generate a R_RISCV_RELATIVE reloc
- for the dynamic linker. */
- s = htab->elf.srelgot;
- BFD_ASSERT (s != NULL);
-
- outrel.r_offset = sec_addr (htab->elf.sgot) + off;
- outrel.r_info =
- ELFNN_R_INFO (0, R_RISCV_RELATIVE);
- outrel.r_addend = relocation;
- relocation = 0;
- riscv_elf_append_rela (output_bfd, s, &outrel);
- }
+ relative_got = true;
bfd_put_NN (output_bfd, relocation,
htab->elf.sgot->contents + off);
@@ -2919,6 +2914,21 @@ riscv_elf_relocate_section (bfd *output_bfd,
}
}
+ /* We need to generate a R_RISCV_RELATIVE relocation later in the
+ riscv_elf_finish_dynamic_symbol if h->dynindx != -1; Otherwise,
+ generate a R_RISCV_RELATIVE relocation here now. */
+ if (relative_got)
+ {
+ asection *s = htab->elf.srelgot;
+ BFD_ASSERT (s != NULL);
+
+ Elf_Internal_Rela outrel;
+ outrel.r_offset = sec_addr (htab->elf.sgot) + off;
+ outrel.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
+ outrel.r_addend = relocation;
+ riscv_elf_append_rela (output_bfd, s, &outrel);
+ }
+
if (rel->r_addend != 0)
{
msg = _("The addend isn't allowed for R_RISCV_GOT_HI20");
@@ -5987,43 +5997,49 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
#define TARGET_BIG_SYM riscv_elfNN_be_vec
#define TARGET_BIG_NAME "elfNN-bigriscv"
-#define elf_backend_reloc_type_class riscv_reloc_type_class
+#define elf_info_to_howto_rel NULL
+#define elf_info_to_howto riscv_info_to_howto_rela
#define bfd_elfNN_bfd_reloc_name_lookup riscv_reloc_name_lookup
-#define bfd_elfNN_bfd_link_hash_table_create riscv_elf_link_hash_table_create
+#define bfd_elfNN_bfd_link_hash_table_create \
+ riscv_elf_link_hash_table_create
#define bfd_elfNN_bfd_reloc_type_lookup riscv_reloc_type_lookup
-#define bfd_elfNN_bfd_merge_private_bfd_data \
+#define bfd_elfNN_bfd_merge_private_bfd_data \
_bfd_riscv_elf_merge_private_bfd_data
-#define bfd_elfNN_bfd_is_target_special_symbol riscv_elf_is_target_special_symbol
+#define bfd_elfNN_bfd_is_target_special_symbol \
+ riscv_elf_is_target_special_symbol
+#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section
+#define bfd_elfNN_mkobject elfNN_riscv_mkobject
+#define bfd_elfNN_get_synthetic_symtab \
+ elfNN_riscv_get_synthetic_symtab
+#define elf_backend_reloc_type_class riscv_reloc_type_class
#define elf_backend_copy_indirect_symbol riscv_elf_copy_indirect_symbol
-#define elf_backend_create_dynamic_sections riscv_elf_create_dynamic_sections
+#define elf_backend_create_dynamic_sections \
+ riscv_elf_create_dynamic_sections
#define elf_backend_check_relocs riscv_elf_check_relocs
#define elf_backend_adjust_dynamic_symbol riscv_elf_adjust_dynamic_symbol
#define elf_backend_late_size_sections riscv_elf_late_size_sections
#define elf_backend_relocate_section riscv_elf_relocate_section
#define elf_backend_finish_dynamic_symbol riscv_elf_finish_dynamic_symbol
-#define elf_backend_finish_dynamic_sections riscv_elf_finish_dynamic_sections
+#define elf_backend_finish_dynamic_sections \
+ riscv_elf_finish_dynamic_sections
#define elf_backend_plt_sym_val riscv_elf_plt_sym_val
#define elf_backend_grok_prstatus riscv_elf_grok_prstatus
#define elf_backend_grok_psinfo riscv_elf_grok_psinfo
#define elf_backend_object_p riscv_elf_object_p
#define elf_backend_write_core_note riscv_write_core_note
#define elf_backend_maybe_function_sym riscv_maybe_function_sym
-#define elf_info_to_howto_rel NULL
-#define elf_info_to_howto riscv_info_to_howto_rela
-#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section
-#define bfd_elfNN_mkobject elfNN_riscv_mkobject
-#define bfd_elfNN_get_synthetic_symtab elfNN_riscv_get_synthetic_symtab
#define elf_backend_additional_program_headers \
riscv_elf_additional_program_headers
#define elf_backend_modify_segment_map riscv_elf_modify_segment_map
-#define elf_backend_merge_symbol_attribute riscv_elf_merge_symbol_attribute
-
+#define elf_backend_merge_symbol_attribute \
+ riscv_elf_merge_symbol_attribute
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
-
-#define elf_backend_setup_gnu_properties elfNN_riscv_link_setup_gnu_properties
-#define elf_backend_merge_gnu_properties elfNN_riscv_merge_gnu_properties
+#define elf_backend_setup_gnu_properties \
+ elfNN_riscv_link_setup_gnu_properties
+#define elf_backend_merge_gnu_properties \
+ elfNN_riscv_merge_gnu_properties
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
@@ -6044,6 +6060,7 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
#define elf_backend_obj_attrs_section_type SHT_RISCV_ATTRIBUTES
#undef elf_backend_obj_attrs_section
#define elf_backend_obj_attrs_section RISCV_ATTRIBUTES_SECTION_NAME
-#define elf_backend_obj_attrs_handle_unknown riscv_elf_obj_attrs_handle_unknown
+#define elf_backend_obj_attrs_handle_unknown \
+ riscv_elf_obj_attrs_handle_unknown
#include "elfNN-target.h"