From: liuzhensong Date: Mon, 21 Feb 2022 06:13:43 +0000 (+0800) Subject: LoongArch: Use functions instead of magic numbers. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=748594bc07f39fda35aba5f46d6e058b42c9c49d;p=binutils-gdb.git LoongArch: Use functions instead of magic numbers. Replace the magic numbers in gas(tc-loongarch.c) and bfd(elfnn-loongarch.c) with the functions defined in the howto table(elfxx-loongarch.c). gas/ * config/tc-loongarch.c: use functions. bfd/ * elfnn-loongarch.c: use functions. * elfxx-loongarch.c: define functions. * elfxx-loongarch.h --- diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 00ebe5daeb2..e7861894c07 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: diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c index ab78792b630..6f7c82297c5 100644 --- a/bfd/elfxx-loongarch.c +++ b/bfd/elfxx-loongarch.c @@ -29,210 +29,259 @@ #define ALL_ONES (~ (bfd_vma) 0) +typedef struct loongarch_reloc_howto_type_struct +{ + /* The first must be reloc_howto_type! */ + reloc_howto_type howto; + bfd_reloc_code_real_type bfd_type; + bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *); +}loongarch_reloc_howto_type; + +#define LOONGARCH_DEFAULT_HOWTO(r_name) \ + { HOWTO (R_LARCH_##r_name, 0, 2, 32, false, 0, complain_overflow_signed, \ + bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES, \ + false), BFD_RELOC_LARCH_##r_name, NULL } + +#define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \ + name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc) \ + { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \ + inplace, src_mask, dst_mask, pcrel_off), btype, afunc } + +#define LOONGARCH_EMPTY_HOWTO(C) \ + { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL } + +bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val); +bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto, + bfd_vma *fix_val); +bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto, + bfd_vma *val); + + /* This does not include any relocation information, but should be good enough for GDB or objdump to read the file. */ - -static reloc_howto_type howto_table[] = +static loongarch_reloc_howto_type loongarch_howto_table[] = { -#define LOONGARCH_HOWTO(r_name) \ - HOWTO (R_LARCH_##r_name, 0, 2, 32, false, 0, complain_overflow_signed, \ - bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, 0xffffffff, false) - /* No relocation. */ - HOWTO (R_LARCH_NONE, /* type (0). */ - 0, /* rightshift */ - 3, /* size */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_NONE", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ + LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */ + 0, /* rightshift */ + 3, /* size */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_NONE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ /* 32 bit relocation. */ - HOWTO (R_LARCH_32, /* type (1). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_32", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ /* 64 bit relocation. */ - HOWTO (R_LARCH_64, /* type (2). */ - 0, /* rightshift */ - 4, /* size */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_64", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_RELATIVE, /* type (3). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_RELATIVE", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_COPY, /* type (4). */ - 0, /* rightshift */ - 0, /* this one is variable size */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_COPY", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */ - 0, /* rightshift */ - 4, /* size */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_JUMP_SLOT", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ + LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */ + 0, /* rightshift */ + 4, /* size */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_64", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_RELATIVE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */ + 0, /* rightshift */ + 0, /* this one is variable size */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_COPY", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */ + 0, /* rightshift */ + 4, /* size */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_JUMP_SLOT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ + NULL), /* adjust_reloc_bits */ /* Dynamic TLS relocations. */ - HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_DTPMOD32", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */ - 0, /* rightshift */ - 4, /* size */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_DTPMOD64", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_DTPREL32", /* name */ - true, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */ - 0, /* rightshift */ - 4, /* size */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_DTPREL64", /* name */ - true, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_TPREL32", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */ - 0, /* rightshift */ - 4, /* size */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_TLS_TPREL64", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ - false), /* pcrel_offset */ - - HOWTO (R_LARCH_IRELATIVE, /* type (12). */ - 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_LARCH_IRELATIVE", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - EMPTY_HOWTO(13), - EMPTY_HOWTO(14), - EMPTY_HOWTO(15), - EMPTY_HOWTO(16), - EMPTY_HOWTO(17), - EMPTY_HOWTO(18), - EMPTY_HOWTO(19), - - HOWTO (R_LARCH_MARK_LA, /* type (20). */ + LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_DTPMOD32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_DTPMOD32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */ + 0, /* rightshift */ + 4, /* size */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_DTPMOD64", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_DTPMOD64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_DTPREL32", /* name */ + true, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_DTPREL32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */ + 0, /* rightshift */ + 4, /* size */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_DTPREL64", /* name */ + true, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_DTPREL64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_TPREL32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_TPREL32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */ + 0, /* rightshift */ + 4, /* size */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_TLS_TPREL64", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_TPREL64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_LARCH_IRELATIVE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ + NULL), /* adjust_reloc_bits */ + + LOONGARCH_EMPTY_HOWTO(13), + LOONGARCH_EMPTY_HOWTO(14), + LOONGARCH_EMPTY_HOWTO(15), + LOONGARCH_EMPTY_HOWTO(16), + LOONGARCH_EMPTY_HOWTO(17), + LOONGARCH_EMPTY_HOWTO(18), + LOONGARCH_EMPTY_HOWTO(19), + + LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */ 0, /* rightshift. */ 3, /* size. */ 0, /* bitsize. */ @@ -244,9 +293,11 @@ static reloc_howto_type howto_table[] = false, /* partial_inplace. */ 0, /* src_mask. */ 0, /* dst_mask. */ - false), /* pcrel_offset. */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_MARK_PCREL, /* type (21). */ + LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */ 0, /* rightshift. */ 3, /* size. */ 0, /* bitsize. */ @@ -258,9 +309,11 @@ static reloc_howto_type howto_table[] = false, /* partial_inplace. */ 0, /* src_mask. */ 0, /* dst_mask. */ - false), /* pcrel_offset. */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */ + LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */ 2, /* rightshift. */ 2, /* size. */ 32, /* bitsize. */ @@ -270,126 +323,144 @@ static reloc_howto_type howto_table[] = bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SOP_PUSH_PCREL", /* name. */ false, /* partial_inplace. */ - 0x03ffffff, /* src_mask. */ - 0x03ffffff, /* dst_mask. */ - false), /* pcrel_offset. */ + 0x03ffffff, /* src_mask. */ + 0x03ffffff, /* dst_mask. */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ /* type 23-37. */ - LOONGARCH_HOWTO (SOP_PUSH_ABSOLUTE), - LOONGARCH_HOWTO (SOP_PUSH_DUP), - LOONGARCH_HOWTO (SOP_PUSH_GPREL), - LOONGARCH_HOWTO (SOP_PUSH_TLS_TPREL), - LOONGARCH_HOWTO (SOP_PUSH_TLS_GOT), - LOONGARCH_HOWTO (SOP_PUSH_TLS_GD), - LOONGARCH_HOWTO (SOP_PUSH_PLT_PCREL), - LOONGARCH_HOWTO (SOP_ASSERT), - LOONGARCH_HOWTO (SOP_NOT), - LOONGARCH_HOWTO (SOP_SUB), - LOONGARCH_HOWTO (SOP_SL), - LOONGARCH_HOWTO (SOP_SR), - LOONGARCH_HOWTO (SOP_ADD), - LOONGARCH_HOWTO (SOP_AND), - LOONGARCH_HOWTO (SOP_IF_ELSE), - - HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */ - 0, /* rightshift. */ - 2, /* size. */ - 5, /* bitsize. */ - false, /* pc_relative. */ - 10, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_10_5", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x7c00, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */ - 0, /* rightshift. */ - 2, /* size. */ - 12, /* bitsize. */ - false, /* pc_relative. */ - 10, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_U_10_12", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x3ffc00, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */ - 0, /* rightshift. */ - 2, /* size. */ - 12, /* bitsize. */ - false, /* pc_relative. */ - 10, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_10_12", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x3ffc00, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */ - 0, /* rightshift. */ - 2, /* size. */ - 16, /* bitsize. */ - false, /* pc_relative. */ - 10, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_10_16", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */ - 2, /* rightshift. */ - 2, /* size. */ - 16, /* bitsize. */ - false, /* pc_relative. */ - 10, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x3fffc00, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */ - 0, /* rightshift. */ - 2, /* size. */ - 20, /* bitsize. */ - false, /* pc_relative. */ - 5, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_5_20", /* name. */ - false, /* partial_inplace. */ - 0, /* src_mask */ - 0x1fffe0, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, /* type (44). */ - 2, /* rightshift. */ - 2, /* size. */ - 21, /* bitsize. */ - false, /* pc_relative. */ - 0, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ - "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */ - false, /* partial_inplace. */ - 0xfc0003e0, /* src_mask */ - 0xfc0003e0, /* dst_mask */ - false), /* pcrel_offset. */ - - HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */ + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD), + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL), + LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT), + LOONGARCH_DEFAULT_HOWTO (SOP_NOT), + LOONGARCH_DEFAULT_HOWTO (SOP_SUB), + LOONGARCH_DEFAULT_HOWTO (SOP_SL), + LOONGARCH_DEFAULT_HOWTO (SOP_SR), + LOONGARCH_DEFAULT_HOWTO (SOP_ADD), + LOONGARCH_DEFAULT_HOWTO (SOP_AND), + LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE), + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */ + 0, /* rightshift. */ + 2, /* size. */ + 5, /* bitsize. */ + false, /* pc_relative. */ + 10, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_10_5", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x7c00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */ + 0, /* rightshift. */ + 2, /* size. */ + 12, /* bitsize. */ + false, /* pc_relative. */ + 10, /* bitpos. */ + complain_overflow_unsigned, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_U_10_12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */ + 0, /* rightshift. */ + 2, /* size. */ + 12, /* bitsize. */ + false, /* pc_relative. */ + 10, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_10_12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */ + 0, /* rightshift. */ + 2, /* size. */ + 16, /* bitsize. */ + false, /* pc_relative. */ + 10, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_10_16", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3fffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */ + 2, /* rightshift. */ + 2, /* size. */ + 16, /* bitsize. */ + false, /* pc_relative. */ + 10, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3fffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */ + 0, /* rightshift. */ + 2, /* size. */ + 20, /* bitsize. */ + false, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_5_20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, + /* type (44). */ + 2, /* rightshift. */ + 2, /* size. */ + 21, /* bitsize. */ + false, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */ + false, /* partial_inplace. */ + 0xfc0003e0, /* src_mask */ + 0xfc0003e0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2, + /* bfd_reloc_code_real_type */ + loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */ 2, /* rightshift. */ 2, /* size. */ 26, /* bitsize. */ @@ -401,23 +472,28 @@ static reloc_howto_type howto_table[] = false, /* partial_inplace. */ 0xfc000000, /* src_mask */ 0xfc000000, /* dst_mask */ - false), /* pcrel_offset. */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2, + /* bfd_reloc_code_real_type */ + loongarch_adjust_reloc_bits_l16_h10), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */ + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */ 0, /* rightshift. */ 2, /* size. */ 32, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ + complain_overflow_unsigned, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SOP_POP_32_S_U", /* name. */ false, /* partial_inplace. */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset. */ + 0xffffffff00000000, /* src_mask */ + 0x00000000ffffffff, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */ + loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */ - HOWTO (R_LARCH_ADD8, /* type (47). */ + LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */ 0, /* rightshift. */ 2, /* size. */ 8, /* bitsize. */ @@ -428,10 +504,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_ADD8", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_ADD16, /* type (48). */ + LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */ 0, /* rightshift. */ 2, /* size. */ 16, /* bitsize. */ @@ -442,10 +520,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_ADD16", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_ADD24, /* type (49). */ + LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */ 0, /* rightshift. */ 2, /* size. */ 24, /* bitsize. */ @@ -456,10 +536,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_ADD24", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_ADD32, /* type (50). */ + LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */ 0, /* rightshift. */ 2, /* size. */ 32, /* bitsize. */ @@ -470,10 +552,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_ADD32", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_ADD64, /* type (51). */ + LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */ 0, /* rightshift. */ 4, /* size. */ 64, /* bitsize. */ @@ -485,9 +569,11 @@ static reloc_howto_type howto_table[] = false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ - false), /* pcrel_offset. */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SUB8, /* type (52). */ + LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */ 0, /* rightshift. */ 2, /* size. */ 8, /* bitsize. */ @@ -498,10 +584,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_SUB8", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SUB16, /* type (53). */ + LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */ 0, /* rightshift. */ 2, /* size. */ 16, /* bitsize. */ @@ -512,10 +600,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_SUB16", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SUB24, /* type (54). */ + LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */ 0, /* rightshift. */ 2, /* size. */ 24, /* bitsize. */ @@ -526,10 +616,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_SUB24", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SUB32, /* type (55). */ + LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */ 0, /* rightshift. */ 2, /* size. */ 32, /* bitsize. */ @@ -540,10 +632,12 @@ static reloc_howto_type howto_table[] = "R_LARCH_SUB32", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset. */ + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ - HOWTO (R_LARCH_SUB64, /* type (56). */ + LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */ 0, /* rightshift. */ 4, /* size. */ 64, /* bitsize. */ @@ -555,79 +649,60 @@ static reloc_howto_type howto_table[] = false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ - false), /* pcrel_offset. */ - -}; + false, /* pcrel_offset */ + BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ -struct elf_reloc_map -{ - bfd_reloc_code_real_type bfd_val; - enum elf_loongarch_reloc_type elf_val; -}; + LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */ + 0, /* rightshift. */ + 0, /* size. */ + 0, /* bitsize. */ + false, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_GNU_VTINHERIT", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ -static const struct elf_reloc_map larch_reloc_map[] = -{ - { BFD_RELOC_NONE, R_LARCH_NONE }, - { BFD_RELOC_32, R_LARCH_32 }, - { BFD_RELOC_64, R_LARCH_64 }, - -#define LOONGARCH_reloc_map(r_name) \ - { \ - BFD_RELOC_LARCH_##r_name, R_LARCH_##r_name \ - } - LOONGARCH_reloc_map (TLS_DTPMOD32), - LOONGARCH_reloc_map (TLS_DTPMOD64), - LOONGARCH_reloc_map (TLS_DTPREL32), - LOONGARCH_reloc_map (TLS_DTPREL64), - LOONGARCH_reloc_map (TLS_TPREL32), - LOONGARCH_reloc_map (TLS_TPREL64), - - LOONGARCH_reloc_map (MARK_LA), - LOONGARCH_reloc_map (MARK_PCREL), - LOONGARCH_reloc_map (SOP_PUSH_PCREL), - LOONGARCH_reloc_map (SOP_PUSH_ABSOLUTE), - LOONGARCH_reloc_map (SOP_PUSH_DUP), - LOONGARCH_reloc_map (SOP_PUSH_GPREL), - LOONGARCH_reloc_map (SOP_PUSH_TLS_TPREL), - LOONGARCH_reloc_map (SOP_PUSH_TLS_GOT), - LOONGARCH_reloc_map (SOP_PUSH_TLS_GD), - LOONGARCH_reloc_map (SOP_PUSH_PLT_PCREL), - LOONGARCH_reloc_map (SOP_ASSERT), - LOONGARCH_reloc_map (SOP_NOT), - LOONGARCH_reloc_map (SOP_SUB), - LOONGARCH_reloc_map (SOP_SL), - LOONGARCH_reloc_map (SOP_SR), - LOONGARCH_reloc_map (SOP_ADD), - LOONGARCH_reloc_map (SOP_AND), - LOONGARCH_reloc_map (SOP_IF_ELSE), - LOONGARCH_reloc_map (SOP_POP_32_S_10_5), - LOONGARCH_reloc_map (SOP_POP_32_U_10_12), - LOONGARCH_reloc_map (SOP_POP_32_S_10_12), - LOONGARCH_reloc_map (SOP_POP_32_S_10_16), - LOONGARCH_reloc_map (SOP_POP_32_S_10_16_S2), - LOONGARCH_reloc_map (SOP_POP_32_S_5_20), - LOONGARCH_reloc_map (SOP_POP_32_S_0_5_10_16_S2), - LOONGARCH_reloc_map (SOP_POP_32_S_0_10_10_16_S2), - LOONGARCH_reloc_map (SOP_POP_32_U), - LOONGARCH_reloc_map (ADD8), - LOONGARCH_reloc_map (ADD16), - LOONGARCH_reloc_map (ADD24), - LOONGARCH_reloc_map (ADD32), - LOONGARCH_reloc_map (ADD64), - LOONGARCH_reloc_map (SUB8), - LOONGARCH_reloc_map (SUB16), - LOONGARCH_reloc_map (SUB24), - LOONGARCH_reloc_map (SUB32), - LOONGARCH_reloc_map (SUB64), + LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */ + 0, /* rightshift. */ + 0, /* size. */ + 0, /* bitsize. */ + false, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + NULL, /* special_function. */ + "R_LARCH_GNU_VTENTRY", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* bfd_reloc_code_real_type */ + NULL), /* adjust_reloc_bits */ }; reloc_howto_type * loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) { - size_t i; - for (i = 0; i < ARRAY_SIZE (howto_table); i++) - if (howto_table[i].type == r_type) - return &howto_table[i]; + if(r_type < R_LARCH_count) + { + /* For search table fast. */ + BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count); + + if (loongarch_howto_table[r_type].howto.type == r_type) + return (reloc_howto_type *)&loongarch_howto_table[r_type]; + + BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type); + + for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) + if (loongarch_howto_table[i].howto.type == r_type) + return (reloc_howto_type *)&loongarch_howto_table[i]; + } (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"), abfd, r_type); @@ -636,26 +711,181 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) } reloc_howto_type * -loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, - bfd_reloc_code_real_type code) +loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE (larch_reloc_map); i++) - if (larch_reloc_map[i].bfd_val == code) - return loongarch_elf_rtype_to_howto (abfd, - (int) larch_reloc_map[i].elf_val); + BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count); + + for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) + if (loongarch_howto_table[i].howto.name + && strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0) + return (reloc_howto_type *)&loongarch_howto_table[i]; + + (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"), + abfd, r_name); + bfd_set_error (bfd_error_bad_value); return NULL; } +/* Cost so much. */ reloc_howto_type * -loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) +loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { - unsigned int i; + BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count); - for (i = 0; i < ARRAY_SIZE (howto_table); i++) - if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) - return &howto_table[i]; + for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) + if (loongarch_howto_table[i].bfd_type == code) + return (reloc_howto_type *)&loongarch_howto_table[i]; + + (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"), + abfd, code); + bfd_set_error (bfd_error_bad_value); return NULL; } + +#define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \ + (~((((bfd_vma)0x1) << (bitsize)) - 1)) + +/* Adjust val to perform insn + * BFD_RELOC_LARCH_SOP_POP_32_S_10_5 + * BFD_RELOC_LARCH_SOP_POP_32_S_10_12 + * BFD_RELOC_LARCH_SOP_POP_32_U_10_12 + * BFD_RELOC_LARCH_SOP_POP_32_S_10_16 + * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2 + * BFD_RELOC_LARCH_SOP_POP_32_S_5_20 + * BFD_RELOC_LARCH_SOP_POP_32_U. +*/ + +bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val) +{ + bfd_vma val = *fix_val; + /* Check val low bits if rightshift != 0, before rightshift */ + if (howto->rightshift + && (((0x1UL << howto->rightshift) - 1) & val)) + return false; + + int bitsize = howto->bitsize + howto->rightshift; + + /* Return false if overflow. */ + if (howto->complain_on_overflow == complain_overflow_signed) + { + bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1; + /* If val < 0. */ + if (sig_bit) + { + if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1)) + return false; + } + else + { + if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + return false; + } + } + else if (howto->complain_on_overflow == complain_overflow_unsigned) + { + if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val) + return false; + } + else + return false; + + /* Perform insn bits field. */ + val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift; + val <<= howto->bitpos; + + *fix_val = val; + + return true; +} + +/* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2. */ +bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto, + bfd_vma *fix_val) +{ + bfd_vma val = *fix_val; + /* Check val low bits if rightshift != 0, before rightshift */ + if (howto->rightshift + && (((0x1UL << howto->rightshift) - 1) & val)) + return false; + + /* Return false if overflow. */ + if (howto->complain_on_overflow != complain_overflow_signed) + return false; + + int bitsize = howto->bitsize + howto->rightshift; + bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1; + /* If val < 0. */ + if (sig_bit) + { + if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1)) + return false; + } + else + { + if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + return false; + } + + /* Perform insn bits field. */ + val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift; + + /* Perform insn bits field. 20:16>>16, 15:0<<10 */ + val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f); + + *fix_val = val; + + return true; +} + +/* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2. */ +bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto, + bfd_vma *fix_val) +{ + bfd_vma val = *fix_val; + /* Check val low bits if rightshift != 0, before rightshift */ + if (howto->rightshift + && (((0x1UL << howto->rightshift) - 1) & val)) + return false; + + /* Return false if overflow. */ + if (howto->complain_on_overflow != complain_overflow_signed) + return false; + + int bitsize = howto->bitsize + howto->rightshift; + bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1; + /* If val < 0. */ + if (sig_bit) + { + if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1)) + return false; + } + else + { + if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) + return false; + } + + /* Perform insn bits field. */ + val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift; + + /* Perform insn bits field. 25:16>>16, 15:0<<10 */ + val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff); + + *fix_val = val; + + return true; +} + +bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, + bfd_vma *fix_val) +{ + BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits); + return ((loongarch_reloc_howto_type *) + howto)->adjust_reloc_bits(howto, fix_val); +} diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h index 13699beed01..3b5c6361e06 100644 --- a/bfd/elfxx-loongarch.h +++ b/bfd/elfxx-loongarch.h @@ -29,3 +29,5 @@ loongarch_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); extern reloc_howto_type * loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name); + +bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma *fix_val); diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c index 2fe40adfc85..e1cce22da90 100644 --- a/gas/config/tc-loongarch.c +++ b/gas/config/tc-loongarch.c @@ -25,6 +25,7 @@ #include "elf/loongarch.h" #include "opcode/loongarch.h" #include "obj-elf.h" +#include "bfd/elfxx-loongarch.h" #include #include #include @@ -1068,13 +1069,29 @@ md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) return 0; } +static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf) +{ + reloc_howto_type *howto; + insn_t insn; + howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); + + insn = bfd_getl32 (buf); + + if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val)) + as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); + + insn = (insn & (insn_t)howto->src_mask) + | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val); + + bfd_putl32 (insn, buf); +} + void md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { static int64_t stack_top; static int last_reloc_is_sop_push_pcrel_1 = 0; int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1; - insn_t insn; last_reloc_is_sop_push_pcrel_1 = 0; char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; @@ -1083,17 +1100,17 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL: case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD: case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT: - if (fixP->fx_addsy) - S_SET_THREAD_LOCAL (fixP->fx_addsy); - else - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Relocation against a constant")); - break; case BFD_RELOC_LARCH_SOP_PUSH_PCREL: case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL: if (fixP->fx_addsy == NULL) as_bad_where (fixP->fx_file, fixP->fx_line, _("Relocation against a constant")); + + if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL + || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD + || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT) + S_SET_THREAD_LOCAL (fixP->fx_addsy); + if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL) { last_reloc_is_sop_push_pcrel_1 = 1; @@ -1106,111 +1123,18 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_LARCH_SOP_POP_32_S_10_5: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & ~(uint64_t) 0xf) != 0x0 - && (stack_top & ~(uint64_t) 0xf) != ~(uint64_t) 0xf) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & (~(uint32_t) 0x7c00)) | ((stack_top & 0x1f) << 10); - bfd_putl32 (insn, buf); - break; - - case BFD_RELOC_LARCH_SOP_POP_32_U_10_12: - if (!last_reloc_is_sop_push_pcrel) - break; - if (stack_top & ~(uint64_t) 0xfff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & (~(uint32_t) 0x3ffc00)) | ((stack_top & 0xfff) << 10); - bfd_putl32 (insn, buf); - break; - case BFD_RELOC_LARCH_SOP_POP_32_S_10_12: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & ~(uint64_t) 0x7ff) != 0x0 - && (stack_top & ~(uint64_t) 0x7ff) != ~(uint64_t) 0x7ff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & (~(uint32_t) 0x3ffc00)) | ((stack_top & 0xfff) << 10); - bfd_putl32 (insn, buf); - break; - + case BFD_RELOC_LARCH_SOP_POP_32_U_10_12: case BFD_RELOC_LARCH_SOP_POP_32_S_10_16: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & ~(uint64_t) 0x7fff) != 0x0 - && (stack_top & ~(uint64_t) 0x7fff) != ~(uint64_t) 0x7fff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); - bfd_putl32 (insn, buf); - break; - case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & 0x3) != 0) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - stack_top >>= 2; - if ((stack_top & ~(uint64_t) 0x7fff) != 0x0 - && (stack_top & ~(uint64_t) 0x7fff) != ~(uint64_t) 0x7fff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); - bfd_putl32 (insn, buf); - break; - - case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & 0x3) != 0) - break; - stack_top >>= 2; - if ((stack_top & ~(uint64_t) 0xfffff) != 0x0 - && (stack_top & ~(uint64_t) 0xfffff) != ~(uint64_t) 0xfffff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = ((insn & 0xfc0003e0) - | ((stack_top & 0xffff) << 10) - | ((stack_top & 0x1f0000) >> 16)); - bfd_putl32 (insn, buf); - break; - case BFD_RELOC_LARCH_SOP_POP_32_S_5_20: - if (!last_reloc_is_sop_push_pcrel) - break; - if ((stack_top & ~(uint64_t) 0x7ffff) != 0x0 - && (stack_top & ~(uint64_t) 0x7ffff) != ~(uint64_t) 0x7ffff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = (insn & (~(uint32_t) 0x1ffffe0)) | ((stack_top & 0xfffff) << 5); - bfd_putl32 (insn, buf); - break; - + case BFD_RELOC_LARCH_SOP_POP_32_U: + case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2: case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2: if (!last_reloc_is_sop_push_pcrel) break; - if ((stack_top & 0x3) != 0) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - stack_top >>= 2; - if ((stack_top & ~(uint64_t) 0x1ffffff) != 0x0 - && (stack_top & ~(uint64_t) 0x1ffffff) != ~(uint64_t) 0x1ffffff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - insn = bfd_getl32 (buf); - insn = ((insn & 0xfc000000) - | ((stack_top & 0xffff) << 10) - | ((stack_top & 0x3ff0000) >> 16)); - bfd_putl32 (insn, buf); - break; - case BFD_RELOC_LARCH_SOP_POP_32_U: - if (!last_reloc_is_sop_push_pcrel) - break; - if (stack_top & ~(uint64_t) 0xffffffff) - as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); - bfd_putl32 (stack_top, buf); + fix_reloc_insn (fixP, (bfd_vma)stack_top, buf); break; case BFD_RELOC_64: