/* LoongArch-specific support for ELF. Copyright (C) 2021-2023 Free Software Foundation, Inc. Contributed by Loongson Ltd. Based on RISC-V target. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING3. If not, see . */ #include "sysdep.h" #include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/loongarch.h" #include "elfxx-loongarch.h" #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 *); const char *larch_reloc_type_name; } loongarch_reloc_howto_type; #define LOONGARCH_DEFAULT_HOWTO(r_name) \ { HOWTO (R_LARCH_##r_name, 0, 4, 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, NULL } #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \ name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc,lname) \ { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \ inplace, src_mask, dst_mask, pcrel_off), btype, afunc, lname } #define LOONGARCH_EMPTY_HOWTO(C) \ { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL } static bool reloc_bits (reloc_howto_type *howto, bfd_vma *val); static bool reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val); static bool reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val); static bool reloc_bits_b26 (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 loongarch_reloc_howto_type loongarch_howto_table[] = { /* No relocation. */ LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */ 0, /* rightshift */ 0, /* 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 */ NULL), /* larch_reloc_type_name */ /* 32 bit relocation. */ LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ /* 64 bit relocation. */ LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */ 0, /* rightshift */ 8, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */ 0, /* rightshift */ 8, /* 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 */ NULL), /* larch_reloc_type_name */ /* Dynamic TLS relocations. */ LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */ 0, /* rightshift */ 8, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */ 0, /* rightshift */ 8, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */ 0, /* rightshift */ 8, /* 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */ 0, /* rightshift */ 4, /* 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 */ NULL), /* larch_reloc_type_name */ 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. */ 0, /* size. */ 0, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_MARK_LA", /* name. */ false, /* partial_inplace. */ 0, /* src_mask. */ 0, /* dst_mask. */ false, /* pcrel_offset */ BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */ 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_MARK_PCREL", /* name. */ false, /* partial_inplace. */ 0, /* src_mask. */ 0, /* dst_mask. */ false, /* pcrel_offset */ BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */ 2, /* rightshift. */ 4, /* size. */ 32, /* bitsize. */ true /* FIXME: somewhat use this. */, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SOP_PUSH_PCREL", /* name. */ false, /* partial_inplace. */ 0x03ffffff, /* src_mask. */ 0x03ffffff, /* dst_mask. */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ /* type 23-37. */ 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. */ 4, /* 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 */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */ 0, /* rightshift. */ 4, /* 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 */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */ 0, /* rightshift. */ 4, /* 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 */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */ 0, /* rightshift. */ 4, /* 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 */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */ 2, /* rightshift. */ 4, /* 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 */ reloc_bits_b16, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */ 0, /* rightshift. */ 4, /* 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 */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, /* type (44). */ 2, /* rightshift. */ 4, /* 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 */ reloc_bits_b21, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */ 2, /* rightshift. */ 4, /* size. */ 26, /* 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_10_10_16_S2", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x03ffffff, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* bfd_reloc_code_real_type */ reloc_bits_b26, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */ 0, /* rightshift. */ 4, /* size. */ 32, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_unsigned, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SOP_POP_32_S_U", /* name. */ false, /* partial_inplace. */ 0xffffffff00000000, /* src_mask */ 0x00000000ffffffff, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */ 0, /* rightshift. */ 4, /* size. */ 8, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ADD8", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */ 0, /* rightshift. */ 4, /* size. */ 16, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ADD16", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */ 0, /* rightshift. */ 4, /* size. */ 24, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ADD24", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */ 0, /* rightshift. */ 4, /* size. */ 32, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ADD32", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */ 0, /* rightshift. */ 8, /* size. */ 64, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ADD64", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */ 0, /* rightshift. */ 4, /* size. */ 8, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SUB8", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */ 0, /* rightshift. */ 4, /* size. */ 16, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SUB16", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */ 0, /* rightshift. */ 4, /* size. */ 24, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SUB24", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */ 0, /* rightshift. */ 4, /* size. */ 32, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SUB32", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */ 0, /* rightshift. */ 8, /* size. */ 64, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_SUB64", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ 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 */ NULL), /* larch_reloc_type_name */ 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 */ NULL), /* larch_reloc_type_name */ LOONGARCH_EMPTY_HOWTO (59), LOONGARCH_EMPTY_HOWTO (60), LOONGARCH_EMPTY_HOWTO (61), LOONGARCH_EMPTY_HOWTO (62), LOONGARCH_EMPTY_HOWTO (63), /* New reloc types. */ LOONGARCH_HOWTO (R_LARCH_B16, /* type (64). */ 2, /* rightshift. */ 4, /* size. */ 16, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_B16", /* name. */ false, /* partial_inplace. */ 0x3fffc00, /* src_mask */ 0x3fffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_B16, /* bfd_reloc_code_real_type */ reloc_bits_b16, /* adjust_reloc_bits */ "b16"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_B21, /* type (65). */ 2, /* rightshift. */ 4, /* size. */ 21, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_B21", /* name. */ false, /* partial_inplace. */ 0xfc0003e0, /* src_mask */ 0xfc0003e0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_B21, /* bfd_reloc_code_real_type */ reloc_bits_b21, /* adjust_reloc_bits */ "b21"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_B26, /* type (66). */ 2, /* rightshift. */ 4, /* size. */ 26, /* bitsize. */ false, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_B26", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x03ffffff, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_B26, /* bfd_reloc_code_real_type */ reloc_bits_b26, /* adjust_reloc_bits */ "b26"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ABS_HI20, /* type (67). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ABS_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ABS_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "abs_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ABS_LO12, /* type (68). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_unsigned, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ABS_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ABS_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "abs_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ABS64_LO20, /* type (69). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ABS64_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ABS64_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "abs64_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_ABS64_HI12, /* type (70). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_ABS64_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_ABS64_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "abs64_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_PCALA_HI20, /* type (71). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_PCALA_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_PCALA_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "pc_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_PCALA_LO12, /* type (72). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_PCALA_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_PCALA_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "pc_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20, /* type (73). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_PCALA64_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_PCALA64_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "pc64_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12, /* type (74). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_PCALA64_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_PCALA64_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "pc64_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20, /* type (75). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT_PC_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT_PC_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got_pc_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12, /* type (76). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT_PC_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT_PC_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got_pc_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20, /* type (77). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT64_PC_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT64_PC_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got64_pc_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12, /* type (78). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT64_PC_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got64_pc_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT64_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got64_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_GOT64_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "got64_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LE_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "le_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LE_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "le_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LE64_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "le64_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LE64_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "le64_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE_PC_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie_pc_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_unsigned, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE_PC_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie_pc_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE64_PC_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie64_pc_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE64_PC_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie64_pc_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */ 0, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE_LO12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie_lo12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */ 32, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE64_LO20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie64_lo20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */ 52, /* rightshift. */ 4, /* size. */ 12, /* bitsize. */ false, /* pc_relative. */ 10, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_IE64_HI12", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x3ffc00, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ie64_hi12"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LD_PC_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ld_pc_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_LD_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "ld_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_GD_PC_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "gd_pc_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */ 12, /* rightshift. */ 4, /* size. */ 20, /* bitsize. */ false, /* pc_relative. */ 5, /* bitpos. */ complain_overflow_signed, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_TLS_GD_HI20", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0x1ffffe0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */ reloc_bits, /* adjust_reloc_bits */ "gd_hi20"), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */ 0, /* rightshift. */ 4, /* size. */ 32, /* bitsize. */ true, /* pc_relative. */ 0, /* bitpos. */ complain_overflow_dont, /* complain_on_overflow. */ bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_32_PCREL", /* name. */ false, /* partial_inplace. */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */ 0, /* rightshift */ 1, /* size */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_LARCH_RELAX", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */ NULL, /* adjust_reloc_bits */ NULL), /* larch_reloc_type_name */ }; reloc_howto_type * loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) { 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]; 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); bfd_set_error (bfd_error_bad_value); return NULL; } reloc_howto_type * loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) { 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_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) { BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count); /* Fast search for new reloc types. */ if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX) { BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16 == R_LARCH_RELAX - R_LARCH_B16); loongarch_reloc_howto_type *ht = NULL; ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16]; BFD_ASSERT (ht->bfd_type == code); return (reloc_howto_type *)ht; } 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; } bfd_reloc_code_real_type loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *l_r_name) { for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) { loongarch_reloc_howto_type *lht = &loongarch_howto_table[i]; if ((NULL != lht->larch_reloc_type_name) && (0 == strcmp (lht->larch_reloc_type_name, l_r_name))) return lht->bfd_type; } (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"), abfd, l_r_name); bfd_set_error (bfd_error_bad_value); return BFD_RELOC_NONE; } /* Functions for reloc bits field. 1. Signed extend *fix_val. 2. Return false if overflow. */ #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_5_20 BFD_RELOC_LARCH_SOP_POP_32_U. */ static bool reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val) { bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift; /* Perform insn bits field. */ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); val <<= howto->bitpos; *fix_val = (bfd_vma)val; return true; } /* Adjust val to perform insn R_LARCH_SOP_POP_32_S_10_16_S2 R_LARCH_B16. */ static bool reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val) { if (howto->complain_on_overflow != complain_overflow_signed) return false; bfd_signed_vma val = *fix_val; /* Judge whether 4 bytes align. */ if (val & ((0x1UL << howto->rightshift) - 1)) return false; int bitsize = howto->bitsize + howto->rightshift; bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1; /* If val < 0, sign bit is 1. */ if (sig_bit) { /* Signed bits is 1. */ if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1)) return false; } else { /* Signed bits is 0. */ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val) return false; } /* Perform insn bits field. */ val >>= howto->rightshift; val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); val <<= howto->bitpos; *fix_val = val; return true; } /* Reloc type : R_LARCH_SOP_POP_32_S_0_5_10_16_S2 R_LARCH_B21. */ static bool reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val) { if (howto->complain_on_overflow != complain_overflow_signed) return false; bfd_signed_vma val = *fix_val; if (val & ((0x1UL << howto->rightshift) - 1)) return false; int bitsize = howto->bitsize + howto->rightshift; bfd_signed_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) & val) return false; } /* Perform insn bits field. */ val >>= howto->rightshift; val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); /* Perform insn bits field. 15:0<<10, 20:16>>16. */ 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 R_LARCH_B26. */ static bool reloc_bits_b26 (reloc_howto_type *howto, bfd_vma *fix_val) { /* Return false if overflow. */ if (howto->complain_on_overflow != complain_overflow_signed) return false; bfd_signed_vma val = *fix_val; if (val & ((0x1UL << howto->rightshift) - 1)) return false; int bitsize = howto->bitsize + howto->rightshift; bfd_signed_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) & val) return false; } /* Perform insn bits field. */ val >>= howto->rightshift; val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); /* 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); }