binutils-gdb/bfd/elfxx-loongarch.c
Alan Modra 5d0feb989c Revert reloc howto nits
The "HOWTO size encoding" patch put 1 as the HOWTO size arg for
numerous howtos that are unused, describe dynamic relocs, are markers,
or otherwise are special purpose reloc howtos that don't care about
the size.  The idea was to ensure no howto changed by inspecting
object files.  Revert those changes, making them zero size.

	* coff-alpha.c: Give special purpose reloc howtos a size of zero.
	* coff-mcore.c, * elf-hppa.h, * elf-m10300.c, * elf32-arm.c,
	* elf32-csky.c, * elf32-m32c.c, * elf32-m68k.c, * elf32-mep.c,
	* elf32-mips.c, * elf32-ppc.c, * elf32-rx.c, * elf32-s390.c,
	* elf32-spu.c, * elf32-tic6x.c, * elf32-tilepro.c, *elf32-vax.c,
	* elf32-xtensa.c, * elf64-alpha.c, * elf64-mips.c,
	* elf64-mmix.c, * elf64-ppc.c, * elf64-s390.c, * elfn32-mips.c,
	* elfxx-loongarch.c, * elfxx-riscv.c, * elfxx-sparc.c,
	* elfxx-tilegx.c, * som.c, * vms-alpha.c: Likewise.
2022-06-08 21:33:00 +09:30

892 lines
30 KiB
C

/* LoongArch-specific support for ELF.
Copyright (C) 2021-2022 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 <http://www.gnu.org/licenses/>. */
#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 *);
}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 }
#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 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 */
/* 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 */
/* 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 */
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 */
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 */
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 */
/* 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
/* 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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
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. */
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 */
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. */
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. */
0xfc000000, /* src_mask */
0xfc000000, /* dst_mask */
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 */
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 */
loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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)
{
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);
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);
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);
}