123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891 |
- /* 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, 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 loongarch_reloc_howto_type loongarch_howto_table[] =
- {
- /* No relocation. */
- 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. */
- 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. */
- 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. */
- 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. */
- 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. */
- 3, /* 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. */
- 2, /* 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. */
- 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. */
- 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. */
- 2, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 4, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 2, /* 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. */
- 4, /* 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);
- }
|