aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2018-02-02 12:43:09 -0800
committerJim Wilson <jimw@sifive.com>2018-02-02 12:43:09 -0800
commit7f02625eb48105e100d2da58091d56978ed041ef (patch)
tree0c1e3dec2610638bd0f974b2d368982dfcd8c780
parent0625771b9e29116dc1fb0b597501f18e4bb0e18c (diff)
downloadgdb-7f02625eb48105e100d2da58091d56978ed041ef.zip
gdb-7f02625eb48105e100d2da58091d56978ed041ef.tar.gz
gdb-7f02625eb48105e100d2da58091d56978ed041ef.tar.bz2
RISC-V: Fix --wrap and relaxation conflict.
bfd/ PR ld/22756 * elfnn-riscv.c (riscv_relax_delete_bytes): New parameter link_info. If link_info->wrap_hash, check for a duplicate symbol and ignore. (_bfd_riscv_relax_call, bfd_riscv_relax_lui, _bfd_riscv_relax_tls_le): Pass new argument to riscv_relax_delete_bytes. (_bfd_riscv_relax_align, _bfd_riscv_relax_delete): Likewise. Remove ATTRIBUTE_UNUSED from link_info parameter.
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elfnn-riscv.c48
2 files changed, 49 insertions, 9 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 090fc23..b651051 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2018-02-02 Jim Wilson <jimw@sifive.com>
+
+ PR ld/22756
+ * elfnn-riscv.c (riscv_relax_delete_bytes): New parameter link_info.
+ If link_info->wrap_hash, check for a duplicate symbol and ignore.
+ (_bfd_riscv_relax_call, bfd_riscv_relax_lui, _bfd_riscv_relax_tls_le):
+ Pass new argument to riscv_relax_delete_bytes.
+ (_bfd_riscv_relax_align, _bfd_riscv_relax_delete): Likewise. Remove
+ ATTRIBUTE_UNUSED from link_info parameter.
+
2018-02-02 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_relocate_section): Don't relocate nops
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 5f66f4f..f2136b2 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -2604,7 +2604,8 @@ fail:
/* Delete some bytes from a section while relaxing. */
static bfd_boolean
-riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
+riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
+ struct bfd_link_info *link_info)
{
unsigned int i, symcount;
bfd_vma toaddr = sec->size;
@@ -2654,6 +2655,31 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
{
struct elf_link_hash_entry *sym_hash = sym_hashes[i];
+ /* The '--wrap SYMBOL' option is causing a pain when the object file,
+ containing the definition of __wrap_SYMBOL, includes a direct
+ call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
+ the same symbol (which is __wrap_SYMBOL), but still exist as two
+ different symbols in 'sym_hashes', we don't want to adjust
+ the global symbol __wrap_SYMBOL twice.
+ This check is only relevant when symbols are being wrapped. */
+ if (link_info->wrap_hash != NULL)
+ {
+ struct elf_link_hash_entry **cur_sym_hashes;
+
+ /* Loop only over the symbols which have already been checked. */
+ for (cur_sym_hashes = sym_hashes; cur_sym_hashes < &sym_hashes[i];
+ cur_sym_hashes++)
+ {
+ /* If the current symbol is identical to 'sym_hash', that means
+ the symbol was already adjusted (or at least checked). */
+ if (*cur_sym_hashes == sym_hash)
+ break;
+ }
+ /* Don't adjust the symbol again. */
+ if (cur_sym_hashes < &sym_hashes[i])
+ continue;
+ }
+
if ((sym_hash->root.type == bfd_link_hash_defined
|| sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec)
@@ -2886,7 +2912,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
/* Delete unnecessary JALR. */
*again = TRUE;
- return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len);
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len,
+ link_info);
}
/* Traverse all output sections and return the max alignment. */
@@ -2964,7 +2991,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
/* We can delete the unnecessary LUI and reloc. */
rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
*again = TRUE;
- return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4,
+ link_info);
default:
abort ();
@@ -2991,7 +3019,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_RVC_LUI);
*again = TRUE;
- return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2);
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2,
+ link_info);
}
return TRUE;
@@ -3031,7 +3060,7 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
/* We can delete the unnecessary instruction and reloc. */
rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
*again = TRUE;
- return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info);
default:
abort ();
@@ -3043,7 +3072,7 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
static bfd_boolean
_bfd_riscv_relax_align (bfd *abfd, asection *sec,
asection *sym_sec,
- struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info,
Elf_Internal_Rela *rel,
bfd_vma symval,
bfd_vma max_alignment ATTRIBUTE_UNUSED,
@@ -3091,7 +3120,7 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
/* Delete the excess bytes. */
return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
- rel->r_addend - nop_bytes);
+ rel->r_addend - nop_bytes, link_info);
}
/* Relax PC-relative references to GP-relative references. */
@@ -3212,7 +3241,7 @@ static bfd_boolean
_bfd_riscv_relax_delete (bfd *abfd,
asection *sec,
asection *sym_sec ATTRIBUTE_UNUSED,
- struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info,
Elf_Internal_Rela *rel,
bfd_vma symval ATTRIBUTE_UNUSED,
bfd_vma max_alignment ATTRIBUTE_UNUSED,
@@ -3220,7 +3249,8 @@ _bfd_riscv_relax_delete (bfd *abfd,
bfd_boolean *again ATTRIBUTE_UNUSED,
riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED)
{
- if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend))
+ if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend,
+ link_info))
return FALSE;
rel->r_info = ELFNN_R_INFO(0, R_RISCV_NONE);
return TRUE;