aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2019-06-24 13:50:10 -0700
committerJim Wilson <jimw@sifive.com>2019-06-24 13:50:10 -0700
commit04b865dc2ede2b8ca8c60f0487a179eb97895fee (patch)
tree90ea8e2ea5857832e6b39f1bbc65a6bba0a07664 /bfd
parentf93ab3a0b8039a1667a666f013cca50b03d67f9b (diff)
downloadgdb-04b865dc2ede2b8ca8c60f0487a179eb97895fee.zip
gdb-04b865dc2ede2b8ca8c60f0487a179eb97895fee.tar.gz
gdb-04b865dc2ede2b8ca8c60f0487a179eb97895fee.tar.bz2
RISC-V: Enable lui relaxation for CODE and MERGE sections.
2019-06-24 Ilia Diachkov <ilia.diachkov@optimitech.com> bfd/ * elfnn-riscv.c (_bfd_riscv_relax_lui): Delete early exit when SEC_MERGE or SEC_CODE flags are set. (_bfd_riscv_relax_section): New local symtype. Set sym_sec and symtype consistently. Don't include sec_addr (sym_sec) in symval. Add check for SEC_INFO_TYPE_MERGE and call _bfd_merged_section_offset. Add sec_addr (sym_sec) after handling merge sections.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elfnn-riscv.c56
2 files changed, 55 insertions, 10 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ec272a8..d8cbef1 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2019-06-24 Ilia Diachkov <ilia.diachkov@optimitech.com>
+
+ * elfnn-riscv.c (_bfd_riscv_relax_lui): Delete early exit when
+ SEC_MERGE or SEC_CODE flags are set.
+ (_bfd_riscv_relax_section): New local symtype. Set sym_sec and
+ symtype consistently. Don't include sec_addr (sym_sec) in symval.
+ Add check for SEC_INFO_TYPE_MERGE and call _bfd_merged_section_offset.
+ Add sec_addr (sym_sec) after handling merge sections.
+
2019-06-24 H.J. Lu <hongjiu.lu@intel.com>
PR ld/24721
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 1bddbca..003b4f8 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3517,10 +3517,6 @@ _bfd_riscv_relax_lui (bfd *abfd,
bfd_vma gp = riscv_global_pointer_value (link_info);
int use_rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
- /* Mergeable symbols and code might later move out of range. */
- if (sym_sec->flags & (SEC_MERGE | SEC_CODE))
- return TRUE;
-
BFD_ASSERT (rel->r_offset + 4 <= sec->size);
if (gp)
@@ -3881,6 +3877,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
relax_func_t relax_func;
int type = ELFNN_R_TYPE (rel->r_info);
bfd_vma symval;
+ char symtype;
relax_func = NULL;
if (info->relax_pass == 0)
@@ -3946,7 +3943,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
? 0 : isym->st_size - rel->r_addend;
if (isym->st_shndx == SHN_UNDEF)
- sym_sec = sec, symval = sec_addr (sec) + rel->r_offset;
+ sym_sec = sec, symval = rel->r_offset;
else
{
BFD_ASSERT (isym->st_shndx < elf_numsections (abfd));
@@ -3959,8 +3956,9 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
if (sec_addr (sym_sec) == 0)
continue;
#endif
- symval = sec_addr (sym_sec) + isym->st_value;
+ symval = isym->st_value;
}
+ symtype = ELF_ST_TYPE (isym->st_info);
}
else
{
@@ -3975,21 +3973,59 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->plt.offset != MINUS_ONE)
- symval = sec_addr (htab->elf.splt) + h->plt.offset;
+ {
+ sym_sec = htab->elf.splt;
+ symval = h->plt.offset;
+ }
else if (h->root.u.def.section->output_section == NULL
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak))
continue;
else
- symval = sec_addr (h->root.u.def.section) + h->root.u.def.value;
+ {
+ symval = h->root.u.def.value;
+ sym_sec = h->root.u.def.section;
+ }
if (h->type != STT_FUNC)
reserve_size =
(h->size - rel->r_addend) > h->size ? 0 : h->size - rel->r_addend;
- sym_sec = h->root.u.def.section;
+ symtype = h->type;
}
- symval += rel->r_addend;
+ if (sym_sec->sec_info_type == SEC_INFO_TYPE_MERGE
+ && (sym_sec->flags & SEC_MERGE))
+ {
+ /* At this stage in linking, no SEC_MERGE symbol has been
+ adjusted, so all references to such symbols need to be
+ passed through _bfd_merged_section_offset. (Later, in
+ relocate_section, all SEC_MERGE symbols *except* for
+ section symbols have been adjusted.)
+
+ gas may reduce relocations against symbols in SEC_MERGE
+ sections to a relocation against the section symbol when
+ the original addend was zero. When the reloc is against
+ a section symbol we should include the addend in the
+ offset passed to _bfd_merged_section_offset, since the
+ location of interest is the original symbol. On the
+ other hand, an access to "sym+addend" where "sym" is not
+ a section symbol should not include the addend; Such an
+ access is presumed to be an offset from "sym"; The
+ location of interest is just "sym". */
+ if (symtype == STT_SECTION)
+ symval += rel->r_addend;
+
+ symval = _bfd_merged_section_offset (abfd, &sym_sec,
+ elf_section_data (sym_sec)->sec_info,
+ symval);
+
+ if (symtype != STT_SECTION)
+ symval += rel->r_addend;
+ }
+ else
+ symval += rel->r_addend;
+
+ symval += sec_addr (sym_sec);
if (!relax_func (abfd, sec, sym_sec, info, rel, symval,
max_alignment, reserve_size, again,