diff options
Diffstat (limited to 'bfd/elfnn-loongarch.c')
-rw-r--r-- | bfd/elfnn-loongarch.c | 121 |
1 files changed, 32 insertions, 89 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 00ebe5d..e786189 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -1446,7 +1446,6 @@ loongarch_check_offset (const Elf_Internal_Rela *rel, return bfd_reloc_ok; } - #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \ ({ \ bfd_reloc_status_type ret = loongarch_pop (&op2); \ @@ -1459,50 +1458,21 @@ loongarch_check_offset (const Elf_Internal_Rela *rel, ret; \ }) -#define LARCH_RELOC_UINT32_BIT_MASK(bitsize) \ - (~((0x1U << (bitsize)) - 1)) - static bfd_reloc_status_type loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel, const asection *input_section ATTRIBUTE_UNUSED, reloc_howto_type *howto, bfd *input_bfd, - bfd_byte *contents, int64_t op, - bool is_signed) + bfd_byte *contents, bfd_vma reloc_val) { - /* Check op low bits if rightshift != 0, before rightshift */ - if (howto->rightshift - && (((0x1U << howto->rightshift) - 1) & op)) - return bfd_reloc_overflow; - - uint32_t imm = (uint32_t)(int32_t)(op >> howto->rightshift); - - if (is_signed) - { - if (op >= 0) - { - if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm) - return bfd_reloc_overflow; - } - else - { - if ((LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm) - != LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1)) - return bfd_reloc_overflow; - } - } - else - { - if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize) & imm) - return bfd_reloc_overflow; - } - int bits = bfd_get_reloc_size (howto) * 8; uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset); - imm = imm & ((0x1U << howto->bitsize) - 1); - imm <<= howto->bitpos; - insn = ((insn & howto->src_mask) - | ((insn & (~(uint32_t) howto->dst_mask)) | imm)); + if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val)) + return bfd_reloc_overflow; + + insn = (insn & (uint32_t)howto->src_mask) + | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val); + bfd_put (bits, input_bfd, insn, contents + rel->r_offset); return bfd_reloc_ok; @@ -1594,19 +1564,8 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, case R_LARCH_SOP_POP_32_S_10_16: case R_LARCH_SOP_POP_32_S_10_16_S2: case R_LARCH_SOP_POP_32_S_5_20: - r = loongarch_pop (&opr1); - if (r != bfd_reloc_ok) - break; - r = loongarch_check_offset (rel, input_section); - if (r != bfd_reloc_ok) - break; - - r = loongarch_reloc_rewrite_imm_insn (rel, input_section, - howto, input_bfd, - contents, opr1, true); - break; - case R_LARCH_SOP_POP_32_U_10_12: + case R_LARCH_SOP_POP_32_U: r = loongarch_pop (&opr1); if (r != bfd_reloc_ok) break; @@ -1616,39 +1575,38 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, r = loongarch_reloc_rewrite_imm_insn (rel, input_section, howto, input_bfd, - contents, opr1, false); + contents, (bfd_vma)opr1); break; case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: - { - r = loongarch_pop (&opr1); - if (r != bfd_reloc_ok) - break; - - if ((opr1 & 0x3) != 0) - { - r = bfd_reloc_overflow; + { + r = loongarch_pop (&opr1); + if (r != bfd_reloc_ok) break; - } - uint32_t imm = opr1 >> howto->rightshift; - if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU))) - { - r = bfd_reloc_overflow; + if ((opr1 & 0x3) != 0) + { + r = bfd_reloc_overflow; + break; + } + + uint32_t imm = opr1 >> howto->rightshift; + if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU))) + { + r = bfd_reloc_overflow; + break; + } + r = loongarch_check_offset (rel, input_section); + if (r != bfd_reloc_ok) break; - } - r = loongarch_check_offset (rel, input_section); - if (r != bfd_reloc_ok) + insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset); + insn1 = (insn1 & howto->src_mask) + | ((imm & 0xffffU) << 10) + | ((imm & 0x1f0000U) >> 16); + bfd_put (bits, input_bfd, insn1, contents + rel->r_offset); break; - - insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset); - insn1 = ((insn1 & howto->src_mask) - | ((imm & 0xffffU) << 10) - | ((imm & 0x1f0000U) >> 16)); - bfd_put (bits, input_bfd, insn1, contents + rel->r_offset); - break; - } + } case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: { @@ -1681,21 +1639,6 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, break; } - case R_LARCH_SOP_POP_32_U: - r = loongarch_pop (&opr1); - if (r != bfd_reloc_ok) - break; - if ((uint64_t)opr1 & ~(uint64_t) 0xffffffff) - r = bfd_reloc_overflow; - if (r != bfd_reloc_ok) - break; - r = loongarch_check_offset (rel, input_section); - if (r != bfd_reloc_ok) - break; - - bfd_put (bits, input_bfd, opr1, contents + rel->r_offset); - break; - case R_LARCH_TLS_DTPREL32: case R_LARCH_32: case R_LARCH_TLS_DTPREL64: |