From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7867) id 9D84138418BD; Mon, 25 Jul 2022 02:00:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9D84138418BD Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: liu & zhensong To: bfd-cvs@sourceware.org Subject: [binutils-gdb] bfd: Add supported for LoongArch new relocations. X-Act-Checkin: binutils-gdb X-Git-Author: liuzhensong X-Git-Refname: refs/heads/master X-Git-Oldrev: 5d471bd907be60e9858b22cdf4fd10ddc0f6ee1a X-Git-Newrev: 6d13722a97cee3fd397e116bde3bcedbb1e220be Message-Id: <20220725020046.9D84138418BD@sourceware.org> Date: Mon, 25 Jul 2022 02:00:46 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Jul 2022 02:00:46 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D6d13722a97ce= e3fd397e116bde3bcedbb1e220be commit 6d13722a97cee3fd397e116bde3bcedbb1e220be Author: liuzhensong Date: Mon Jul 11 15:11:03 2022 +0800 bfd: Add supported for LoongArch new relocations. =20 Define new reloc types according to linker needs. =20 include/elf/ loongarch.h =20 bfd/ bfd-in2.h libbfd.h reloc.c elfnn-loongarch.c elfxx-loongarch.c elfxx-loongarch.h Diff: --- bfd/bfd-in2.h | 36 ++ bfd/elfnn-loongarch.c | 1202 ++++++++++++++++++++++++++--------------- bfd/elfxx-loongarch.c | 1354 ++++++++++++++++++++++++++++++++++++-------= ---- bfd/elfxx-loongarch.h | 4 + bfd/libbfd.h | 36 ++ bfd/reloc.c | 79 +++ include/elf/loongarch.h | 136 +++++ 7 files changed, 2095 insertions(+), 752 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 4e1182e93d4..91e6ad76b9a 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6274,6 +6274,42 @@ assembler and not (currently) written to any object = files. */ BFD_RELOC_LARCH_SUB24, BFD_RELOC_LARCH_SUB32, BFD_RELOC_LARCH_SUB64, + BFD_RELOC_LARCH_B16, + BFD_RELOC_LARCH_B21, + BFD_RELOC_LARCH_B26, + BFD_RELOC_LARCH_ABS_HI20, + BFD_RELOC_LARCH_ABS_LO12, + BFD_RELOC_LARCH_ABS64_LO20, + BFD_RELOC_LARCH_ABS64_HI12, + BFD_RELOC_LARCH_PCALA_HI20, + BFD_RELOC_LARCH_PCALA_LO12, + BFD_RELOC_LARCH_PCALA64_LO20, + BFD_RELOC_LARCH_PCALA64_HI12, + BFD_RELOC_LARCH_GOT_PC_HI20, + BFD_RELOC_LARCH_GOT_PC_LO12, + BFD_RELOC_LARCH_GOT64_PC_LO20, + BFD_RELOC_LARCH_GOT64_PC_HI12, + BFD_RELOC_LARCH_GOT_HI20, + BFD_RELOC_LARCH_GOT_LO12, + BFD_RELOC_LARCH_GOT64_LO20, + BFD_RELOC_LARCH_GOT64_HI12, + BFD_RELOC_LARCH_TLS_LE_HI20, + BFD_RELOC_LARCH_TLS_LE_LO12, + BFD_RELOC_LARCH_TLS_LE64_LO20, + BFD_RELOC_LARCH_TLS_LE64_HI12, + BFD_RELOC_LARCH_TLS_IE_PC_HI20, + BFD_RELOC_LARCH_TLS_IE_PC_LO12, + BFD_RELOC_LARCH_TLS_IE64_PC_LO20, + BFD_RELOC_LARCH_TLS_IE64_PC_HI12, + BFD_RELOC_LARCH_TLS_IE_HI20, + BFD_RELOC_LARCH_TLS_IE_LO12, + BFD_RELOC_LARCH_TLS_IE64_LO20, + BFD_RELOC_LARCH_TLS_IE64_HI12, + BFD_RELOC_LARCH_TLS_LD_PC_HI20, + BFD_RELOC_LARCH_TLS_LD_HI20, + BFD_RELOC_LARCH_TLS_GD_PC_HI20, + BFD_RELOC_LARCH_TLS_GD_HI20, + BFD_RELOC_LARCH_RELAX, BFD_RELOC_UNUSED }; =20 typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 5b44901b9e0..21710dcb3fb 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -122,14 +122,16 @@ struct loongarch_elf_link_hash_table =20 #define elf_backend_plt_readonly 1 =20 -#define elf_backend_want_plt_sym 0 +#define elf_backend_want_plt_sym 1 #define elf_backend_plt_alignment 4 #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_sym 1 =20 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1) =20 #define elf_backend_want_dynrelro 1 +#define elf_backend_rela_normal 1 =20 /* Generate a PLT header. */ =20 @@ -607,9 +609,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, struct elf_link_hash_entry *h; Elf_Internal_Sym *isym =3D NULL; =20 - int need_dynreloc; - int only_need_pcrel; - r_symndx =3D ELFNN_R_SYM (rel->r_info); r_type =3D ELFNN_R_TYPE (rel->r_info); =20 @@ -622,7 +621,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, if (r_symndx < symtab_hdr->sh_info) { /* A local symbol. */ - isym =3D bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); + isym =3D bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym =3D=3D NULL) return false; =20 @@ -655,17 +654,20 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_lin= k_info *info, if (htab->elf.dynobj =3D=3D NULL) htab->elf.dynobj =3D abfd; =20 + /* Create 'irelifunc' in PIC object. */ + if (bfd_link_pic (info) + && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) + return false; + /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ + else if (!htab->elf.splt + && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) + return false; /* Create the ifunc sections, iplt and ipltgot, for static executables. */ if ((r_type =3D=3D R_LARCH_64 || r_type =3D=3D R_LARCH_32) && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) return false; =20 - if (!htab->elf.splt - && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) - /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ - return false; - if (h->plt.refcount < 0) h->plt.refcount =3D 0; h->plt.refcount++; @@ -674,17 +676,27 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_lin= k_info *info, elf_tdata (info->output_bfd)->has_gnu_osabi |=3D elf_gnu_osabi_ifunc; } =20 - need_dynreloc =3D 0; - only_need_pcrel =3D 0; + int need_dynreloc =3D 0; + int only_need_pcrel =3D 0; + switch (r_type) { + case R_LARCH_GOT_PC_HI20: + case R_LARCH_GOT_HI20: case R_LARCH_SOP_PUSH_GPREL: + /* For la.global. */ + if (h) + h->pointer_equality_needed =3D 1; if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h, r_symndx, GOT_NORMAL)) return false; break; =20 + case R_LARCH_TLS_LD_PC_HI20: + case R_LARCH_TLS_LD_HI20: + case R_LARCH_TLS_GD_PC_HI20: + case R_LARCH_TLS_GD_HI20: case R_LARCH_SOP_PUSH_TLS_GD: if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h, r_symndx, @@ -692,6 +704,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, return false; break; =20 + case R_LARCH_TLS_IE_PC_HI20: + case R_LARCH_TLS_IE_HI20: case R_LARCH_SOP_PUSH_TLS_GOT: if (bfd_link_pic (info)) /* May fail for lazy-bind. */ @@ -703,6 +717,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, return false; break; =20 + case R_LARCH_TLS_LE_HI20: case R_LARCH_SOP_PUSH_TLS_TPREL: if (!bfd_link_executable (info)) return false; @@ -715,6 +730,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, return false; break; =20 + case R_LARCH_ABS_HI20: case R_LARCH_SOP_PUSH_ABSOLUTE: if (h !=3D NULL) /* If this reloc is in a read-only section, we might @@ -726,16 +742,45 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_lin= k_info *info, h->non_got_ref =3D 1; break; =20 - case R_LARCH_SOP_PUSH_PCREL: + case R_LARCH_PCALA_HI20: if (h !=3D NULL) { h->non_got_ref =3D 1; + h->pointer_equality_needed =3D 1; + } + + break; + + case R_LARCH_B21: + case R_LARCH_B16: + case R_LARCH_B26: + if (h !=3D NULL) + { + h->needs_plt =3D 1; + if (!bfd_link_pic (info)) + h->non_got_ref =3D 1; + + /* We try to create PLT stub for all non-local function. */ + if (h->plt.refcount < 0) + h->plt.refcount =3D 0; + h->plt.refcount++; + } + + break; + + case R_LARCH_SOP_PUSH_PCREL: + if (h !=3D NULL) + { + if (!bfd_link_pic (info)) + h->non_got_ref =3D 1; =20 /* We try to create PLT stub for all non-local function. */ if (h->plt.refcount < 0) h->plt.refcount =3D 0; h->plt.refcount++; + h->pointer_equality_needed =3D 1; } + break; =20 case R_LARCH_SOP_PUSH_PLT_PCREL: @@ -762,6 +807,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, case R_LARCH_JUMP_SLOT: case R_LARCH_32: case R_LARCH_64: + need_dynreloc =3D 1; =20 /* If resolved symbol is defined in this object, @@ -774,9 +820,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_= info *info, Thus, only under pde, it needs pcrel only. We discard it. */ only_need_pcrel =3D bfd_link_pde (info); =20 - if (h !=3D NULL) - h->non_got_ref =3D 1; - if (h !=3D NULL && (!bfd_link_pic (info) || h->type =3D=3D STT_GNU_IFUNC)) @@ -899,9 +942,7 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_in= fo *info, struct elf_link_hash_entry *h) { struct loongarch_elf_link_hash_table *htab; - struct loongarch_elf_link_hash_entry *eh; bfd *dynobj; - asection *s, *srel; =20 htab =3D loongarch_elf_hash_table (info); BFD_ASSERT (htab !=3D NULL); @@ -951,73 +992,9 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_i= nfo *info, return true; } =20 - /* This is a reference to a symbol defined by a dynamic object which - is not a function. */ - - /* If we are creating a shared library, we must presume that the - only references to the symbol are via the global offset table. - For such cases we need not do anything here; the relocations will - be handled correctly by relocate_section. */ - if (bfd_link_dll (info)) - return true; - - /* If there are no references to this symbol that do not use the - GOT, we don't need to generate a copy reloc. */ - if (!h->non_got_ref) - return true; - - /* If -z nocopyreloc was given, we won't generate them either. */ - if (info->nocopyreloc) - { - h->non_got_ref =3D 0; - return true; - } - - /* If we don't find any dynamic relocs in read-only sections, then - we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (!readonly_dynrelocs (h)) - { - h->non_got_ref =3D 0; - return true; - } - - /* We must allocate the symbol in our .dynbss section, which will - become part of the .bss section of the executable. There will be - an entry for this symbol in the .dynsym section. The dynamic - object will contain position independent code, so all references - from the dynamic object to this symbol will go through the global - offset table. The dynamic linker will use the .dynsym entry to - determine the address it must put in the global offset table, so - both the dynamic object and the regular object will refer to the - same memory location for the variable. */ - - /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker - to copy the initial value out of the dynamic object and into the - runtime process image. We need to remember the offset into the - .rel.bss section we are going to use. */ - eh =3D (struct loongarch_elf_link_hash_entry *) h; - if (eh->tls_type & ~GOT_NORMAL) - { - s =3D htab->sdyntdata; - srel =3D htab->elf.srelbss; - } - else if ((h->root.u.def.section->flags & SEC_READONLY) !=3D 0) - { - s =3D htab->elf.sdynrelro; - srel =3D htab->elf.sreldynrelro; - } - else - { - s =3D htab->elf.sdynbss; - srel =3D htab->elf.srelbss; - } - if ((h->root.u.def.section->flags & SEC_ALLOC) !=3D 0 && h->size !=3D 0) - { - srel->size +=3D sizeof (ElfNN_External_Rela); - h->needs_copy =3D 1; - } - - return _bfd_elf_adjust_dynamic_copy (info, h, s); + /* R_LARCH_COPY is not adept glibc, not to generate. */ + /* Can not print anything, because make check ld. */ + return true; } =20 /* Allocate space in .plt, .got and associated reloc sections for @@ -1039,6 +1016,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, vo= id *inf) =20 info =3D (struct bfd_link_info *) inf; htab =3D loongarch_elf_hash_table (info); + bool dyn =3D htab->elf.dynamic_sections_created; BFD_ASSERT (htab !=3D NULL); =20 do @@ -1052,9 +1030,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, v= oid *inf) =20 if (htab->elf.splt) { - if (h->dynindx =3D=3D -1 && !h->forced_local - && !bfd_elf_link_record_dynamic_symbol (info, h)) - return false; + if (h->dynindx =3D=3D -1 && !h->forced_local && dyn + && h->root.type =3D=3D bfd_link_hash_undefweak) + { + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return false; + } =20 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h) && h->type !=3D STT_GNU_IFUNC) @@ -1090,7 +1071,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, vo= id *inf) location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (!bfd_link_pic(info) + if (!bfd_link_pic (info) && !h->def_regular) { h->root.u.def.section =3D plt; @@ -1107,51 +1088,68 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, = void *inf) if (0 < h->got.refcount) { asection *s; - bool dyn; int tls_type =3D loongarch_elf_hash_entry (h)->tls_type; =20 /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx =3D=3D -1 && !h->forced_local) + if (h->dynindx =3D=3D -1 && !h->forced_local && dyn + && h->root.type =3D=3D bfd_link_hash_undefweak) { - if (SYMBOL_REFERENCES_LOCAL (info, h) - && (ELF_ST_VISIBILITY (h->other) !=3D STV_DEFAULT) - && h->start_stop) - { - /* The pr21964-4. do nothing. */ - } - else - { - if( !bfd_elf_link_record_dynamic_symbol (info, h)) - return false; - } + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return false; } =20 s =3D htab->elf.sgot; h->got.offset =3D s->size; - dyn =3D htab->elf.dynamic_sections_created; if (tls_type & (GOT_TLS_GD | GOT_TLS_IE)) { /* TLS_GD needs two dynamic relocs and two GOT slots. */ if (tls_type & GOT_TLS_GD) { s->size +=3D 2 * GOT_ENTRY_SIZE; - htab->elf.srelgot->size +=3D 2 * sizeof (ElfNN_External_Rela); + if (bfd_link_executable (info)) + { + /* Link exe and not defined local. */ + if (!SYMBOL_REFERENCES_LOCAL (info, h)) + htab->elf.srelgot->size +=3D 2 * sizeof (ElfNN_External_Rela); + } + else + { + if (SYMBOL_REFERENCES_LOCAL (info, h)) + htab->elf.srelgot->size +=3D sizeof (ElfNN_External_Rela); + else + htab->elf.srelgot->size +=3D 2 * sizeof (ElfNN_External_Rela); + } } =20 /* TLS_IE needs one dynamic reloc and one GOT slot. */ if (tls_type & GOT_TLS_IE) { s->size +=3D GOT_ENTRY_SIZE; - htab->elf.srelgot->size +=3D sizeof (ElfNN_External_Rela); + + if (bfd_link_executable (info)) + { + /* Link exe and not defined local. */ + if (!SYMBOL_REFERENCES_LOCAL (info, h)) + htab->elf.srelgot->size +=3D sizeof (ElfNN_External_Rela); + } + else + { + htab->elf.srelgot->size +=3D sizeof (ElfNN_External_Rela); + } } } else { s->size +=3D GOT_ENTRY_SIZE; - if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) - && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) - || h->type =3D=3D STT_GNU_IFUNC) + if ((ELF_ST_VISIBILITY (h->other) =3D=3D STV_DEFAULT + || h->root.type !=3D bfd_link_hash_undefweak) + && (bfd_link_pic (info) + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), + h)) + && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) + /* Undefined weak symbol in static PIE resolves to 0 without + any dynamic relocations. */ htab->elf.srelgot->size +=3D sizeof (ElfNN_External_Rela); } } @@ -1161,7 +1159,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, v= oid *inf) if (h->dyn_relocs =3D=3D NULL) return true; =20 - if (SYMBOL_REFERENCES_LOCAL (info, h)) + /* Extra dynamic relocate, + * R_LARCH_64 + * R_LARCH_TLS_DTPRELNN + * R_LARCH_JUMP_SLOT + * R_LARCH_NN. */ + + if (SYMBOL_CALLS_LOCAL (info, h)) { struct elf_dyn_relocs **pp; =20 @@ -1178,13 +1182,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, = void *inf) =20 if (h->root.type =3D=3D bfd_link_hash_undefweak) { - if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) + if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h) + || ELF_ST_VISIBILITY (h->other) !=3D STV_DEFAULT + || (!bfd_link_pic (info) && h->non_got_ref)) h->dyn_relocs =3D NULL; - else if (h->dynindx =3D=3D -1 && !h->forced_local - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ - && !bfd_elf_link_record_dynamic_symbol (info, h)) - return false; + else if (h->dynindx =3D=3D -1 && !h->forced_local) + { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return false; + + if (h->dynindx =3D=3D -1) + h->dyn_relocs =3D NULL; + } } =20 for (p =3D h->dyn_relocs; p !=3D NULL; p =3D p->next) @@ -1200,8 +1211,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, vo= id *inf) ifunc dynamic relocs. */ =20 static bool -elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, - void *inf) +elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; /* An example of a bfd_link_hash_indirect symbol is versioned @@ -1223,14 +1233,14 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct el= f_link_hash_entry *h, =20 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ - if (h->type =3D=3D STT_GNU_IFUNC - && h->def_regular) + if (h->type =3D=3D STT_GNU_IFUNC && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, PLT_ENTRY_SIZE, PLT_HEADER_SIZE, GOT_ENTRY_SIZE, false); + return true; } =20 @@ -1238,7 +1248,7 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_= link_hash_entry *h, ifunc dynamic relocs. */ =20 static bool -elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf) +elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf) { struct elf_link_hash_entry *h =3D (struct elf_link_hash_entry *) *slot; =20 @@ -1249,7 +1259,7 @@ elfNN_loongarch_allocate_local_dynrelocs (void **slot= , void *inf) || h->root.type !=3D bfd_link_hash_defined) abort (); =20 - return elfNN_loongarch_allocate_ifunc_dynrelocs (h, inf); + return elfNN_allocate_ifunc_dynrelocs (h, inf); } =20 /* Set DF_TEXTREL if we find any dynamic relocs that apply to @@ -1367,16 +1377,21 @@ loongarch_elf_size_dynamic_sections (bfd *output_bf= d, if (0 < *local_got) { *local_got =3D s->size; - s->size +=3D GOT_ENTRY_SIZE; =20 + /* TLS gd use two got. */ if (*local_tls_type & GOT_TLS_GD) + s->size +=3D GOT_ENTRY_SIZE * 2; + else + /* Normal got, tls ie/ld use one got. */ s->size +=3D GOT_ENTRY_SIZE; =20 - /* If R_LARCH_RELATIVE. */ - if (bfd_link_pic (info) - /* Or R_LARCH_TLS_DTPRELNN or R_LARCH_TLS_TPRELNN. */ - || (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE))) - srel->size +=3D sizeof (ElfNN_External_Rela); + if (bfd_link_executable (info) + && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE))) + ;/* Do nothing. */ + else + { + srel->size +=3D sizeof (ElfNN_External_Rela); + } } else *local_got =3D MINUS_ONE; @@ -1389,11 +1404,11 @@ loongarch_elf_size_dynamic_sections (bfd *output_bf= d, =20 /* Allocate global ifunc sym .plt and .got entries, and space for global ifunc sym dynamic relocs. */ - elf_link_hash_traverse (&htab->elf, elfNN_loongarch_allocate_ifunc_dynre= locs, info); + elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info= ); =20 /* Allocate .plt and .got entries, and space for local ifunc symbols. */ htab_traverse (htab->loc_hash_table, - (void *) elfNN_loongarch_allocate_local_dynrelocs, info); + (void *) elfNN_allocate_local_ifunc_dynrelocs, info); =20 /* Don't allocate .got.plt section if there are no PLT. */ if (htab->elf.sgotplt && htab->elf.sgotplt->size =3D=3D GOTPLT_HEADER_SI= ZE @@ -1542,10 +1557,13 @@ loongarch_top (int64_t *val) static void loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) { + BFD_ASSERT (s && s->contents); const struct elf_backend_data *bed; bfd_byte *loc; =20 bed =3D get_elf_backend_data (abfd); + if (!(s->size > s->reloc_count * bed->s->sizeof_rela)) + BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela); loc =3D s->contents + (s->reloc_count++ * bed->s->sizeof_rela); bed->s->swap_reloca_out (abfd, rel, loc); } @@ -1594,19 +1612,15 @@ loongarch_reloc_rewrite_imm_insn (const Elf_Interna= l_Rela *rel, return bfd_reloc_ok; } =20 -/* Emplace a static relocation. */ - static bfd_reloc_status_type perform_relocation (const Elf_Internal_Rela *rel, asection *input_section, reloc_howto_type *howto, bfd_vma value, bfd *input_bfd, bfd_byte *contents) { - uint32_t insn1; int64_t opr1, opr2, opr3; bfd_reloc_status_type r =3D bfd_reloc_ok; int bits =3D bfd_get_reloc_size (howto) * 8; =20 - switch (ELFNN_R_TYPE (rel->r_info)) { case R_LARCH_SOP_PUSH_PCREL: @@ -1679,6 +1693,8 @@ perform_relocation (const Elf_Internal_Rela *rel, ase= ction *input_section, case R_LARCH_SOP_POP_32_S_10_12: case R_LARCH_SOP_POP_32_S_10_16: case R_LARCH_SOP_POP_32_S_10_16_S2: + case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: + case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: case R_LARCH_SOP_POP_32_S_5_20: case R_LARCH_SOP_POP_32_U_10_12: case R_LARCH_SOP_POP_32_U: @@ -1694,67 +1710,6 @@ perform_relocation (const Elf_Internal_Rela *rel, as= ection *input_section, contents, (bfd_vma)opr1); break; =20 - case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: - { - r =3D loongarch_pop (&opr1); - if (r !=3D bfd_reloc_ok) - break; - - if ((opr1 & 0x3) !=3D 0) - { - r =3D bfd_reloc_overflow; - break; - } - - uint32_t imm =3D opr1 >> howto->rightshift; - if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) !=3D (~0xfffffU))) - { - r =3D bfd_reloc_overflow; - break; - } - r =3D loongarch_check_offset (rel, input_section); - if (r !=3D bfd_reloc_ok) - break; - - insn1 =3D bfd_get (bits, input_bfd, contents + rel->r_offset); - insn1 =3D (insn1 & howto->src_mask) - | ((imm & 0xffffU) << 10) - | ((imm & 0x1f0000U) >> 16); - bfd_put (bits, input_bfd, insn1, contents + rel->r_offset); - break; - } - - case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: - { - r =3D loongarch_pop (&opr1); - if (r !=3D bfd_reloc_ok) - break; - - if ((opr1 & 0x3) !=3D 0) - { - r =3D bfd_reloc_overflow; - break; - } - - uint32_t imm =3D opr1 >> howto->rightshift; - if ((imm & (~0x1ffffffU)) && (imm & (~0x1ffffffU)) !=3D (~0x1ffffffU)) - { - r =3D bfd_reloc_overflow; - break; - } - - r =3D loongarch_check_offset (rel, input_section); - if (r !=3D bfd_reloc_ok) - break; - - insn1 =3D bfd_get (bits, input_bfd, contents + rel->r_offset); - insn1 =3D ((insn1 & howto->src_mask) - | ((imm & 0xffffU) << 10) - | ((imm & 0x3ff0000U) >> 16)); - bfd_put (bits, input_bfd, insn1, contents + rel->r_offset); - break; - } - case R_LARCH_TLS_DTPREL32: case R_LARCH_32: case R_LARCH_TLS_DTPREL64: @@ -1792,6 +1747,55 @@ perform_relocation (const Elf_Internal_Rela *rel, as= ection *input_section, bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset); break; =20 + /* New reloc type. + R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */ + case R_LARCH_B16: + case R_LARCH_B21: + case R_LARCH_B26: + case R_LARCH_ABS_HI20: + case R_LARCH_ABS_LO12: + case R_LARCH_ABS64_LO20: + case R_LARCH_ABS64_HI12: + case R_LARCH_PCALA_HI20: + case R_LARCH_PCALA_LO12: + case R_LARCH_PCALA64_LO20: + case R_LARCH_PCALA64_HI12: + case R_LARCH_GOT_PC_HI20: + case R_LARCH_GOT_PC_LO12: + case R_LARCH_GOT64_PC_LO20: + case R_LARCH_GOT64_PC_HI12: + case R_LARCH_GOT_HI20: + case R_LARCH_GOT_LO12: + case R_LARCH_GOT64_LO20: + case R_LARCH_GOT64_HI12: + case R_LARCH_TLS_LE_HI20: + case R_LARCH_TLS_LE_LO12: + case R_LARCH_TLS_LE64_LO20: + case R_LARCH_TLS_LE64_HI12: + case R_LARCH_TLS_IE_PC_HI20: + case R_LARCH_TLS_IE_PC_LO12: + case R_LARCH_TLS_IE64_PC_LO20: + case R_LARCH_TLS_IE64_PC_HI12: + case R_LARCH_TLS_IE_HI20: + case R_LARCH_TLS_IE_LO12: + case R_LARCH_TLS_IE64_LO20: + case R_LARCH_TLS_IE64_HI12: + case R_LARCH_TLS_LD_PC_HI20: + case R_LARCH_TLS_LD_HI20: + case R_LARCH_TLS_GD_PC_HI20: + case R_LARCH_TLS_GD_HI20: + r =3D loongarch_check_offset (rel, input_section); + if (r !=3D bfd_reloc_ok) + break; + + r =3D loongarch_reloc_rewrite_imm_insn (rel, input_section, + howto, input_bfd, + contents, value); + break; + + case R_LARCH_RELAX: + break; + default: r =3D bfd_reloc_notsupported; } @@ -1900,7 +1904,6 @@ loongarch_dump_reloc_record (void (*p) (const char *f= mt, ...)) "-- Record dump end --\n\n"); } =20 - static bool loongarch_reloc_is_fatal (struct bfd_link_info *info, bfd *input_bfd, @@ -1945,8 +1948,27 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info, return fatal; } =20 - - +#define RELOCATE_CALC_PC32_HI20(relocation, pc) \ + ({ \ + bfd_vma lo =3D (relocation) & ((bfd_vma)0xfff); \ + pc =3D pc & (~(bfd_vma)0xfff); \ + if (lo > 0x7ff) \ + { \ + relocation +=3D 0x1000; \ + } \ + relocation &=3D ~(bfd_vma)0xfff; \ + relocation -=3D pc; \ + }) + +#define RELOCATE_CALC_PC64_HI32(relocation, pc) \ + ({ \ + bfd_vma lo =3D (relocation) & ((bfd_vma)0xfff); \ + if (lo > 0x7ff) \ + { \ + relocation -=3D 0x100000000; \ + } \ + relocation -=3D (pc & ~(bfd_vma)0xffffffff); \ + }) =20 static int loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *inf= o, @@ -1983,8 +2005,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, bool is_ie, is_undefweak, unresolved_reloc, defined_local; bool resolved_local, resolved_dynly, resolved_to_const; char tls_type; - bfd_vma relocation; - bfd_vma off, ie_off; + bfd_vma relocation, off, ie_off; int i, j; =20 howto =3D loongarch_elf_rtype_to_howto (input_bfd, r_type); @@ -2018,9 +2039,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, str= uct bfd_link_info *info, resolved_local =3D true; resolved_dynly =3D false; resolved_to_const =3D false; + + /* Calc in funtion elf_link_input_bfd, + * if #define elf_backend_rela_normal to 1. */ if (bfd_link_relocatable (info) && ELF_ST_TYPE (sym->st_info) =3D=3D STT_SECTION) - rel->r_addend +=3D sec->output_offset; + continue; } else { @@ -2092,7 +2116,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, resolved_to_const =3D true; } =20 - /* The ifunc without reference does not generate plt. */ + /* The ifunc reference generate plt. */ if (h && h->type =3D=3D STT_GNU_IFUNC && h->plt.offset !=3D MINUS_ON= E) { defined_local =3D true; @@ -2150,20 +2174,25 @@ loongarch_elf_relocate_section (bfd *output_bfd, st= ruct bfd_link_info *info, + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); =20 - /* Dynamic relocations are stored in - 1. .rela.ifunc section in PIC object. - 2. .rela.got section in dynamic executable. - 3. .rela.iplt section in static executable. */ - if (bfd_link_pic (info)) - sreloc =3D htab->elf.irelifunc; - else if (htab->elf.splt !=3D NULL) - sreloc =3D htab->elf.srelgot; + if (htab->elf.splt !=3D NULL) + sreloc =3D htab->elf.srelplt; else sreloc =3D htab->elf.irelplt; } else if (resolved_dynly) { - outrel.r_info =3D ELFNN_R_INFO (h->dynindx, r_type); + if (h->dynindx =3D=3D -1) + { + if (h->root.type =3D=3D bfd_link_hash_undefined) + (*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, + rel->r_offset, true); + + outrel.r_info =3D ELFNN_R_INFO (0, r_type); + } + else + outrel.r_info =3D ELFNN_R_INFO (h->dynindx, r_type); + outrel.r_addend =3D rel->r_addend; } else @@ -2172,7 +2201,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, outrel.r_addend =3D relocation + rel->r_addend; } =20 - if (unresolved_reloc) + /* No alloc space of func allocate_dynrelocs. */ + if (unresolved_reloc + && !(h && (h->is_weakalias || !h->dyn_relocs))) loongarch_elf_append_rela (output_bfd, sreloc, &outrel); } =20 @@ -2341,12 +2372,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, str= uct bfd_link_info *info, case R_LARCH_SOP_PUSH_PLT_PCREL: unresolved_reloc =3D false; =20 - if (resolved_to_const) - { - relocation +=3D rel->r_addend; - break; - } - else if (is_undefweak) + if (is_undefweak) { i =3D 0, j =3D 0; relocation =3D 0; @@ -2427,10 +2453,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, str= uct bfd_link_info *info, =20 if (h !=3D NULL) { - off =3D h->got.offset; + off =3D h->got.offset & (~1); =20 - if (off =3D=3D MINUS_ONE - && h->type !=3D STT_GNU_IFUNC) + if (h->got.offset =3D=3D MINUS_ONE && h->type !=3D STT_GNU_IFUNC) { fatal =3D (loongarch_reloc_is_fatal (info, input_bfd, input_section, rel, howto, @@ -2441,8 +2466,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, =20 /* Hidden symbol not has .got entry, only .got.plt entry so gprel is (plt - got). */ - if (off =3D=3D MINUS_ONE - && h->type =3D=3D STT_GNU_IFUNC) + if (h->got.offset =3D=3D MINUS_ONE && h->type =3D=3D STT_GNU_IFUNC) { if (h->plt.offset =3D=3D (bfd_vma) -1) { @@ -2455,79 +2479,76 @@ loongarch_elf_relocate_section (bfd *output_bfd, st= ruct bfd_link_info *info, if (htab->elf.splt !=3D NULL) { /* Section .plt header is 2 times of plt entry. */ - off =3D sec_addr(htab->elf.sgotplt) + off - - sec_addr(htab->elf.sgot); + off =3D sec_addr (htab->elf.sgotplt) + off + - sec_addr (htab->elf.sgot); } else { /* Section iplt not has plt header. */ - off =3D sec_addr(htab->elf.igotplt) + off - - sec_addr(htab->elf.sgot); + off =3D sec_addr (htab->elf.igotplt) + off + - sec_addr (htab->elf.sgot); } } =20 - if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h) - || (is_pic && SYMBOL_REFERENCES_LOCAL (info, h))) + if ((h->got.offset & 1) =3D=3D 0) { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of the word size, - we use the least significant bit to record whether - we have initialized it already. - - When doing a dynamic link, we create a .rela.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - - if (resolved_dynly) + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, + bfd_link_pic (info), h) + && ((bfd_link_pic (info) + && SYMBOL_REFERENCES_LOCAL (info, h)))) { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_dangerous, is_undefweak, name, - "Internal: here shouldn't dynamic.")); - } + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of the word size, + we use the least significant bit to record whether + we have initialized it already. + + When doing a dynamic link, we create a rela.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + + if (resolved_dynly) + { + fatal =3D (loongarch_reloc_is_fatal + (info, input_bfd, input_section, rel, howto, + bfd_reloc_dangerous, is_undefweak, name, + "Internal: here shouldn't dynamic.")); + } =20 - if (!(defined_local || resolved_to_const)) - { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_undefined, is_undefweak, name, - "Internal: ")); - break; - } + if (!(defined_local || resolved_to_const)) + { + fatal =3D (loongarch_reloc_is_fatal + (info, input_bfd, input_section, rel, howto, + bfd_reloc_undefined, is_undefweak, name, + "Internal: ")); + break; + } =20 - if ((off & 1) !=3D 0) - off &=3D ~1; - else - { - /* The pr21964-4. Create relocate entry. */ - if (is_pic && h->start_stop) + asection *s; + Elf_Internal_Rela outrel; + /* We need to generate a R_LARCH_RELATIVE reloc + for the dynamic linker. */ + s =3D htab->elf.srelgot; + if (!s) { - asection *s; - Elf_Internal_Rela outrel; - /* We need to generate a R_LARCH_RELATIVE reloc - for the dynamic linker. */ - s =3D htab->elf.srelgot; - if (!s) - { - fatal =3D loongarch_reloc_is_fatal (info, input_bfd, - input_section, rel, howto, - bfd_reloc_notsupported, is_undefweak, name, - "Internal: '.rel.got' not represent"); - break; - } - - outrel.r_offset =3D sec_addr (got) + off; - outrel.r_info =3D ELFNN_R_INFO (0, R_LARCH_RELATIVE); - outrel.r_addend =3D relocation; /* Link-time addr. */ - loongarch_elf_append_rela (output_bfd, s, &outrel); + fatal =3D loongarch_reloc_is_fatal + (info, input_bfd, + input_section, rel, howto, + bfd_reloc_notsupported, is_undefweak, name, + "Internal: '.rel.got' not represent"); + break; } - bfd_put_NN (output_bfd, relocation, got->contents + off); - h->got.offset |=3D 1; + + outrel.r_offset =3D sec_addr (got) + off; + outrel.r_info =3D ELFNN_R_INFO (0, R_LARCH_RELATIVE); + outrel.r_addend =3D relocation; /* Link-time addr. */ + loongarch_elf_append_rela (output_bfd, s, &outrel); } + bfd_put_NN (output_bfd, relocation, got->contents + off); + h->got.offset |=3D 1; } } else @@ -2541,9 +2562,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, break; } =20 - off =3D local_got_offsets[r_symndx]; + off =3D local_got_offsets[r_symndx] & (~1); =20 - if (off =3D=3D MINUS_ONE) + if (local_got_offsets[r_symndx] =3D=3D MINUS_ONE) { fatal =3D (loongarch_reloc_is_fatal (info, input_bfd, input_section, rel, howto, @@ -2555,9 +2576,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, /* The offset must always be a multiple of the word size. So, we can use the least significant bit to record whether we have already processed this entry. */ - if ((off & 1) !=3D 0) - off &=3D ~1; - else + if (local_got_offsets[r_symndx] =3D=3D 0) { if (is_pic) { @@ -2586,160 +2605,519 @@ loongarch_elf_relocate_section (bfd *output_bfd, = struct bfd_link_info *info, } } relocation =3D off; + break; =20 case R_LARCH_SOP_PUSH_TLS_GOT: case R_LARCH_SOP_PUSH_TLS_GD: - if (r_type =3D=3D R_LARCH_SOP_PUSH_TLS_GOT) - is_ie =3D true; + { + unresolved_reloc =3D false; + if (r_type =3D=3D R_LARCH_SOP_PUSH_TLS_GOT) + is_ie =3D true; + + bfd_vma got_off =3D 0; + if (h !=3D NULL) + { + got_off =3D h->got.offset; + h->got.offset |=3D 1; + } + else + { + got_off =3D local_got_offsets[r_symndx]; + local_got_offsets[r_symndx] |=3D 1; + } + + BFD_ASSERT (got_off !=3D MINUS_ONE); + + ie_off =3D 0; + tls_type =3D _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); + if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) + ie_off =3D 2 * GOT_ENTRY_SIZE; + + if ((got_off & 1) =3D=3D 0) + { + Elf_Internal_Rela rela; + asection *srel =3D htab->elf.srelgot; + bfd_vma tls_block_off =3D 0; + + if (SYMBOL_REFERENCES_LOCAL (info, h)) + { + BFD_ASSERT (elf_hash_table (info)->tls_sec); + tls_block_off =3D relocation + - elf_hash_table (info)->tls_sec->vma; + } + + if (tls_type & GOT_TLS_GD) + { + rela.r_offset =3D sec_addr (got) + got_off; + rela.r_addend =3D 0; + if (SYMBOL_REFERENCES_LOCAL (info, h)) + { + /* Local sym, used in exec, set module id 1. */ + if (bfd_link_executable (info)) + bfd_put_NN (output_bfd, 1, got->contents + got_off); + else + { + rela.r_info =3D ELFNN_R_INFO (0, + R_LARCH_TLS_DTPMODNN); + loongarch_elf_append_rela (output_bfd, srel, &rela); + } + + bfd_put_NN (output_bfd, tls_block_off, + got->contents + got_off + GOT_ENTRY_SIZE); + } + /* Dynamic resolved. */ + else + { + /* Dynamic relocate module id. */ + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_DTPMODNN); + loongarch_elf_append_rela (output_bfd, srel, &rela); + + /* Dynamic relocate offset of block. */ + rela.r_offset +=3D GOT_ENTRY_SIZE; + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_DTPRELNN); + loongarch_elf_append_rela (output_bfd, srel, &rela); + } + } + if (tls_type & GOT_TLS_IE) + { + rela.r_offset =3D sec_addr (got) + got_off + ie_off; + if (SYMBOL_REFERENCES_LOCAL (info, h)) + { + /* Local sym, used in exec, set module id 1. */ + if (!bfd_link_executable (info)) + { + rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); + rela.r_addend =3D tls_block_off; + loongarch_elf_append_rela (output_bfd, srel, &rela); + } + + bfd_put_NN (output_bfd, tls_block_off, + got->contents + got_off + ie_off); + } + /* Dynamic resolved. */ + else + { + /* Dynamic relocate offset of block. */ + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_TPRELNN); + rela.r_addend =3D 0; + loongarch_elf_append_rela (output_bfd, srel, &rela); + } + } + } + + relocation =3D (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0); + } + break; + + /* New reloc types. */ + case R_LARCH_B21: + case R_LARCH_B26: + case R_LARCH_B16: unresolved_reloc =3D false; + if (is_undefweak) + { + relocation =3D 0; + } =20 - if (rel->r_addend !=3D 0) + if (resolved_local) { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_notsupported, is_undefweak, name, - "Shouldn't be with r_addend.")); + relocation -=3D pc; + relocation +=3D rel->r_addend; + } + else if (resolved_dynly) + { + BFD_ASSERT (h + && (h->plt.offset !=3D MINUS_ONE + || ELF_ST_VISIBILITY (h->other) !=3D STV_DEFAULT) + && rel->r_addend =3D=3D 0); + if (h && h->plt.offset =3D=3D MINUS_ONE + && ELF_ST_VISIBILITY (h->other) !=3D STV_DEFAULT) + { + relocation -=3D pc; + relocation +=3D rel->r_addend; + } + else + relocation =3D sec_addr (plt) + h->plt.offset - pc; + } + + break; + + case R_LARCH_ABS_HI20: + case R_LARCH_ABS_LO12: + case R_LARCH_ABS64_LO20: + case R_LARCH_ABS64_HI12: + BFD_ASSERT (!is_pic); + + if (is_undefweak) + { + BFD_ASSERT (resolved_dynly); + relocation =3D 0; break; } + else if (resolved_to_const || resolved_local) + { + relocation +=3D rel->r_addend; + } + else if (resolved_dynly) + { + unresolved_reloc =3D false; + BFD_ASSERT ((plt && h && h->plt.offset !=3D MINUS_ONE) + && rel->r_addend =3D=3D 0); + relocation =3D sec_addr (plt) + h->plt.offset; + } + + break; + + case R_LARCH_PCALA_HI20: + unresolved_reloc =3D false; + if (h && h->plt.offset !=3D MINUS_ONE) + relocation =3D sec_addr (plt) + h->plt.offset; + else + relocation +=3D rel->r_addend; =20 + RELOCATE_CALC_PC32_HI20 (relocation, pc); + + break; + + case R_LARCH_PCALA_LO12: + /* Not support if sym_addr in 2k page edge. + pcalau12i pc_hi20 (sym_addr) + ld.w/d pc_lo12 (sym_addr) + ld.w/d pc_lo12 (sym_addr + x) + ... + can not calc correct address + if sym_addr < 0x800 && sym_addr + x >=3D 0x800. */ + + if (h && h->plt.offset !=3D MINUS_ONE) + relocation =3D sec_addr (plt) + h->plt.offset; + else + relocation +=3D rel->r_addend; =20 - if (resolved_to_const && is_undefweak && h->dynindx !=3D -1) { - /* What if undefweak? Let rtld make a decision. */ - resolved_to_const =3D resolved_local =3D false; - resolved_dynly =3D true; + relocation &=3D 0xfff; + /* Signed extend. */ + relocation =3D (relocation ^ 0x800) - 0x800; + + /* For 2G jump, generate pcalau12i, jirl. */ + /* If use jirl, turns to R_LARCH_B16. */ + uint32_t insn =3D bfd_get (32, input_bfd, contents + rel->r_offset); + if ((insn & 0x4c000000) =3D=3D 0x4c000000) + { + rel->r_info =3D ELFNN_R_INFO (r_symndx, R_LARCH_B16); + howto =3D loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16); + } } + break; =20 - if (resolved_to_const) + case R_LARCH_PCALA64_LO20: + case R_LARCH_PCALA64_HI12: + if (h && h->plt.offset !=3D MINUS_ONE) { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_notsupported, is_undefweak, name, - "Internal: Shouldn't be resolved to const.")); - break; + BFD_ASSERT (rel->r_addend =3D=3D 0); + relocation =3D sec_addr (plt) + h->plt.offset; + } + else + relocation +=3D rel->r_addend; + + RELOCATE_CALC_PC64_HI32 (relocation, pc); + + break; + + case R_LARCH_GOT_PC_HI20: + case R_LARCH_GOT_HI20: + /* Calc got offset. */ + { + unresolved_reloc =3D false; + BFD_ASSERT (rel->r_addend =3D=3D 0); + + bfd_vma got_off =3D 0; + if (h !=3D NULL) + { + /* GOT ref or ifunc. */ + BFD_ASSERT (h->got.offset !=3D MINUS_ONE + || h->type =3D=3D STT_GNU_IFUNC); + + got_off =3D h->got.offset & (~(bfd_vma)1); + /* Hidden symbol not has got entry, + * only got.plt entry so it is (plt - got). */ + if (h->got.offset =3D=3D MINUS_ONE && h->type =3D=3D STT_GNU_IFUNC) + { + bfd_vma idx; + if (htab->elf.splt !=3D NULL) + { + idx =3D (h->plt.offset - PLT_HEADER_SIZE) + / PLT_ENTRY_SIZE; + got_off =3D sec_addr (htab->elf.sgotplt) + + GOTPLT_HEADER_SIZE + + (idx * GOT_ENTRY_SIZE) + - sec_addr (htab->elf.sgot); + } + else + { + idx =3D h->plt.offset / PLT_ENTRY_SIZE; + got_off =3D sec_addr (htab->elf.sgotplt) + + (idx * GOT_ENTRY_SIZE) + - sec_addr (htab->elf.sgot); + } + } + + if ((h->got.offset & 1) =3D=3D 0) + { + /* We need to generate a R_LARCH_RELATIVE reloc once + * in loongarch_elf_finish_dynamic_symbol or now, + * call finish_dyn && nopic + * or !call finish_dyn && pic. */ + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, + bfd_link_pic (info), + h) + && bfd_link_pic (info) + && SYMBOL_REFERENCES_LOCAL (info, h)) + { + Elf_Internal_Rela rela; + rela.r_offset =3D sec_addr (got) + got_off; + rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_RELATIVE); + rela.r_addend =3D relocation; + loongarch_elf_append_rela (output_bfd, + htab->elf.srelgot, &rela); + } + h->got.offset |=3D 1; + } + } + else + { + BFD_ASSERT (local_got_offsets + && local_got_offsets[r_symndx] !=3D MINUS_ONE); + + got_off =3D local_got_offsets[r_symndx] & (~(bfd_vma)1); + if ((local_got_offsets[r_symndx] & 1) =3D=3D 0) + { + if (bfd_link_pic (info)) + { + Elf_Internal_Rela rela; + rela.r_offset =3D sec_addr (got) + got_off; + rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_RELATIVE); + rela.r_addend =3D relocation; + loongarch_elf_append_rela (output_bfd, + htab->elf.srelgot, &rela); + } + local_got_offsets[r_symndx] |=3D 1; + } + } + + bfd_put_NN (output_bfd, relocation, got->contents + got_off); + + relocation =3D got_off + sec_addr (got); } =20 + if (r_type =3D=3D R_LARCH_GOT_PC_HI20) + RELOCATE_CALC_PC32_HI20 (relocation, pc); + + break; + + case R_LARCH_GOT_PC_LO12: + case R_LARCH_GOT64_PC_LO20: + case R_LARCH_GOT64_PC_HI12: + case R_LARCH_GOT_LO12: + case R_LARCH_GOT64_LO20: + case R_LARCH_GOT64_HI12: + { + unresolved_reloc =3D false; + bfd_vma got_off; + if (h) + got_off =3D h->got.offset & (~(bfd_vma)1); + else + got_off =3D local_got_offsets[r_symndx] & (~(bfd_vma)1); + + if (h && h->got.offset =3D=3D MINUS_ONE && h->type =3D=3D STT_GNU_I= FUNC) + { + bfd_vma idx; + if (htab->elf.splt !=3D NULL) + idx =3D (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + else + idx =3D h->plt.offset / PLT_ENTRY_SIZE; + + got_off =3D sec_addr (htab->elf.sgotplt) + + GOTPLT_HEADER_SIZE + + (idx * GOT_ENTRY_SIZE) + - sec_addr (htab->elf.sgot); + } + relocation =3D got_off + sec_addr (got); + } + + if (r_type =3D=3D R_LARCH_GOT_PC_LO12) + relocation &=3D (bfd_vma)0xfff; + else if (r_type =3D=3D R_LARCH_GOT64_PC_LO20 + || r_type =3D=3D R_LARCH_GOT64_PC_HI12) + RELOCATE_CALC_PC64_HI32 (relocation, pc); + + break; + + case R_LARCH_TLS_LE_HI20: + case R_LARCH_TLS_LE_LO12: + case R_LARCH_TLS_LE64_LO20: + case R_LARCH_TLS_LE64_HI12: + BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec); + + relocation -=3D elf_hash_table (info)->tls_sec->vma; + break; + + /* TLS IE LD/GD process separately is troublesome. + When a symbol is both ie and LD/GD, h->got.off |=3D 1 + make only one type be relocated. We must use + h->got.offset |=3D 1 and h->got.offset |=3D 2 + diff IE and LD/GD. And all (got_off & (~(bfd_vma)1)) + (IE LD/GD and reusable GOT reloc) must change to + (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits + as a tag. + Now, LD and GD is both GOT_TLS_GD type, LD seems to + can be omitted. */ + case R_LARCH_TLS_IE_PC_HI20: + case R_LARCH_TLS_IE_HI20: + case R_LARCH_TLS_LD_PC_HI20: + case R_LARCH_TLS_LD_HI20: + case R_LARCH_TLS_GD_PC_HI20: + case R_LARCH_TLS_GD_HI20: + BFD_ASSERT (rel->r_addend =3D=3D 0); + unresolved_reloc =3D false; + + if (r_type =3D=3D R_LARCH_TLS_IE_PC_HI20 + || r_type =3D=3D R_LARCH_TLS_IE_HI20) + is_ie =3D true; + + bfd_vma got_off =3D 0; if (h !=3D NULL) { - off =3D h->got.offset; + got_off =3D h->got.offset; h->got.offset |=3D 1; } else { - off =3D local_got_offsets[r_symndx]; + got_off =3D local_got_offsets[r_symndx]; local_got_offsets[r_symndx] |=3D 1; } =20 - if (off =3D=3D MINUS_ONE) - { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_notsupported, is_undefweak, name, - "Internal: TLS GOT entry doesn't represent.")); - break; - } - - tls_type =3D _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); + BFD_ASSERT (got_off !=3D MINUS_ONE); =20 - /* If this symbol is referenced by both GD and IE TLS, the IE - reference's GOT slot follows the GD reference's slots. */ ie_off =3D 0; + tls_type =3D _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) ie_off =3D 2 * GOT_ENTRY_SIZE; =20 - if ((off & 1) !=3D 0) - off &=3D ~1; - else + if ((got_off & 1) =3D=3D 0) { + Elf_Internal_Rela rela; + asection *relgot =3D htab->elf.srelgot; bfd_vma tls_block_off =3D 0; - Elf_Internal_Rela outrel; =20 - if (resolved_local) + if (SYMBOL_REFERENCES_LOCAL (info, h)) { - if (!elf_hash_table (info)->tls_sec) - { - fatal =3D (loongarch_reloc_is_fatal - (info, input_bfd, input_section, rel, howto, - bfd_reloc_notsupported, is_undefweak, name, - "Internal: TLS sec not represent.")); - break; - } - tls_block_off =3D - relocation - elf_hash_table (info)->tls_sec->vma; + BFD_ASSERT (elf_hash_table (info)->tls_sec); + tls_block_off =3D relocation + - elf_hash_table (info)->tls_sec->vma; } =20 if (tls_type & GOT_TLS_GD) { - outrel.r_offset =3D sec_addr (got) + off; - outrel.r_addend =3D 0; - bfd_put_NN (output_bfd, 0, got->contents + off); - if (resolved_local && bfd_link_executable (info)) - bfd_put_NN (output_bfd, 1, got->contents + off); - else if (resolved_local /* && !bfd_link_executable (info) */) - { - outrel.r_info =3D ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); - loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, - &outrel); - } - else /* if (resolved_dynly) */ + rela.r_offset =3D sec_addr (got) + got_off; + rela.r_addend =3D 0; + if (SYMBOL_REFERENCES_LOCAL (info, h)) { - outrel.r_info =3D - ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN); - loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, - &outrel); - } + /* Local sym, used in exec, set module id 1. */ + if (bfd_link_executable (info)) + bfd_put_NN (output_bfd, 1, got->contents + got_off); + else + { + rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); + loongarch_elf_append_rela (output_bfd, relgot, &rela); + } =20 - outrel.r_offset +=3D GOT_ENTRY_SIZE; - bfd_put_NN (output_bfd, tls_block_off, - got->contents + off + GOT_ENTRY_SIZE); - if (resolved_local) - /* DTPREL known. */; - else /* if (resolved_dynly) */ + bfd_put_NN (output_bfd, tls_block_off, + got->contents + got_off + GOT_ENTRY_SIZE); + } + /* Dynamic resolved. */ + else { - outrel.r_info =3D - ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN); - loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, - &outrel); + /* Dynamic relocate module id. */ + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_DTPMODNN); + loongarch_elf_append_rela (output_bfd, relgot, &rela); + + /* Dynamic relocate offset of block. */ + rela.r_offset +=3D GOT_ENTRY_SIZE; + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_DTPRELNN); + loongarch_elf_append_rela (output_bfd, relgot, &rela); } } - if (tls_type & GOT_TLS_IE) { - outrel.r_offset =3D sec_addr (got) + off + ie_off; - bfd_put_NN (output_bfd, tls_block_off, - got->contents + off + ie_off); - if (resolved_local && bfd_link_executable (info)) - /* TPREL known. */; - else if (resolved_local /* && !bfd_link_executable (info) */) + rela.r_offset =3D sec_addr (got) + got_off + ie_off; + if (SYMBOL_REFERENCES_LOCAL (info, h)) { - outrel.r_info =3D ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); - outrel.r_addend =3D tls_block_off; - loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, - &outrel); - } - else /* if (resolved_dynly) */ - { - /* Static linking has no .dynsym table. */ - if (!htab->elf.dynamic_sections_created) - { - outrel.r_info =3D - ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); - outrel.r_addend =3D 0; - } - else + /* Local sym, used in exec, set module id 1. */ + if (!bfd_link_executable (info)) { - outrel.r_info =3D - ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN); - outrel.r_addend =3D 0; + rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); + rela.r_addend =3D tls_block_off; + loongarch_elf_append_rela (output_bfd, relgot, &rela); } - loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, - &outrel); + + bfd_put_NN (output_bfd, tls_block_off, + got->contents + got_off + ie_off); + } + /* Dynamic resolved. */ + else + { + /* Dynamic relocate offset of block. */ + rela.r_info =3D ELFNN_R_INFO (h->dynindx, + R_LARCH_TLS_TPRELNN); + rela.r_addend =3D 0; + loongarch_elf_append_rela (output_bfd, relgot, &rela); } } } + relocation =3D (got_off & (~(bfd_vma)1)) + sec_addr (got) + + (is_ie ? ie_off : 0); + + if (r_type =3D=3D R_LARCH_TLS_LD_PC_HI20 + || r_type =3D=3D R_LARCH_TLS_GD_PC_HI20 + || r_type =3D=3D R_LARCH_TLS_IE_PC_HI20) + RELOCATE_CALC_PC32_HI20 (relocation, pc); =20 - relocation =3D off + (is_ie ? ie_off : 0); + break; + + case R_LARCH_TLS_IE_PC_LO12: + case R_LARCH_TLS_IE64_PC_LO20: + case R_LARCH_TLS_IE64_PC_HI12: + case R_LARCH_TLS_IE_LO12: + case R_LARCH_TLS_IE64_LO20: + case R_LARCH_TLS_IE64_HI12: + unresolved_reloc =3D false; + + if (h) + relocation =3D sec_addr (got) + (h->got.offset & (~(bfd_vma)3)); + else + relocation =3D sec_addr (got) + + (local_got_offsets[r_symndx] & (~(bfd_vma)3)); + + tls_type =3D _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); + /* Use both TLS_GD and TLS_IE. */ + if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) + relocation +=3D 2 * GOT_ENTRY_SIZE; + + if (r_type =3D=3D R_LARCH_TLS_IE_PC_LO12) + relocation &=3D (bfd_vma)0xfff; + else if (r_type =3D=3D R_LARCH_TLS_IE64_PC_LO20 + || r_type =3D=3D R_LARCH_TLS_IE64_PC_HI12) + RELOCATE_CALC_PC64_HI32 (relocation, pc); + + break; + + case R_LARCH_RELAX: break; =20 default: @@ -2759,7 +3137,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, if (_bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset) =3D=3D MINUS_ONE) /* WHY? May because it's invalid so skip checking. - But why dynamic reloc a invalid section? */ + But why dynamic reloc a invalid section? */ break; =20 if (input_section->output_section->flags & SEC_DEBUGGING) @@ -2825,7 +3203,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, stru= ct bfd_link_info *info, } =20 fatal =3D true; - break; } =20 return !fatal; @@ -2889,27 +3266,15 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bf= d, for (i =3D 0; i < PLT_ENTRY_INSNS; i++) bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i); =20 - /* Fill in the initial value of the .got.plt entry. */ + /* Fill in the initial value of the got.plt entry. */ loc =3D gotplt->contents + (got_address - sec_addr (gotplt)); bfd_put_NN (output_bfd, sec_addr (plt), loc); =20 rela.r_offset =3D got_address; =20 - /* TRUE if this is a PLT reference to a local IFUNC. */ - if (PLT_LOCAL_IFUNC_P(info, h)) - { - rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_IRELATIVE); - rela.r_addend =3D (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } - else - { - /* Fill in the entry in the .rela.plt section. */ - rela.r_info =3D ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT); - rela.r_addend =3D 0; - } - + /* Fill in the entry in the rela.plt section. */ + rela.r_info =3D ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT); + rela.r_addend =3D 0; loc =3D relplt->contents + plt_idx * sizeof (ElfNN_External_Rela); bed->s->swap_reloca_out (output_bfd, &rela, loc); =20 @@ -2930,15 +3295,14 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bf= d, if (h->got.offset !=3D MINUS_ONE /* TLS got entry have been handled in elf_relocate_section. */ && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_= IE)) - /* have allocated got entry but not allocated rela before. */ + /* Have allocated got entry but not allocated rela before. */ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) { asection *sgot, *srela; Elf_Internal_Rela rela; - bfd_vma off =3D h->got.offset & ~(bfd_vma) 1; + bfd_vma off =3D h->got.offset & ~(bfd_vma)1; =20 /* This symbol has an entry in the GOT. Set it up. */ - sgot =3D htab->elf.sgot; srela =3D htab->elf.srelgot; BFD_ASSERT (sgot && srela); @@ -2963,7 +3327,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, } else { - BFD_ASSERT ((h->got.offset & 1) =3D=3D 0); BFD_ASSERT (h->dynindx !=3D -1); rela.r_info =3D ELFNN_R_INFO (h->dynindx, R_LARCH_NN); rela.r_addend =3D 0; @@ -2993,7 +3356,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, } else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) { - BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr. */); asection *sec =3D h->root.u.def.section; rela.r_info =3D ELFNN_R_INFO (0, R_LARCH_RELATIVE); rela.r_addend =3D (h->root.u.def.value + sec->output_section->vma @@ -3001,7 +3363,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, } else { - BFD_ASSERT ((h->got.offset & 1) =3D=3D 0); BFD_ASSERT (h->dynindx !=3D -1); rela.r_info =3D ELFNN_R_INFO (h->dynindx, R_LARCH_NN); rela.r_addend =3D 0; @@ -3010,24 +3371,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, loongarch_elf_append_rela (output_bfd, srela, &rela); } =20 - if (h->needs_copy) - { - Elf_Internal_Rela rela; - asection *s; - - /* This symbols needs a copy reloc. Set it up. */ - BFD_ASSERT (h->dynindx !=3D -1); - - rela.r_offset =3D sec_addr (h->root.u.def.section) + h->root.u.def.v= alue; - rela.r_info =3D ELFNN_R_INFO (h->dynindx, R_LARCH_COPY); - rela.r_addend =3D 0; - if (h->root.u.def.section =3D=3D htab->elf.sdynrelro) - s =3D htab->elf.sreldynrelro; - else - s =3D htab->elf.srelbss; - loongarch_elf_append_rela (output_bfd, s, &rela); - } - /* Mark some specially defined symbols as absolute. */ if (h =3D=3D htab->elf.hdynamic || h =3D=3D htab->elf.hgot || h =3D=3D h= tab->elf.hplt) sym->st_shndx =3D SHN_ABS; @@ -3337,7 +3680,6 @@ loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_= Note *note) #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50 =20 - static bool loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c index 4424969e579..f059f1a0c05 100644 --- a/bfd/elfxx-loongarch.c +++ b/bfd/elfxx-loongarch.c @@ -35,27 +35,30 @@ typedef struct loongarch_reloc_howto_type_struct reloc_howto_type howto; bfd_reloc_code_real_type bfd_type; bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *); -}loongarch_reloc_howto_type; + const char *larch_reloc_type_name; +} loongarch_reloc_howto_type; =20 #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 } + false), BFD_RELOC_LARCH_##r_name, NULL, NULL } =20 #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \ - name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc) \ + 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 } + inplace, src_mask, dst_mask, pcrel_off), btype, afunc, lname } =20 #define LOONGARCH_EMPTY_HOWTO(C) \ - { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL } - -bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *va= l); -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); + { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL } =20 +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); =20 /* This does not include any relocation information, but should be good enough for GDB or objdump to read the file. */ @@ -76,7 +79,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[]= =3D 0, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_NONE, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 /* 32 bit relocation. */ LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */ @@ -93,7 +97,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[]= =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_32, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 /* 64 bit relocation. */ LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */ @@ -110,7 +115,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_64, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */ 0, /* rightshift */ @@ -126,7 +132,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_NONE, /* undefined? */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */ 0, /* rightshift */ @@ -141,8 +148,9 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D 0, /* src_mask */ 0, /* dst_mask */ false, /* pcrel_offset */ - BFD_RELOC_NONE, /* undefined? */ - NULL), /* adjust_reloc_bits */ + BFD_RELOC_NONE, /* undefined? */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */ 0, /* rightshift */ @@ -157,8 +165,9 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D 0, /* src_mask */ 0, /* dst_mask */ false, /* pcrel_offset */ - BFD_RELOC_NONE, /* undefined? */ - NULL), /* adjust_reloc_bits */ + BFD_RELOC_NONE, /* undefined? */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 /* Dynamic TLS relocations. */ LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */ @@ -175,7 +184,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_DTPMOD32, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */ 0, /* rightshift */ @@ -191,7 +201,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_DTPMOD64, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */ 0, /* rightshift */ @@ -207,7 +218,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_DTPREL32, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */ 0, /* rightshift */ @@ -223,7 +235,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_DTPREL64, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */ 0, /* rightshift */ @@ -239,7 +252,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_TPREL32, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */ 0, /* rightshift */ @@ -255,7 +269,8 @@ static loongarch_reloc_howto_type loongarch_howto_table= [] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_LARCH_TLS_TPREL64, /* bfd_reloc_code_real_type */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */ 0, /* rightshift */ @@ -271,63 +286,67 @@ static loongarch_reloc_howto_type loongarch_howto_tab= le[] =3D ALL_ONES, /* dst_mask */ false, /* pcrel_offset */ BFD_RELOC_NONE, /* undefined? */ - NULL), /* adjust_reloc_bits */ + NULL, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - 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_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), =20 LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */ - 0, /* rightshift. */ - 0, /* size. */ - 0, /* bitsize. */ + 0, /* rightshift. */ + 0, /* size. */ + 0, /* bitsize. */ false, /* pc_relative. */ - 0, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_MARK_LA", /* name. */ - false, /* partial_inplace. */ + 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */ - 0, /* rightshift. */ - 0, /* size. */ - 0, /* bitsize. */ + 0, /* rightshift. */ + 0, /* size. */ + 0, /* bitsize. */ false, /* pc_relative. */ - 0, /* bitpos. */ - complain_overflow_signed, /* complain_on_overflow. */ - bfd_elf_generic_reloc, /* special_function. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ "R_LARCH_MARK_PCREL", /* name. */ - false, /* partial_inplace. */ + 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */ - 2, /* rightshift. */ - 4, /* size. */ - 32, /* bitsize. */ + 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. */ + 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 /* type 23-37. */ LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE), @@ -347,343 +366,984 @@ static loongarch_reloc_howto_type loongarch_howto_t= able[] =3D LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE), =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */ - 0, /* rightshift. */ - 4, /* size. */ - 5, /* bitsize. */ + 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */ - 0, /* rightshift. */ - 4, /* size. */ - 12, /* bitsize. */ + 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */ - 0, /* rightshift. */ - 4, /* size. */ - 12, /* bitsize. */ + 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */ - 0, /* rightshift. */ - 4, /* size. */ - 16, /* bitsize. */ + 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */ 2, /* rightshift. */ - 4, /* size. */ - 16, /* bitsize. */ + 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. */ + 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 */ + reloc_bits_b16, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */ - 0, /* rightshift. */ - 4, /* size. */ - 20, /* bitsize. */ + 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, /* type (44). */ 2, /* rightshift. */ 4, /* size. */ - 21, /* bitsize. */ + 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. */ + 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 */ + reloc_bits_b21, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 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 */ + 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 */ - loongarch_adjust_reloc_bits_l16_h10), /* adjust_reloc_bits */ + reloc_bits_b26, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 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. */ + 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 */ + reloc_bits, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */ - 0, /* rightshift. */ - 4, /* size. */ - 8, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */ - 0, /* rightshift. */ - 4, /* size. */ - 16, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */ - 0, /* rightshift. */ - 4, /* size. */ - 24, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */ - 0, /* rightshift. */ - 4, /* size. */ - 32, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */ - 0, /* rightshift. */ - 8, /* size. */ - 64, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */ - 0, /* rightshift. */ - 4, /* size. */ - 8, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */ - 0, /* rightshift. */ - 4, /* size. */ - 16, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */ - 0, /* rightshift. */ - 4, /* size. */ - 24, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */ - 0, /* rightshift. */ - 4, /* size. */ - 32, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */ - 0, /* rightshift. */ - 8, /* size. */ - 64, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */ - 0, /* rightshift. */ - 0, /* size. */ - 0, /* bitsize. */ + 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, /* 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, /* adjust_reloc_bits */ + NULL), /* larch_reloc_type_name */ =20 - LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */ - 0, /* rightshift. */ - 0, /* size. */ - 0, /* bitsize. */ + 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. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ NULL, /* special_function. */ - "R_LARCH_GNU_VTENTRY", /* name. */ - false, /* partial_inplace. */ + "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, /* 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). */[...] [diff truncated at 100000 bytes]