diff options
author | Peter Zotov <whitequark@whitequark.org> | 2015-09-25 15:21:14 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-09-25 15:21:14 +0100 |
commit | 8a9e7a9121490a8c64d8c17f5be510e43104f6d9 (patch) | |
tree | 43e5f465538c635dfee83fddab4f3a9e5adeb42d /gas/config/tc-or1k.c | |
parent | 6cd8405efd699ed7686671d6f0d9caf20757b7a3 (diff) | |
download | gdb-8a9e7a9121490a8c64d8c17f5be510e43104f6d9.zip gdb-8a9e7a9121490a8c64d8c17f5be510e43104f6d9.tar.gz gdb-8a9e7a9121490a8c64d8c17f5be510e43104f6d9.tar.bz2 |
Correct the generation of OR1K pc-relative relocations.
gas PR ld/18759
* config/tc-or1k.c (tc_gen_reloc): Correct computation of PC
relative relocs.
* config/tc-or1k.h (GAS_CGEN_PRCEL_R_TYPE): Delete.
bfd * elf32-or1k.c (R_OR1K_32_PCREL): Set pcrel_offset to TRUE.
(R_OR1K_16_PCREL): Likewise.
(R_OR1K_8_PCREL): Likewise.
ld/tests * ld-elf/eh-frame-hdr: Expect to pass on the or1k-linux target.
Diffstat (limited to 'gas/config/tc-or1k.c')
-rw-r--r-- | gas/config/tc-or1k.c | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/gas/config/tc-or1k.c b/gas/config/tc-or1k.c index e490ffc..dba2dde 100644 --- a/gas/config/tc-or1k.c +++ b/gas/config/tc-or1k.c @@ -298,27 +298,59 @@ or1k_fix_adjustable (fixS * fixP) #define GOT_NAME "_GLOBAL_OFFSET_TABLE_" arelent * -tc_gen_reloc (asection *sec, fixS *fx) +tc_gen_reloc (asection * section, fixS * fixp) { - bfd_reloc_code_real_type code = fx->fx_r_type; + arelent *reloc; + bfd_reloc_code_real_type code; - if (fx->fx_addsy != NULL - && strcmp (S_GET_NAME (fx->fx_addsy), GOT_NAME) == 0 - && (code == BFD_RELOC_OR1K_GOTPC_HI16 - || code == BFD_RELOC_OR1K_GOTPC_LO16)) + reloc = xmalloc (sizeof (arelent)); + + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + + if (fixp->fx_pcrel) + { + if (section->use_rela_p) + fixp->fx_offset -= md_pcrel_from_section (fixp, section); + else + fixp->fx_offset = reloc->address; + } + reloc->addend = fixp->fx_offset; + + code = fixp->fx_r_type; + switch (code) + { + case BFD_RELOC_16: + if (fixp->fx_pcrel) + code = BFD_RELOC_16_PCREL; + break; + + case BFD_RELOC_32: + if (fixp->fx_pcrel) + code = BFD_RELOC_32_PCREL; + break; + + case BFD_RELOC_64: + if (fixp->fx_pcrel) + code = BFD_RELOC_64_PCREL; + break; + + default: + break; + } + + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + if (reloc->howto == NULL) { - arelent * reloc; - - reloc = xmalloc (sizeof (* reloc)); - reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy); - reloc->address = fx->fx_frag->fr_address + fx->fx_where; - reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type); - reloc->addend = fx->fx_offset; - return reloc; + as_bad_where (fixp->fx_file, fixp->fx_line, + _ + ("cannot represent %s relocation in this object file format"), + bfd_get_reloc_code_name (code)); + return NULL; } - return gas_cgen_tc_gen_reloc (sec, fx); + return reloc; } void |