diff --git a/0001-gdb-Add-LoongArch-bfd-support.patch b/0001-gdb-Add-LoongArch-bfd-support.patch index 346c6ccb9a92892edc5622eda84bd169581bc576..77e43b466aad9ac899bf00389d06581ec78fcb9c 100644 --- a/0001-gdb-Add-LoongArch-bfd-support.patch +++ b/0001-gdb-Add-LoongArch-bfd-support.patch @@ -1,36 +1,36 @@ -From e49267f4cb49658703768e4baf197b16e0053ba7 Mon Sep 17 00:00:00 2001 +From 5bdf4ed8e675df43a94eec716d9d82aa214c0a06 Mon Sep 17 00:00:00 2001 From: Qing Zhang -Date: Tue, 29 Mar 2022 16:08:17 +0800 -Subject: [PATCH 1/4] gdb-Add LoongArch bfd support +Date: Thu, 22 Sep 2022 12:46:48 +0800 +Subject: [PATCH 1/5] gdb-Add LoongArch bfd support Signed-off-by: Qing Zhang --- - gdb-11.1/bfd/Makefile.am | 17 +- - gdb-11.1/bfd/Makefile.in | 21 +- - gdb-11.1/bfd/archures.c | 5 + - gdb-11.1/bfd/bfd-in2.h | 48 + - gdb-11.1/bfd/config.bfd | 15 + - gdb-11.1/bfd/configure | 2 + - gdb-11.1/bfd/configure.ac | 2 + - gdb-11.1/bfd/cpu-loongarch.c | 61 + - gdb-11.1/bfd/elf-bfd.h | 9 + - gdb-11.1/bfd/elf.c | 109 + - gdb-11.1/bfd/elfnn-loongarch.c | 3425 ++++++++++++++++++++++++++++++ - gdb-11.1/bfd/elfxx-loongarch.c | 891 ++++++++ - gdb-11.1/bfd/elfxx-loongarch.h | 41 + - gdb-11.1/bfd/libbfd.h | 43 + - gdb-11.1/bfd/po/BLD-POTFILES.in | 2 + - gdb-11.1/bfd/po/SRC-POTFILES.in | 3 + - gdb-11.1/bfd/reloc.c | 89 + - gdb-11.1/bfd/targets.c | 8 + - gdb-11.1/include/elf/common.h | 12 +- - gdb-11.1/include/elf/loongarch.h | 128 ++ - 20 files changed, 4928 insertions(+), 3 deletions(-) - create mode 100644 gdb-11.1/bfd/cpu-loongarch.c - create mode 100644 gdb-11.1/bfd/elfnn-loongarch.c - create mode 100644 gdb-11.1/bfd/elfxx-loongarch.c - create mode 100644 gdb-11.1/bfd/elfxx-loongarch.h - create mode 100644 gdb-11.1/include/elf/loongarch.h + bfd/Makefile.am | 17 +- + bfd/Makefile.in | 21 +- + bfd/archures.c | 5 + + bfd/bfd-in2.h | 85 + + bfd/config.bfd | 15 + + bfd/configure | 2 + + bfd/configure.ac | 2 + + bfd/cpu-loongarch.c | 61 + + bfd/elf-bfd.h | 9 + + bfd/elf.c | 109 ++ + bfd/elfnn-loongarch.c | 4128 +++++++++++++++++++++++++++++++++++++++ + bfd/elfxx-loongarch.c | 1618 +++++++++++++++ + bfd/elfxx-loongarch.h | 45 + + bfd/libbfd.h | 80 + + bfd/po/BLD-POTFILES.in | 2 + + bfd/po/SRC-POTFILES.in | 1 + + bfd/reloc.c | 171 ++ + bfd/targets.c | 8 + + include/elf/common.h | 12 +- + include/elf/loongarch.h | 267 +++ + 20 files changed, 6655 insertions(+), 3 deletions(-) + create mode 100644 bfd/cpu-loongarch.c + create mode 100644 bfd/elfnn-loongarch.c + create mode 100644 bfd/elfxx-loongarch.c + create mode 100644 bfd/elfxx-loongarch.h + create mode 100644 include/elf/loongarch.h diff --git a/bfd/Makefile.am b/bfd/Makefile.am index ed2f701..097177b 100644 @@ -235,7 +235,7 @@ index 390691b..b1e8869 100644 &bfd_m32r_arch, &bfd_m68hc11_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index 57b3c45..ca9e814 100644 +index 57b3c45..edc01c1 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1932,6 +1932,9 @@ enum bfd_architecture @@ -248,7 +248,7 @@ index 57b3c45..ca9e814 100644 bfd_arch_last }; -@@ -6263,6 +6266,51 @@ assembler and not (currently) written to any object files. */ +@@ -6263,6 +6266,88 @@ assembler and not (currently) written to any object files. */ /* S12Z relocations. */ BFD_RELOC_S12Z_OPR, @@ -297,11 +297,48 @@ index 57b3c45..ca9e814 100644 + 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_32_PCREL, ++ BFD_RELOC_LARCH_RELAX, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; diff --git a/bfd/config.bfd b/bfd/config.bfd -index 30087e3..a5ed3da 100644 +index 30087e3..dcdcb33 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -182,6 +182,7 @@ hppa*) targ_archs=bfd_hppa_arch ;; @@ -320,7 +357,7 @@ index 30087e3..a5ed3da 100644 + loongarch32-*) + targ_defvec=loongarch_elf32_vec + targ_selvecs="loongarch_elf32_vec" -+ want64=false ++ want64=true + ;; + + loongarch64-*) @@ -361,12 +398,12 @@ index 07a75ed..f1da356 100644 m32r_elf32_le_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; diff --git a/bfd/cpu-loongarch.c b/bfd/cpu-loongarch.c new file mode 100644 -index 0000000..e866c3e +index 0000000..bf6702a --- /dev/null +++ b/bfd/cpu-loongarch.c @@ -0,0 +1,61 @@ +/* BFD support for LoongArch. -+ Copyright (C) 2021-2022 Free Software Foundation, Inc. ++ Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Loongson Ltd. + + This file is part of BFD, the Binary File Descriptor library. @@ -596,10 +633,10 @@ index 8f6531f..d71fe79 100644 diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c new file mode 100644 -index 0000000..8aaf157 +index 0000000..43182ea --- /dev/null +++ b/bfd/elfnn-loongarch.c -@@ -0,0 +1,3425 @@ +@@ -0,0 +1,4128 @@ +/* LoongArch-specific support for NN-bit ELF. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. @@ -724,17 +761,17 @@ index 0000000..8aaf157 + +#define elf_backend_plt_readonly 1 + -+#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_can_refcount 1 +#define elf_backend_want_got_sym 1 + +#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1) + +#define elf_backend_want_dynrelro 1 -+/* #define elf_backend_rela_normal 1 -+#define elf_backend_default_execstack 0 */ ++#define elf_backend_rela_normal 1 ++#define elf_backend_default_execstack 0 + +/* Generate a PLT header. */ + @@ -991,6 +1028,27 @@ index 0000000..8aaf157 + if (!_bfd_elf_merge_object_attributes (ibfd, info)) + return false; + ++ /* If the input BFD is not a dynamic object and it does not contain any ++ non-data sections, do not account its ABI. For example, various ++ packages produces such data-only relocatable objects with ++ `ld -r -b binary` or `objcopy`, and these objects have zero e_flags. ++ But they are compatible with all ABIs. */ ++ if (!(ibfd->flags & DYNAMIC)) ++ { ++ asection *sec; ++ bool have_code_sections = false; ++ for (sec = ibfd->sections; sec != NULL; sec = sec->next) ++ if ((bfd_section_flags (sec) ++ & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) ++ == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) ++ { ++ have_code_sections = true; ++ break; ++ } ++ if (!have_code_sections) ++ return true; ++ } ++ + if (!elf_flags_init (obfd)) + { + elf_flags_init (obfd) = true; @@ -1191,9 +1249,6 @@ index 0000000..8aaf157 + struct elf_link_hash_entry *h; + Elf_Internal_Sym *isym = NULL; + -+ int need_dynreloc; -+ int only_need_pcrel; -+ + r_symndx = ELFNN_R_SYM (rel->r_info); + r_type = ELFNN_R_TYPE (rel->r_info); + @@ -1206,7 +1261,7 @@ index 0000000..8aaf157 + if (r_symndx < symtab_hdr->sh_info) + { + /* A local symbol. */ -+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); ++ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); + if (isym == NULL) + return false; + @@ -1239,17 +1294,20 @@ index 0000000..8aaf157 + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + ++ /* 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 == R_LARCH_64 || r_type == R_LARCH_32) + && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) + return false; + -+ 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 = 0; + h->plt.refcount++; @@ -1258,17 +1316,27 @@ index 0000000..8aaf157 + elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc; + } + -+ need_dynreloc = 0; -+ only_need_pcrel = 0; ++ int need_dynreloc = 0; ++ int only_need_pcrel = 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 = 1; + if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h, + r_symndx, + GOT_NORMAL)) + return false; + break; + ++ 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, @@ -1276,6 +1344,8 @@ index 0000000..8aaf157 + return false; + break; + ++ 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. */ @@ -1287,6 +1357,7 @@ index 0000000..8aaf157 + return false; + break; + ++ case R_LARCH_TLS_LE_HI20: + case R_LARCH_SOP_PUSH_TLS_TPREL: + if (!bfd_link_executable (info)) + return false; @@ -1299,6 +1370,7 @@ index 0000000..8aaf157 + return false; + break; + ++ case R_LARCH_ABS_HI20: + case R_LARCH_SOP_PUSH_ABSOLUTE: + if (h != NULL) + /* If this reloc is in a read-only section, we might @@ -1310,16 +1382,45 @@ index 0000000..8aaf157 + h->non_got_ref = 1; + break; + -+ case R_LARCH_SOP_PUSH_PCREL: ++ case R_LARCH_PCALA_HI20: + if (h != NULL) + { + h->non_got_ref = 1; ++ h->pointer_equality_needed = 1; ++ } ++ ++ break; ++ ++ case R_LARCH_B21: ++ case R_LARCH_B16: ++ case R_LARCH_B26: ++ if (h != NULL) ++ { ++ h->needs_plt = 1; ++ if (!bfd_link_pic (info)) ++ h->non_got_ref = 1; ++ ++ /* We try to create PLT stub for all non-local function. */ ++ if (h->plt.refcount < 0) ++ h->plt.refcount = 0; ++ h->plt.refcount++; ++ } ++ ++ break; ++ ++ case R_LARCH_SOP_PUSH_PCREL: ++ if (h != NULL) ++ { ++ if (!bfd_link_pic (info)) ++ h->non_got_ref = 1; + + /* We try to create PLT stub for all non-local function. */ + if (h->plt.refcount < 0) + h->plt.refcount = 0; + h->plt.refcount++; ++ h->pointer_equality_needed = 1; + } ++ + break; + + case R_LARCH_SOP_PUSH_PLT_PCREL: @@ -1346,6 +1447,7 @@ index 0000000..8aaf157 + case R_LARCH_JUMP_SLOT: + case R_LARCH_32: + case R_LARCH_64: ++ + need_dynreloc = 1; + + /* If resolved symbol is defined in this object, @@ -1358,9 +1460,6 @@ index 0000000..8aaf157 + Thus, only under pde, it needs pcrel only. We discard it. */ + only_need_pcrel = bfd_link_pde (info); + -+ if (h != NULL) -+ h->non_got_ref = 1; -+ + if (h != NULL + && (!bfd_link_pic (info) + || h->type == STT_GNU_IFUNC)) @@ -1483,9 +1582,7 @@ index 0000000..8aaf157 + 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; + + htab = loongarch_elf_hash_table (info); + BFD_ASSERT (htab != NULL); @@ -1535,73 +1632,9 @@ index 0000000..8aaf157 + return true; + } + -+ /* 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 = 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 = 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 = (struct loongarch_elf_link_hash_entry *) h; -+ if (eh->tls_type & ~GOT_NORMAL) -+ { -+ s = htab->sdyntdata; -+ srel = htab->elf.srelbss; -+ } -+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0) -+ { -+ s = htab->elf.sdynrelro; -+ srel = htab->elf.sreldynrelro; -+ } -+ else -+ { -+ s = htab->elf.sdynbss; -+ srel = htab->elf.srelbss; -+ } -+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) -+ { -+ srel->size += sizeof (ElfNN_External_Rela); -+ h->needs_copy = 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; +} + +/* Allocate space in .plt, .got and associated reloc sections for @@ -1623,6 +1656,7 @@ index 0000000..8aaf157 + + info = (struct bfd_link_info *) inf; + htab = loongarch_elf_hash_table (info); ++ bool dyn = htab->elf.dynamic_sections_created; + BFD_ASSERT (htab != NULL); + + do @@ -1636,9 +1670,12 @@ index 0000000..8aaf157 + + if (htab->elf.splt) + { -+ if (h->dynindx == -1 && !h->forced_local -+ && !bfd_elf_link_record_dynamic_symbol (info, h)) -+ return false; ++ if (h->dynindx == -1 && !h->forced_local && dyn ++ && h->root.type == bfd_link_hash_undefweak) ++ { ++ if (!bfd_elf_link_record_dynamic_symbol (info, h)) ++ return false; ++ } + + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h) + && h->type != STT_GNU_IFUNC) @@ -1674,7 +1711,7 @@ index 0000000..8aaf157 + 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 = plt; @@ -1691,51 +1728,68 @@ index 0000000..8aaf157 + if (0 < h->got.refcount) + { + asection *s; -+ bool dyn; + int tls_type = loongarch_elf_hash_entry (h)->tls_type; + + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ -+ if (h->dynindx == -1 && !h->forced_local) ++ if (h->dynindx == -1 && !h->forced_local && dyn ++ && h->root.type == bfd_link_hash_undefweak) + { -+ if (SYMBOL_REFERENCES_LOCAL (info, h) -+ && (ELF_ST_VISIBILITY (h->other) != 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; + } + + s = htab->elf.sgot; + h->got.offset = s->size; -+ dyn = 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 += 2 * GOT_ENTRY_SIZE; -+ htab->elf.srelgot->size += 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 += 2 * sizeof (ElfNN_External_Rela); ++ } ++ else ++ { ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); ++ else ++ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela); ++ } + } + + /* TLS_IE needs one dynamic reloc and one GOT slot. */ + if (tls_type & GOT_TLS_IE) + { + s->size += GOT_ENTRY_SIZE; -+ htab->elf.srelgot->size += 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 += sizeof (ElfNN_External_Rela); ++ } ++ else ++ { ++ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); ++ } + } + } + else + { + s->size += GOT_ENTRY_SIZE; -+ if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) -+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) -+ || h->type == STT_GNU_IFUNC) ++ if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT ++ || h->root.type != 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 += sizeof (ElfNN_External_Rela); + } + } @@ -1745,7 +1799,13 @@ index 0000000..8aaf157 + if (h->dyn_relocs == NULL) + return true; + -+ 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; + @@ -1762,13 +1822,20 @@ index 0000000..8aaf157 + + if (h->root.type == bfd_link_hash_undefweak) + { -+ if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) ++ if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h) ++ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT ++ || (!bfd_link_pic (info) && h->non_got_ref)) + h->dyn_relocs = NULL; -+ else if (h->dynindx == -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 == -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 == -1) ++ h->dyn_relocs = NULL; ++ } + } + + for (p = h->dyn_relocs; p != NULL; p = p->next) @@ -1780,12 +1847,264 @@ index 0000000..8aaf157 + return true; +} + ++/* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs. ++ For local def and ref ifunc, ++ dynamic relocations are stored in ++ 1. rela.srelgot section in dynamic object (dll or exec). ++ 2. rela.irelplt section in static executable. ++ Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used ++ instead of rela.srelplt. Glibc ELF loader will not support ++ R_LARCH_IRELATIVE relocation in rela.plt. */ ++ ++static bool ++local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, ++ struct elf_link_hash_entry *h, ++ struct elf_dyn_relocs **head, ++ unsigned int plt_entry_size, ++ unsigned int plt_header_size, ++ unsigned int got_entry_size, ++ bool avoid_plt) ++{ ++ asection *plt, *gotplt, *relplt; ++ struct elf_dyn_relocs *p; ++ unsigned int sizeof_reloc; ++ const struct elf_backend_data *bed; ++ struct elf_link_hash_table *htab; ++ /* If AVOID_PLT is TRUE, don't use PLT if possible. */ ++ bool use_plt = !avoid_plt || h->plt.refcount > 0; ++ bool need_dynreloc = !use_plt || bfd_link_pic (info); ++ ++ /* When a PIC object references a STT_GNU_IFUNC symbol defined ++ in executable or it isn't referenced via PLT, the address of ++ the resolved function may be used. But in non-PIC executable, ++ the address of its plt slot may be used. Pointer equality may ++ not work correctly. PIE or non-PLT reference should be used if ++ pointer equality is required here. ++ ++ If STT_GNU_IFUNC symbol is defined in position-dependent executable, ++ backend should change it to the normal function and set its address ++ to its PLT entry which should be resolved by R_*_IRELATIVE at ++ run-time. All external references should be resolved to its PLT in ++ executable. */ ++ if (!need_dynreloc ++ && !(bfd_link_pde (info) && h->def_regular) ++ && (h->dynindx != -1 ++ || info->export_dynamic) ++ && h->pointer_equality_needed) ++ { ++ info->callbacks->einfo ++ /* xgettext:c-format. */ ++ (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer " ++ "equality in `%pB' can not be used when making an " ++ "executable; recompile with -fPIE and relink with -pie\n"), ++ h->root.root.string, ++ h->root.u.def.section->owner); ++ bfd_set_error (bfd_error_bad_value); ++ return false; ++ } ++ ++ htab = elf_hash_table (info); ++ ++ /* When the symbol is marked with regular reference, if PLT isn't used ++ or we are building a PIC object, we must keep dynamic relocation ++ if there is non-GOT reference and use PLT if there is PC-relative ++ reference. */ ++ if (need_dynreloc && h->ref_regular) ++ { ++ bool keep = false; ++ for (p = *head; p != NULL; p = p->next) ++ if (p->count) ++ { ++ h->non_got_ref = 1; ++ /* Need dynamic relocations for non-GOT reference. */ ++ keep = true; ++ if (p->pc_count) ++ { ++ /* Must use PLT for PC-relative reference. */ ++ use_plt = true; ++ need_dynreloc = bfd_link_pic (info); ++ break; ++ } ++ } ++ if (keep) ++ goto keep; ++ } ++ ++ /* Support garbage collection against STT_GNU_IFUNC symbols. */ ++ if (h->plt.refcount <= 0 && h->got.refcount <= 0) ++ { ++ h->got = htab->init_got_offset; ++ h->plt = htab->init_plt_offset; ++ *head = NULL; ++ return true; ++ } ++ ++ /* Return and discard space for dynamic relocations against it if ++ it is never referenced. */ ++ if (!h->ref_regular) ++ { ++ if (h->plt.refcount > 0 ++ || h->got.refcount > 0) ++ abort (); ++ h->got = htab->init_got_offset; ++ h->plt = htab->init_plt_offset; ++ *head = NULL; ++ return true; ++ } ++ ++ keep: ++ bed = get_elf_backend_data (info->output_bfd); ++ if (bed->rela_plts_and_copies_p) ++ sizeof_reloc = bed->s->sizeof_rela; ++ else ++ sizeof_reloc = bed->s->sizeof_rel; ++ ++ /* When building a static executable, use iplt, igot.plt and ++ rela.iplt sections for STT_GNU_IFUNC symbols. */ ++ if (htab->splt != NULL) ++ { ++ plt = htab->splt; ++ gotplt = htab->sgotplt; ++ /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */ ++ relplt = htab->srelgot; ++ ++ /* If this is the first plt entry and PLT is used, make room for ++ the special first entry. */ ++ if (plt->size == 0 && use_plt) ++ plt->size += plt_header_size; ++ } ++ else ++ { ++ plt = htab->iplt; ++ gotplt = htab->igotplt; ++ relplt = htab->irelplt; ++ } ++ ++ if (use_plt) ++ { ++ /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need ++ the original value for R_*_IRELATIVE. */ ++ h->plt.offset = plt->size; ++ ++ /* Make room for this entry in the plt/iplt section. */ ++ plt->size += plt_entry_size; ++ ++ /* We also need to make an entry in the got.plt/got.iplt section, ++ which will be placed in the got section by the linker script. */ ++ gotplt->size += got_entry_size; ++ } ++ ++ /* We also need to make an entry in the rela.plt/.rela.iplt ++ section for GOTPLT relocation if PLT is used. */ ++ if (use_plt) ++ { ++ relplt->size += sizeof_reloc; ++ relplt->reloc_count++; ++ } ++ ++ /* We need dynamic relocation for STT_GNU_IFUNC symbol only when ++ there is a non-GOT reference in a PIC object or PLT isn't used. */ ++ if (!need_dynreloc || !h->non_got_ref) ++ *head = NULL; ++ ++ /* Finally, allocate space. */ ++ p = *head; ++ if (p != NULL) ++ { ++ bfd_size_type count = 0; ++ do ++ { ++ count += p->count; ++ p = p->next; ++ } ++ while (p != NULL); ++ ++ htab->ifunc_resolvers = count != 0; ++ ++ /* Dynamic relocations are stored in ++ 1. rela.srelgot section in PIC object. ++ 2. rela.srelgot section in dynamic executable. ++ 3. rela.irelplt section in static executable. */ ++ if (htab->splt != NULL) ++ htab->srelgot->size += count * sizeof_reloc; ++ else ++ { ++ relplt->size += count * sizeof_reloc; ++ relplt->reloc_count += count; ++ } ++ } ++ ++ /* For STT_GNU_IFUNC symbol, got.plt has the real function address ++ and got has the PLT entry adddress. We will load the GOT entry ++ with the PLT entry in finish_dynamic_symbol if it is used. For ++ branch, it uses got.plt. For symbol value, if PLT is used, ++ 1. Use got.plt in a PIC object if it is forced local or not ++ dynamic. ++ 2. Use got.plt in a non-PIC object if pointer equality isn't ++ needed. ++ 3. Use got.plt in PIE. ++ 4. Use got.plt if got isn't used. ++ 5. Otherwise use got so that it can be shared among different ++ objects at run-time. ++ If PLT isn't used, always use got for symbol value. ++ We only need to relocate got entry in PIC object or in dynamic ++ executable without PLT. */ ++ if (use_plt ++ && (h->got.refcount <= 0 ++ || (bfd_link_pic (info) ++ && (h->dynindx == -1 ++ || h->forced_local)) ++ || ( ++ !h->pointer_equality_needed) ++ || htab->sgot == NULL)) ++ { ++ /* Use got.plt. */ ++ h->got.offset = (bfd_vma) -1; ++ } ++ else ++ { ++ if (!use_plt) ++ { ++ /* PLT isn't used. */ ++ h->plt.offset = (bfd_vma) -1; ++ } ++ if (h->got.refcount <= 0) ++ { ++ /* GOT isn't need when there are only relocations for static ++ pointers. */ ++ h->got.offset = (bfd_vma) -1; ++ } ++ else ++ { ++ h->got.offset = htab->sgot->size; ++ htab->sgot->size += got_entry_size; ++ /* Need to relocate the GOT entry in a PIC object or PLT isn't ++ used. Otherwise, the GOT entry will be filled with the PLT ++ entry and dynamic GOT relocation isn't needed. */ ++ if (need_dynreloc) ++ { ++ /* For non-static executable, dynamic GOT relocation is in ++ rela.got section, but for static executable, it is ++ in rela.iplt section. */ ++ if (htab->splt != NULL) ++ htab->srelgot->size += sizeof_reloc; ++ else ++ { ++ relplt->size += sizeof_reloc; ++ relplt->reloc_count++; ++ } ++ } ++ } ++ } ++ ++ return true; ++} ++ +/* Allocate space in .plt, .got and associated reloc sections for + ifunc dynamic relocs. */ + +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 @@ -1807,14 +2126,24 @@ index 0000000..8aaf157 + + /* 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 == 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); ++ if (h->type == STT_GNU_IFUNC && h->def_regular) ++ { ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ return local_allocate_ifunc_dyn_relocs (info, h, ++ &h->dyn_relocs, ++ PLT_ENTRY_SIZE, ++ PLT_HEADER_SIZE, ++ GOT_ENTRY_SIZE, ++ false); ++ else ++ return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, ++ &h->dyn_relocs, ++ PLT_ENTRY_SIZE, ++ PLT_HEADER_SIZE, ++ GOT_ENTRY_SIZE, ++ false); ++ } ++ + return true; +} + @@ -1822,7 +2151,7 @@ index 0000000..8aaf157 + ifunc dynamic relocs. */ + +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 = (struct elf_link_hash_entry *) *slot; + @@ -1833,7 +2162,7 @@ index 0000000..8aaf157 + || h->root.type != bfd_link_hash_defined) + abort (); + -+ return elfNN_loongarch_allocate_ifunc_dynrelocs (h, inf); ++ return elfNN_allocate_ifunc_dynrelocs (h, inf); +} + +/* Set DF_TEXTREL if we find any dynamic relocs that apply to @@ -1951,16 +2280,21 @@ index 0000000..8aaf157 + if (0 < *local_got) + { + *local_got = s->size; -+ s->size += GOT_ENTRY_SIZE; + ++ /* TLS gd use two got. */ + if (*local_tls_type & GOT_TLS_GD) ++ s->size += GOT_ENTRY_SIZE * 2; ++ else ++ /* Normal got, tls ie/ld use one got. */ + s->size += GOT_ENTRY_SIZE; + -+ /* 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 += sizeof (ElfNN_External_Rela); ++ if (bfd_link_executable (info) ++ && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE))) ++ ;/* Do nothing. */ ++ else ++ { ++ srel->size += sizeof (ElfNN_External_Rela); ++ } + } + else + *local_got = MINUS_ONE; @@ -1973,11 +2307,11 @@ index 0000000..8aaf157 + + /* 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_dynrelocs, info); ++ elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info); + + /* 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); + + /* Don't allocate .got.plt section if there are no PLT. */ + if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE @@ -2126,10 +2460,13 @@ index 0000000..8aaf157 +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; + + bed = 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 = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); + bed->s->swap_reloca_out (abfd, rel, loc); +} @@ -2178,19 +2515,15 @@ index 0000000..8aaf157 + return bfd_reloc_ok; +} + -+/* 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 = bfd_reloc_ok; + int bits = bfd_get_reloc_size (howto) * 8; + -+ + switch (ELFNN_R_TYPE (rel->r_info)) + { + case R_LARCH_SOP_PUSH_PCREL: @@ -2263,6 +2596,8 @@ index 0000000..8aaf157 + 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: @@ -2278,67 +2613,6 @@ index 0000000..8aaf157 + contents, (bfd_vma)opr1); + break; + -+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ { -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ -+ if ((opr1 & 0x3) != 0) -+ { -+ r = bfd_reloc_overflow; -+ break; -+ } -+ -+ uint32_t imm = opr1 >> howto->rightshift; -+ if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU))) -+ { -+ r = bfd_reloc_overflow; -+ break; -+ } -+ r = loongarch_check_offset (rel, input_section); -+ if (r != bfd_reloc_ok) -+ break; -+ -+ insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & howto->src_mask) -+ | ((imm & 0xffffU) << 10) -+ | ((imm & 0x1f0000U) >> 16); -+ bfd_put (bits, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ } -+ -+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ { -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ -+ if ((opr1 & 0x3) != 0) -+ { -+ r = bfd_reloc_overflow; -+ break; -+ } -+ -+ uint32_t imm = opr1 >> howto->rightshift; -+ if ((imm & (~0x1ffffffU)) && (imm & (~0x1ffffffU)) != (~0x1ffffffU)) -+ { -+ r = bfd_reloc_overflow; -+ break; -+ } -+ -+ r = loongarch_check_offset (rel, input_section); -+ if (r != bfd_reloc_ok) -+ break; -+ -+ insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset); -+ insn1 = ((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: @@ -2376,6 +2650,66 @@ index 0000000..8aaf157 + bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset); + break; + ++ /* For eh_frame and debug info. */ ++ case R_LARCH_32_PCREL: ++ value -= sec_addr (input_section) + rel->r_offset; ++ value += rel->r_addend; ++ bfd_vma word = bfd_get (howto->bitsize, input_bfd, ++ contents + rel->r_offset); ++ word = (word & ~howto->dst_mask) | (value & howto->dst_mask); ++ bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset); ++ r = bfd_reloc_ok; ++ break; ++ ++ /* 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 = loongarch_check_offset (rel, input_section); ++ if (r != bfd_reloc_ok) ++ break; ++ ++ r = loongarch_reloc_rewrite_imm_insn (rel, input_section, ++ howto, input_bfd, ++ contents, value); ++ break; ++ ++ case R_LARCH_RELAX: ++ break; ++ + default: + r = bfd_reloc_notsupported; + } @@ -2484,7 +2818,6 @@ index 0000000..8aaf157 + "-- Record dump end --\n\n"); +} + -+ +static bool +loongarch_reloc_is_fatal (struct bfd_link_info *info, + bfd *input_bfd, @@ -2529,8 +2862,27 @@ index 0000000..8aaf157 + return fatal; +} + -+ -+ ++#define RELOCATE_CALC_PC32_HI20(relocation, pc) \ ++ ({ \ ++ bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \ ++ pc = pc & (~(bfd_vma)0xfff); \ ++ if (lo > 0x7ff) \ ++ { \ ++ relocation += 0x1000; \ ++ } \ ++ relocation &= ~(bfd_vma)0xfff; \ ++ relocation -= pc; \ ++ }) ++ ++#define RELOCATE_CALC_PC64_HI32(relocation, pc) \ ++ ({ \ ++ bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \ ++ if (lo > 0x7ff) \ ++ { \ ++ relocation -= 0x100000000; \ ++ } \ ++ relocation -= (pc & ~(bfd_vma)0xffffffff); \ ++ }) + +static int +loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, @@ -2567,8 +2919,7 @@ index 0000000..8aaf157 + 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; + + howto = loongarch_elf_rtype_to_howto (input_bfd, r_type); @@ -2602,9 +2953,12 @@ index 0000000..8aaf157 + resolved_local = true; + resolved_dynly = false; + resolved_to_const = 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) == STT_SECTION) -+ rel->r_addend += sec->output_offset; ++ continue; + } + else + { @@ -2676,7 +3030,7 @@ index 0000000..8aaf157 + resolved_to_const = true; + } + -+ /* The ifunc without reference does not generate plt. */ ++ /* The ifunc reference generate plt. */ + if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE) + { + defined_local = true; @@ -2722,32 +3076,55 @@ index 0000000..8aaf157 + + outrel.r_offset += sec_addr (input_section); + -+ /* A pointer point to a local ifunc symbol. */ -+ if(h -+ && h->type == STT_GNU_IFUNC -+ && (h->dynindx == -1 -+ || h->forced_local -+ || bfd_link_executable(info))) ++ /* A pointer point to a ifunc symbol. */ ++ if (h && h->type == STT_GNU_IFUNC) + { -+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); -+ outrel.r_addend = (h->root.u.def.value -+ + h->root.u.def.section->output_section->vma -+ + h->root.u.def.section->output_offset); -+ -+ /* 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 = htab->elf.irelifunc; -+ else if (htab->elf.splt != NULL) -+ sreloc = htab->elf.srelgot; ++ if (h->dynindx == -1) ++ { ++ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); ++ outrel.r_addend = (h->root.u.def.value ++ + h->root.u.def.section->output_section->vma ++ + h->root.u.def.section->output_offset); ++ } ++ else ++ { ++ outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); ++ outrel.r_addend = 0; ++ } ++ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ ++ if (htab->elf.splt != NULL) ++ sreloc = htab->elf.srelgot; ++ else ++ sreloc = htab->elf.irelplt; ++ } + else -+ sreloc = htab->elf.irelplt; ++ { ++ ++ if (bfd_link_pic (info)) ++ sreloc = htab->elf.irelifunc; ++ else if (htab->elf.splt != NULL) ++ sreloc = htab->elf.srelgot; ++ else ++ sreloc = htab->elf.irelplt; ++ } + } + else if (resolved_dynly) + { -+ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); ++ if (h->dynindx == -1) ++ { ++ if (h->root.type == bfd_link_hash_undefined) ++ (*info->callbacks->undefined_symbol) ++ (info, name, input_bfd, input_section, ++ rel->r_offset, true); ++ ++ outrel.r_info = ELFNN_R_INFO (0, r_type); ++ } ++ else ++ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); ++ + outrel.r_addend = rel->r_addend; + } + else @@ -2756,7 +3133,9 @@ index 0000000..8aaf157 + outrel.r_addend = relocation + rel->r_addend; + } + -+ 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); + } + @@ -2925,12 +3304,7 @@ index 0000000..8aaf157 + case R_LARCH_SOP_PUSH_PLT_PCREL: + unresolved_reloc = false; + -+ if (resolved_to_const) -+ { -+ relocation += rel->r_addend; -+ break; -+ } -+ else if (is_undefweak) ++ if (is_undefweak) + { + i = 0, j = 0; + relocation = 0; @@ -3011,10 +3385,9 @@ index 0000000..8aaf157 + + if (h != NULL) + { -+ off = h->got.offset; ++ off = h->got.offset & (~1); + -+ if (off == MINUS_ONE -+ && h->type != STT_GNU_IFUNC) ++ if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC) + { + fatal = (loongarch_reloc_is_fatal + (info, input_bfd, input_section, rel, howto, @@ -3025,8 +3398,7 @@ index 0000000..8aaf157 + + /* Hidden symbol not has .got entry, only .got.plt entry + so gprel is (plt - got). */ -+ if (off == MINUS_ONE -+ && h->type == STT_GNU_IFUNC) ++ if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) + { + if (h->plt.offset == (bfd_vma) -1) + { @@ -3039,79 +3411,76 @@ index 0000000..8aaf157 + if (htab->elf.splt != NULL) + { + /* Section .plt header is 2 times of plt entry. */ -+ off = sec_addr(htab->elf.sgotplt) + off -+ - sec_addr(htab->elf.sgot); ++ off = sec_addr (htab->elf.sgotplt) + off ++ - sec_addr (htab->elf.sgot); + } + else + { + /* Section iplt not has plt header. */ -+ off = sec_addr(htab->elf.igotplt) + off -+ - sec_addr(htab->elf.sgot); ++ off = sec_addr (htab->elf.igotplt) + off ++ - sec_addr (htab->elf.sgot); + } + } + -+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h) -+ || (is_pic && SYMBOL_REFERENCES_LOCAL (info, h))) ++ if ((h->got.offset & 1) == 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 = (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 = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Internal: here shouldn't dynamic.")); ++ } + -+ if (!(defined_local || resolved_to_const)) -+ { -+ fatal = (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 = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "Internal: ")); ++ break; ++ } + -+ if ((off & 1) != 0) -+ off &= ~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 = 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 = htab->elf.srelgot; -+ if (!s) -+ { -+ fatal = 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 = sec_addr (got) + off; -+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); -+ outrel.r_addend = relocation; /* Link-time addr. */ -+ loongarch_elf_append_rela (output_bfd, s, &outrel); ++ fatal = 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 |= 1; ++ ++ outrel.r_offset = sec_addr (got) + off; ++ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); ++ outrel.r_addend = relocation; /* Link-time addr. */ ++ loongarch_elf_append_rela (output_bfd, s, &outrel); + } ++ bfd_put_NN (output_bfd, relocation, got->contents + off); ++ h->got.offset |= 1; + } + } + else @@ -3125,9 +3494,9 @@ index 0000000..8aaf157 + break; + } + -+ off = local_got_offsets[r_symndx]; ++ off = local_got_offsets[r_symndx] & (~1); + -+ if (off == MINUS_ONE) ++ if (local_got_offsets[r_symndx] == MINUS_ONE) + { + fatal = (loongarch_reloc_is_fatal + (info, input_bfd, input_section, rel, howto, @@ -3139,9 +3508,7 @@ index 0000000..8aaf157 + /* 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) != 0) -+ off &= ~1; -+ else ++ if (local_got_offsets[r_symndx] == 0) + { + if (is_pic) + { @@ -3170,160 +3537,516 @@ index 0000000..8aaf157 + } + } + relocation = off; ++ + break; + + case R_LARCH_SOP_PUSH_TLS_GOT: + case R_LARCH_SOP_PUSH_TLS_GD: -+ if (r_type == R_LARCH_SOP_PUSH_TLS_GOT) -+ is_ie = true; ++ { ++ unresolved_reloc = false; ++ if (r_type == R_LARCH_SOP_PUSH_TLS_GOT) ++ is_ie = true; ++ ++ bfd_vma got_off = 0; ++ if (h != NULL) ++ { ++ got_off = h->got.offset; ++ h->got.offset |= 1; ++ } ++ else ++ { ++ got_off = local_got_offsets[r_symndx]; ++ local_got_offsets[r_symndx] |= 1; ++ } ++ ++ BFD_ASSERT (got_off != MINUS_ONE); ++ ++ ie_off = 0; ++ tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); ++ if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) ++ ie_off = 2 * GOT_ENTRY_SIZE; ++ ++ if ((got_off & 1) == 0) ++ { ++ Elf_Internal_Rela rela; ++ asection *srel = htab->elf.srelgot; ++ bfd_vma tls_block_off = 0; ++ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ BFD_ASSERT (elf_hash_table (info)->tls_sec); ++ tls_block_off = relocation ++ - elf_hash_table (info)->tls_sec->vma; ++ } ++ ++ if (tls_type & GOT_TLS_GD) ++ { ++ rela.r_offset = sec_addr (got) + got_off; ++ rela.r_addend = 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 = 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 = 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 += GOT_ENTRY_SIZE; ++ rela.r_info = 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 = 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 = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); ++ rela.r_addend = 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 = ELFNN_R_INFO (h->dynindx, ++ R_LARCH_TLS_TPRELNN); ++ rela.r_addend = 0; ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ } ++ } ++ } ++ ++ relocation = (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 = false; ++ if (is_undefweak) ++ { ++ relocation = 0; ++ } + -+ if (rel->r_addend != 0) ++ if (resolved_local) + { -+ fatal = (loongarch_reloc_is_fatal -+ (info, input_bfd, input_section, rel, howto, -+ bfd_reloc_notsupported, is_undefweak, name, -+ "Shouldn't be with r_addend.")); ++ relocation -= pc; ++ relocation += rel->r_addend; ++ } ++ else if (resolved_dynly) ++ { ++ BFD_ASSERT (h ++ && (h->plt.offset != MINUS_ONE ++ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) ++ && rel->r_addend == 0); ++ if (h && h->plt.offset == MINUS_ONE ++ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) ++ { ++ relocation -= pc; ++ relocation += rel->r_addend; ++ } ++ else ++ relocation = 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 = 0; + break; + } ++ else if (resolved_to_const || resolved_local) ++ { ++ relocation += rel->r_addend; ++ } ++ else if (resolved_dynly) ++ { ++ unresolved_reloc = false; ++ BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE) ++ && rel->r_addend == 0); ++ relocation = sec_addr (plt) + h->plt.offset; ++ } ++ ++ break; ++ ++ case R_LARCH_PCALA_HI20: ++ unresolved_reloc = false; ++ if (h && h->plt.offset != MINUS_ONE) ++ relocation = sec_addr (plt) + h->plt.offset; ++ else ++ relocation += rel->r_addend; ++ ++ 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 >= 0x800. */ ++ ++ if (h && h->plt.offset != MINUS_ONE) ++ relocation = sec_addr (plt) + h->plt.offset; ++ else ++ relocation += rel->r_addend; + -+ if (resolved_to_const && is_undefweak && h->dynindx != -1) + { -+ /* What if undefweak? Let rtld make a decision. */ -+ resolved_to_const = resolved_local = false; -+ resolved_dynly = true; ++ relocation &= 0xfff; ++ /* Signed extend. */ ++ relocation = (relocation ^ 0x800) - 0x800; ++ ++ /* For 2G jump, generate pcalau12i, jirl. */ ++ /* If use jirl, turns to R_LARCH_B16. */ ++ uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset); ++ if ((insn & 0x4c000000) == 0x4c000000) ++ { ++ rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16); ++ howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16); ++ } + } ++ break; + -+ if (resolved_to_const) ++ case R_LARCH_PCALA64_LO20: ++ case R_LARCH_PCALA64_HI12: ++ if (h && h->plt.offset != MINUS_ONE) ++ relocation = sec_addr (plt) + h->plt.offset; ++ else ++ relocation += rel->r_addend; ++ ++ RELOCATE_CALC_PC64_HI32 (relocation, pc); ++ ++ break; ++ ++ case R_LARCH_GOT_PC_HI20: ++ case R_LARCH_GOT_HI20: ++ /* Calc got offset. */ + { -+ fatal = (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; ++ unresolved_reloc = false; ++ BFD_ASSERT (rel->r_addend == 0); ++ ++ bfd_vma got_off = 0; ++ if (h != NULL) ++ { ++ /* GOT ref or ifunc. */ ++ BFD_ASSERT (h->got.offset != MINUS_ONE ++ || h->type == STT_GNU_IFUNC); ++ ++ got_off = 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 == MINUS_ONE && h->type == STT_GNU_IFUNC) ++ { ++ bfd_vma idx; ++ if (htab->elf.splt != NULL) ++ { ++ idx = (h->plt.offset - PLT_HEADER_SIZE) ++ / PLT_ENTRY_SIZE; ++ got_off = sec_addr (htab->elf.sgotplt) ++ + GOTPLT_HEADER_SIZE ++ + (idx * GOT_ENTRY_SIZE) ++ - sec_addr (htab->elf.sgot); ++ } ++ else ++ { ++ idx = h->plt.offset / PLT_ENTRY_SIZE; ++ got_off = sec_addr (htab->elf.sgotplt) ++ + (idx * GOT_ENTRY_SIZE) ++ - sec_addr (htab->elf.sgot); ++ } ++ } ++ ++ if ((h->got.offset & 1) == 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 = sec_addr (got) + got_off; ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); ++ rela.r_addend = relocation; ++ loongarch_elf_append_rela (output_bfd, ++ htab->elf.srelgot, &rela); ++ } ++ h->got.offset |= 1; ++ } ++ } ++ else ++ { ++ BFD_ASSERT (local_got_offsets ++ && local_got_offsets[r_symndx] != MINUS_ONE); ++ ++ got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1); ++ if ((local_got_offsets[r_symndx] & 1) == 0) ++ { ++ if (bfd_link_pic (info)) ++ { ++ Elf_Internal_Rela rela; ++ rela.r_offset = sec_addr (got) + got_off; ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); ++ rela.r_addend = relocation; ++ loongarch_elf_append_rela (output_bfd, ++ htab->elf.srelgot, &rela); ++ } ++ local_got_offsets[r_symndx] |= 1; ++ } ++ } ++ ++ bfd_put_NN (output_bfd, relocation, got->contents + got_off); ++ ++ relocation = got_off + sec_addr (got); ++ } ++ ++ if (r_type == 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 = false; ++ bfd_vma got_off; ++ if (h) ++ got_off = h->got.offset & (~(bfd_vma)1); ++ else ++ got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1); ++ ++ if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) ++ { ++ bfd_vma idx; ++ if (htab->elf.splt != NULL) ++ idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; ++ else ++ idx = h->plt.offset / PLT_ENTRY_SIZE; ++ ++ got_off = sec_addr (htab->elf.sgotplt) ++ + GOTPLT_HEADER_SIZE ++ + (idx * GOT_ENTRY_SIZE) ++ - sec_addr (htab->elf.sgot); ++ } ++ relocation = got_off + sec_addr (got); + } + ++ if (r_type == R_LARCH_GOT_PC_LO12) ++ relocation &= (bfd_vma)0xfff; ++ else if (r_type == R_LARCH_GOT64_PC_LO20 ++ || r_type == 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 -= 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 |= 1 ++ make only one type be relocated. We must use ++ h->got.offset |= 1 and h->got.offset |= 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 == 0); ++ unresolved_reloc = false; ++ ++ if (r_type == R_LARCH_TLS_IE_PC_HI20 ++ || r_type == R_LARCH_TLS_IE_HI20) ++ is_ie = true; ++ ++ bfd_vma got_off = 0; + if (h != NULL) + { -+ off = h->got.offset; ++ got_off = h->got.offset; + h->got.offset |= 1; + } + else + { -+ off = local_got_offsets[r_symndx]; ++ got_off = local_got_offsets[r_symndx]; + local_got_offsets[r_symndx] |= 1; + } + -+ if (off == MINUS_ONE) -+ { -+ fatal = (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 = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); ++ BFD_ASSERT (got_off != MINUS_ONE); + -+ /* 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 = 0; ++ tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); + if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) + ie_off = 2 * GOT_ENTRY_SIZE; + -+ if ((off & 1) != 0) -+ off &= ~1; -+ else ++ if ((got_off & 1) == 0) + { ++ Elf_Internal_Rela rela; ++ asection *relgot = htab->elf.srelgot; + bfd_vma tls_block_off = 0; -+ Elf_Internal_Rela outrel; + -+ if (resolved_local) ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) + { -+ if (!elf_hash_table (info)->tls_sec) -+ { -+ fatal = (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 = -+ relocation - elf_hash_table (info)->tls_sec->vma; ++ BFD_ASSERT (elf_hash_table (info)->tls_sec); ++ tls_block_off = relocation ++ - elf_hash_table (info)->tls_sec->vma; + } + + if (tls_type & GOT_TLS_GD) + { -+ outrel.r_offset = sec_addr (got) + off; -+ outrel.r_addend = 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 = 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 = sec_addr (got) + got_off; ++ rela.r_addend = 0; ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) + { -+ outrel.r_info = -+ 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 = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); ++ loongarch_elf_append_rela (output_bfd, relgot, &rela); ++ } + -+ outrel.r_offset += 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 = -+ 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 = 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 += GOT_ENTRY_SIZE; ++ rela.r_info = 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 = 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) */) -+ { -+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); -+ outrel.r_addend = tls_block_off; -+ loongarch_elf_append_rela (output_bfd, htab->elf.srelgot, -+ &outrel); -+ } -+ else /* if (resolved_dynly) */ ++ rela.r_offset = sec_addr (got) + got_off + ie_off; ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) + { -+ /* Static linking has no .dynsym table. */ -+ if (!htab->elf.dynamic_sections_created) -+ { -+ outrel.r_info = -+ ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); -+ outrel.r_addend = 0; -+ } -+ else ++ /* Local sym, used in exec, set module id 1. */ ++ if (!bfd_link_executable (info)) + { -+ outrel.r_info = -+ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN); -+ outrel.r_addend = 0; ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); ++ rela.r_addend = 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 = ELFNN_R_INFO (h->dynindx, ++ R_LARCH_TLS_TPRELNN); ++ rela.r_addend = 0; ++ loongarch_elf_append_rela (output_bfd, relgot, &rela); + } + } + } ++ relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got) ++ + (is_ie ? ie_off : 0); ++ ++ if (r_type == R_LARCH_TLS_LD_PC_HI20 ++ || r_type == R_LARCH_TLS_GD_PC_HI20 ++ || r_type == R_LARCH_TLS_IE_PC_HI20) ++ RELOCATE_CALC_PC32_HI20 (relocation, pc); ++ ++ 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 = false; ++ ++ if (h) ++ relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3)); ++ else ++ relocation = sec_addr (got) ++ + (local_got_offsets[r_symndx] & (~(bfd_vma)3)); ++ ++ tls_type = _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 += 2 * GOT_ENTRY_SIZE; ++ ++ if (r_type == R_LARCH_TLS_IE_PC_LO12) ++ relocation &= (bfd_vma)0xfff; ++ else if (r_type == R_LARCH_TLS_IE64_PC_LO20 ++ || r_type == R_LARCH_TLS_IE64_PC_HI12) ++ RELOCATE_CALC_PC64_HI32 (relocation, pc); + -+ relocation = off + (is_ie ? ie_off : 0); ++ break; ++ ++ case R_LARCH_RELAX: + break; + + default: @@ -3343,7 +4066,7 @@ index 0000000..8aaf157 + if (_bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) == 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; + + if (input_section->output_section->flags & SEC_DEBUGGING) @@ -3409,7 +4132,6 @@ index 0000000..8aaf157 + } + + fatal = true; -+ break; + } + + return !fatal; @@ -3444,7 +4166,10 @@ index 0000000..8aaf157 + + plt = htab->elf.splt; + gotplt = htab->elf.sgotplt; -+ relplt = htab->elf.srelplt; ++ if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h)) ++ relplt = htab->elf.srelgot; ++ else ++ relplt = htab->elf.srelplt; + plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + got_address = + sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE; @@ -3473,30 +4198,52 @@ index 0000000..8aaf157 + for (i = 0; i < PLT_ENTRY_INSNS; i++) + bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i); + -+ /* Fill in the initial value of the .got.plt entry. */ ++ /* Fill in the initial value of the got.plt entry. */ + loc = gotplt->contents + (got_address - sec_addr (gotplt)); + bfd_put_NN (output_bfd, sec_addr (plt), loc); + + rela.r_offset = got_address; + + /* TRUE if this is a PLT reference to a local IFUNC. */ -+ if (PLT_LOCAL_IFUNC_P(info, h)) ++ if (PLT_LOCAL_IFUNC_P (info, h) ++ && (relplt == htab->elf.srelgot ++ || relplt == htab->elf.irelplt)) + { -+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); -+ rela.r_addend = (h->root.u.def.value -+ + h->root.u.def.section->output_section->vma -+ + h->root.u.def.section->output_offset); ++ { ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); ++ rela.r_addend = (h->root.u.def.value ++ + h->root.u.def.section->output_section->vma ++ + h->root.u.def.section->output_offset); ++ } ++ ++ /* Find the space after dyn sort. */ ++ { ++ Elf_Internal_Rela *dyn = (Elf_Internal_Rela *)relplt->contents; ++ bool fill = false; ++ for (;dyn < dyn + relplt->size / sizeof (*dyn); dyn++) ++ { ++ if (0 == dyn->r_offset) ++ { ++ bed->s->swap_reloca_out (output_bfd, &rela, ++ (bfd_byte *)dyn); ++ relplt->reloc_count++; ++ fill = true; ++ break; ++ } ++ } ++ BFD_ASSERT (fill); ++ } ++ + } + else + { -+ /* Fill in the entry in the .rela.plt section. */ ++ /* Fill in the entry in the rela.plt section. */ + rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT); + rela.r_addend = 0; ++ loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela); ++ bed->s->swap_reloca_out (output_bfd, &rela, loc); + } + -+ loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela); -+ bed->s->swap_reloca_out (output_bfd, &rela, loc); -+ + if (!h->def_regular) + { + /* Mark the symbol as undefined, rather than as defined in @@ -3514,15 +4261,14 @@ index 0000000..8aaf157 + if (h->got.offset != 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 = h->got.offset & ~(bfd_vma) 1; ++ bfd_vma off = h->got.offset & ~(bfd_vma)1; + + /* This symbol has an entry in the GOT. Set it up. */ -+ + sgot = htab->elf.sgot; + srela = htab->elf.srelgot; + BFD_ASSERT (sgot && srela); @@ -3547,7 +4293,6 @@ index 0000000..8aaf157 + } + else + { -+ BFD_ASSERT ((h->got.offset & 1) == 0); + BFD_ASSERT (h->dynindx != -1); + rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); + rela.r_addend = 0; @@ -3577,7 +4322,6 @@ index 0000000..8aaf157 + } + else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) + { -+ BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr. */); + asection *sec = h->root.u.def.section; + rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); + rela.r_addend = (h->root.u.def.value + sec->output_section->vma @@ -3585,7 +4329,6 @@ index 0000000..8aaf157 + } + else + { -+ BFD_ASSERT ((h->got.offset & 1) == 0); + BFD_ASSERT (h->dynindx != -1); + rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); + rela.r_addend = 0; @@ -3594,24 +4337,6 @@ index 0000000..8aaf157 + loongarch_elf_append_rela (output_bfd, srela, &rela); + } + -+ if (h->needs_copy) -+ { -+ Elf_Internal_Rela rela; -+ asection *s; -+ -+ /* This symbols needs a copy reloc. Set it up. */ -+ BFD_ASSERT (h->dynindx != -1); -+ -+ rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value; -+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY); -+ rela.r_addend = 0; -+ if (h->root.u.def.section == htab->elf.sdynrelro) -+ s = htab->elf.sreldynrelro; -+ else -+ s = htab->elf.srelbss; -+ loongarch_elf_append_rela (output_bfd, s, &rela); -+ } -+ + /* Mark some specially defined symbols as absolute. */ + if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt) + sym->st_shndx = SHN_ABS; @@ -3921,7 +4646,6 @@ index 0000000..8aaf157 +#define PRPSINFO_OFFSET_PR_PS_ARGS 0x38 +#define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50 + -+ +static bool +loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +{ @@ -3992,6 +4716,21 @@ index 0000000..8aaf157 + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); +} + ++/* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For ++ executable PLT slots where the executable never takes the address of those ++ functions, the function symbols are not added to the hash table. */ ++ ++static bool ++elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h) ++{ ++ if (h->plt.offset != (bfd_vma) -1 ++ && !h->def_regular ++ && !h->pointer_equality_needed) ++ return false; ++ ++ return _bfd_elf_hash_symbol (h); ++} ++ +#define TARGET_LITTLE_SYM loongarch_elfNN_vec +#define TARGET_LITTLE_NAME "elfNN-loongarch" +#define ELF_ARCH bfd_arch_loongarch @@ -4023,19 +4762,20 @@ index 0000000..8aaf157 +#define elf_backend_plt_sym_val loongarch_elf_plt_sym_val +#define elf_backend_grok_prstatus loongarch_elf_grok_prstatus +#define elf_backend_grok_psinfo loongarch_elf_grok_psinfo ++#define elf_backend_hash_symbol elf_loongarch64_hash_symbol + +#include "elfNN-target.h" diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c new file mode 100644 -index 0000000..6f7c822 +index 0000000..1455b57 --- /dev/null +++ b/bfd/elfxx-loongarch.c -@@ -0,0 +1,891 @@ +@@ -0,0 +1,1618 @@ +/* LoongArch-specific support for ELF. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. + -+ Based on RISC-V target. ++ Based on LoongArch target. + + This file is part of BFD, the Binary File Descriptor library. + @@ -4068,27 +4808,30 @@ index 0000000..6f7c822 + 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; + +#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 } ++ false), BFD_RELOC_LARCH_##r_name, NULL, NULL } + +#define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \ -+ name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc) \ ++ 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 } + +#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); ++ { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL } + ++static bool ++reloc_bits (reloc_howto_type *howto, bfd_vma *val); ++static bool ++reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val); ++static bool ++reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val); ++static bool ++reloc_bits_b26 (reloc_howto_type *howto, bfd_vma *val); + +/* This does not include any relocation information, but should be + good enough for GDB or objdump to read the file. */ @@ -4109,7 +4852,8 @@ index 0000000..6f7c822 + 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 */ + + /* 32 bit relocation. */ + LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */ @@ -4126,7 +4870,8 @@ index 0000000..6f7c822 + 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 */ + + /* 64 bit relocation. */ + LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */ @@ -4143,7 +4888,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */ + 0, /* rightshift */ @@ -4159,11 +4905,12 @@ index 0000000..6f7c822 + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ -+ NULL), /* adjust_reloc_bits */ ++ NULL, /* adjust_reloc_bits */ ++ NULL), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */ + 0, /* rightshift */ -+ 0, /* this one is variable size */ ++ 3, /* this one is variable size */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ @@ -4174,8 +4921,9 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */ + 0, /* rightshift */ @@ -4190,8 +4938,9 @@ index 0000000..6f7c822 + 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 */ + + /* Dynamic TLS relocations. */ + LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */ @@ -4208,7 +4957,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */ + 0, /* rightshift */ @@ -4224,7 +4974,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */ + 0, /* rightshift */ @@ -4240,7 +4991,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */ + 0, /* rightshift */ @@ -4256,7 +5008,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */ + 0, /* rightshift */ @@ -4272,7 +5025,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */ + 0, /* rightshift */ @@ -4288,7 +5042,8 @@ index 0000000..6f7c822 + 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 */ + + LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */ + 0, /* rightshift */ @@ -4304,63 +5059,67 @@ index 0000000..6f7c822 + ALL_ONES, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_NONE, /* undefined? */ -+ NULL), /* adjust_reloc_bits */ ++ NULL, /* adjust_reloc_bits */ ++ NULL), /* larch_reloc_type_name */ + -+ LOONGARCH_EMPTY_HOWTO(13), -+ LOONGARCH_EMPTY_HOWTO(14), -+ LOONGARCH_EMPTY_HOWTO(15), -+ LOONGARCH_EMPTY_HOWTO(16), -+ LOONGARCH_EMPTY_HOWTO(17), -+ LOONGARCH_EMPTY_HOWTO(18), -+ LOONGARCH_EMPTY_HOWTO(19), ++ LOONGARCH_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. */ ++ 0, /* rightshift. */ ++ 3, /* 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 */ + + LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */ -+ 0, /* rightshift. */ -+ 3, /* size. */ -+ 0, /* bitsize. */ ++ 0, /* rightshift. */ ++ 3, /* 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */ -+ 2, /* rightshift. */ -+ 2, /* size. */ -+ 32, /* bitsize. */ ++ 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. */ ++ 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 */ + + /* type 23-37. */ + LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE), @@ -4380,343 +5139,1001 @@ index 0000000..6f7c822 + LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE), + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 5, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 12, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 12, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 16, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */ + 2, /* rightshift. */ -+ 2, /* size. */ -+ 16, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 20, /* bitsize. */ ++ 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. */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, + /* type (44). */ + 2, /* rightshift. */ + 2, /* 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */ -+ 2, /* rightshift. */ -+ 2, /* size. */ -+ 26, /* bitsize. */ ++ 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 */ ++ 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 */ + + LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 32, /* bitsize. */ ++ 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. */ ++ 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 8, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 16, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 24, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 32, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */ -+ 0, /* rightshift. */ -+ 4, /* size. */ -+ 64, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 8, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 16, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 24, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */ -+ 0, /* rightshift. */ -+ 2, /* size. */ -+ 32, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */ -+ 0, /* rightshift. */ -+ 4, /* size. */ -+ 64, /* bitsize. */ ++ 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, /* 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 */ + -+ LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */ -+ 0, /* rightshift. */ -+ 0, /* size. */ -+ 0, /* bitsize. */ ++ LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */ ++ 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_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 */ + -+ LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */ -+ 0, /* rightshift. */ -+ 0, /* size. */ -+ 0, /* bitsize. */ ++ LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */ ++ 0, /* rightshift. */ ++ 3, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* 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. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_GOT64_PC_HI12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "got64_pc_hi12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_GOT_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "got_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */ ++ 0, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_GOT_LO12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "got_lo12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */ ++ 32, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_GOT64_LO20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "got64_lo20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */ ++ 52, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_GOT64_HI12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "got64_hi12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LE_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "le_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */ ++ 0, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LE_LO12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "le_lo12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */ ++ 32, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LE64_LO20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "le64_lo20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */ ++ 52, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LE64_HI12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "le64_hi12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE_PC_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie_pc_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */ ++ 0, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_unsigned, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE_PC_LO12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie_pc_lo12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */ ++ 32, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE64_PC_LO20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie64_pc_lo20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */ ++ 52, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE64_PC_HI12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie64_pc_hi12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */ ++ 0, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE_LO12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie_lo12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */ ++ 32, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE64_LO20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie64_lo20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */ ++ 52, /* rightshift. */ ++ 2, /* size. */ ++ 12, /* bitsize. */ ++ false, /* pc_relative. */ ++ 10, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_IE64_HI12", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x3ffc00, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ie64_hi12"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LD_PC_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ld_pc_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_LD_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "ld_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_GD_PC_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "gd_pc_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */ ++ 12, /* rightshift. */ ++ 2, /* size. */ ++ 20, /* bitsize. */ ++ false, /* pc_relative. */ ++ 5, /* bitpos. */ ++ complain_overflow_signed, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_TLS_GD_HI20", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0x1ffffe0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */ ++ reloc_bits, /* adjust_reloc_bits */ ++ "gd_hi20"), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */ ++ 0, /* rightshift. */ ++ 2, /* size. */ ++ 32, /* bitsize. */ ++ true, /* pc_relative. */ ++ 0, /* bitpos. */ ++ complain_overflow_dont, /* complain_on_overflow. */ ++ bfd_elf_generic_reloc, /* special_function. */ ++ "R_LARCH_32_PCREL", /* name. */ ++ false, /* partial_inplace. */ ++ 0, /* src_mask */ ++ 0xffffffff, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */ ++ NULL, /* adjust_reloc_bits */ ++ NULL), /* larch_reloc_type_name */ ++ ++ LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */ ++ 0, /* rightshift */ ++ 0, /* size */ ++ 0, /* bitsize */ ++ false, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_dont, /* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_LARCH_RELAX", /* name */ ++ false, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0, /* dst_mask */ ++ false, /* pcrel_offset */ ++ BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */ ++ NULL, /* adjust_reloc_bits */ ++ NULL), /* larch_reloc_type_name */ ++ +}; + +reloc_howto_type * @@ -4730,8 +6147,6 @@ index 0000000..6f7c822 + 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]; @@ -4767,6 +6182,17 @@ index 0000000..6f7c822 +{ + BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count); + ++ /* Fast search for new reloc types. */ ++ if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX) ++ { ++ BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16 ++ == R_LARCH_RELAX - R_LARCH_B16); ++ loongarch_reloc_howto_type *ht = NULL; ++ ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16]; ++ BFD_ASSERT (ht->bfd_type == code); ++ return (reloc_howto_type *)ht; ++ } ++ + for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) + if (loongarch_howto_table[i].bfd_type == code) + return (reloc_howto_type *)&loongarch_howto_table[i]; @@ -4778,56 +6204,89 @@ index 0000000..6f7c822 + return NULL; +} + ++bfd_reloc_code_real_type ++loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, ++ const char *l_r_name) ++{ ++ for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++) ++ { ++ loongarch_reloc_howto_type *lht = &loongarch_howto_table[i]; ++ if ((NULL != lht->larch_reloc_type_name) ++ && (0 == strcmp (lht->larch_reloc_type_name, l_r_name))) ++ return lht->bfd_type; ++ } ++ ++ (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"), ++ abfd, l_r_name); ++ bfd_set_error (bfd_error_bad_value); ++ return BFD_RELOC_NONE; ++} ++ ++ ++/* Functions for reloc bits field. ++ 1. Signed extend *fix_val. ++ 2. Return false if overflow. */ ++ +#define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \ + (~((((bfd_vma)0x1) << (bitsize)) - 1)) + +/* Adjust val to perform insn -+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_5 -+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_12 -+ * BFD_RELOC_LARCH_SOP_POP_32_U_10_12 -+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_16 -+ * BFD_RELOC_LARCH_SOP_POP_32_S_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_RELOC_LARCH_SOP_POP_32_S_10_5 ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_12 ++ BFD_RELOC_LARCH_SOP_POP_32_U_10_12 ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_16 ++ BFD_RELOC_LARCH_SOP_POP_32_S_5_20 ++ BFD_RELOC_LARCH_SOP_POP_32_U. */ ++static bool ++reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val) ++{ ++ bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift; ++ ++ /* Perform insn bits field. */ ++ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); ++ val <<= howto->bitpos; ++ ++ *fix_val = (bfd_vma)val; ++ ++ return true; ++} ++ ++/* Adjust val to perform insn ++ R_LARCH_SOP_POP_32_S_10_16_S2 ++ R_LARCH_B16. */ ++static bool ++reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val) +{ -+ bfd_vma val = *fix_val; -+ /* Check val low bits if rightshift != 0, before rightshift */ -+ if (howto->rightshift -+ && (((0x1UL << howto->rightshift) - 1) & val)) ++ if (howto->complain_on_overflow != complain_overflow_signed) ++ return false; ++ ++ bfd_signed_vma val = *fix_val; ++ ++ /* Judge whether 4 bytes align. */ ++ if (val & ((0x1UL << howto->rightshift) - 1)) + return false; + + int bitsize = howto->bitsize + howto->rightshift; ++ bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1; + -+ /* Return false if overflow. */ -+ if (howto->complain_on_overflow == complain_overflow_signed) ++ /* If val < 0, sign bit is 1. */ ++ if (sig_bit) + { -+ 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; -+ } ++ /* Signed bits is 1. */ ++ if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) ++ != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1)) ++ return false; + } -+ else if (howto->complain_on_overflow == complain_overflow_unsigned) ++ else + { ++ /* Signed bits is 0. */ + 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->rightshift; ++ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); + val <<= howto->bitpos; + + *fix_val = val; @@ -4835,22 +6294,24 @@ index 0000000..6f7c822 + 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) ++/* Reloc type : ++ R_LARCH_SOP_POP_32_S_0_5_10_16_S2 ++ R_LARCH_B21. */ ++static bool ++reloc_bits_b21 (reloc_howto_type *howto, ++ bfd_vma *fix_val) +{ -+ bfd_vma val = *fix_val; -+ /* Check val low bits if rightshift != 0, before rightshift */ -+ if (howto->rightshift -+ && (((0x1UL << howto->rightshift) - 1) & val)) ++ if (howto->complain_on_overflow != complain_overflow_signed) + return false; + -+ /* Return false if overflow. */ -+ if (howto->complain_on_overflow != complain_overflow_signed) ++ bfd_signed_vma val = *fix_val; ++ ++ if (val & ((0x1UL << howto->rightshift) - 1)) + return false; + + int bitsize = howto->bitsize + howto->rightshift; -+ bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1; ++ bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1; ++ + /* If val < 0. */ + if (sig_bit) + { @@ -4860,14 +6321,15 @@ index 0000000..6f7c822 + } + else + { -+ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) ++ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val) + return false; + } + + /* Perform insn bits field. */ -+ val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift; ++ val >>= howto->rightshift; ++ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); + -+ /* Perform insn bits field. 20:16>>16, 15:0<<10 */ ++ /* Perform insn bits field. 15:0<<10, 20:16>>16. */ + val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f); + + *fix_val = val; @@ -4875,22 +6337,25 @@ index 0000000..6f7c822 + 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) ++/* Reloc type: ++ R_LARCH_SOP_POP_32_S_0_10_10_16_S2 ++ R_LARCH_B26. */ ++static bool ++reloc_bits_b26 (reloc_howto_type *howto, ++ bfd_vma *fix_val) +{ -+ 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; + ++ bfd_signed_vma val = *fix_val; ++ ++ if (val & ((0x1UL << howto->rightshift) - 1)) ++ return false; ++ + int bitsize = howto->bitsize + howto->rightshift; -+ bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1; ++ bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1; ++ + /* If val < 0. */ + if (sig_bit) + { @@ -4900,14 +6365,15 @@ index 0000000..6f7c822 + } + else + { -+ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val) ++ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val) + return false; + } + + /* Perform insn bits field. */ -+ val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift; ++ val >>= howto->rightshift; ++ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1); + -+ /* Perform insn bits field. 25:16>>16, 15:0<<10 */ ++ /* Perform insn bits field. 25:16>>16, 15:0<<10. */ + val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff); + + *fix_val = val; @@ -4915,8 +6381,9 @@ index 0000000..6f7c822 + return true; +} + -+bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, -+ bfd_vma *fix_val) ++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 *) @@ -4924,10 +6391,10 @@ index 0000000..6f7c822 +} diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h new file mode 100644 -index 0000000..8ea63d0 +index 0000000..7b8a721 --- /dev/null +++ b/bfd/elfxx-loongarch.h -@@ -0,0 +1,41 @@ +@@ -0,0 +1,45 @@ +/* LoongArch-specific backend routines. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. @@ -4960,6 +6427,10 @@ index 0000000..8ea63d0 +extern reloc_howto_type * +loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name); + ++extern bfd_reloc_code_real_type ++loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, ++ const char *l_r_name); ++ +bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma *fix_val); + +/* TRUE if this is a PLT reference to a local IFUNC. */ @@ -4970,10 +6441,10 @@ index 0000000..8ea63d0 + && (H)->def_regular \ + && (H)->type == STT_GNU_IFUNC)) diff --git a/bfd/libbfd.h b/bfd/libbfd.h -index c37ddc0..48e2978 100644 +index c37ddc0..1b689f2 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h -@@ -3413,6 +3413,49 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", +@@ -3413,6 +3413,86 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4", "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4", "BFD_RELOC_S12Z_OPR", @@ -5020,6 +6491,43 @@ index c37ddc0..48e2978 100644 + "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_32_PCREL", ++ "BFD_RELOC_LARCH_RELAX", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif @@ -5041,7 +6549,7 @@ index f81e2b4..0ecbbcf 100644 elf64-target.h peigen.c diff --git a/bfd/po/SRC-POTFILES.in b/bfd/po/SRC-POTFILES.in -index c83b86c..cd41295 100644 +index c83b86c..d509335 100644 --- a/bfd/po/SRC-POTFILES.in +++ b/bfd/po/SRC-POTFILES.in @@ -72,6 +72,7 @@ cpu-iq2000.c @@ -5052,20 +6560,11 @@ index c83b86c..cd41295 100644 cpu-m10200.c cpu-m10300.c cpu-m32c.c -@@ -262,6 +263,8 @@ elfxx-aarch64.c - elfxx-aarch64.h - elfxx-ia64.c - elfxx-ia64.h -+elfxx-loongarch.c -+elfxx-loongarch.h - elfxx-mips.c - elfxx-mips.h - elfxx-riscv.c diff --git a/bfd/reloc.c b/bfd/reloc.c -index 6d920e1..30826fe 100644 +index 6d920e1..3c768b6 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c -@@ -8171,6 +8171,95 @@ ENUM +@@ -8171,6 +8171,177 @@ ENUM ENUMDOC S12Z relocations. @@ -5155,6 +6654,88 @@ index 6d920e1..30826fe 100644 + BFD_RELOC_LARCH_SUB32 +ENUMX + BFD_RELOC_LARCH_SUB64 ++ ++ENUMX ++ BFD_RELOC_LARCH_B16 ++ENUMX ++ BFD_RELOC_LARCH_B21 ++ENUMX ++ BFD_RELOC_LARCH_B26 ++ ++ENUMX ++ BFD_RELOC_LARCH_ABS_HI20 ++ENUMX ++ BFD_RELOC_LARCH_ABS_LO12 ++ENUMX ++ BFD_RELOC_LARCH_ABS64_LO20 ++ENUMX ++ BFD_RELOC_LARCH_ABS64_HI12 ++ ++ENUMX ++ BFD_RELOC_LARCH_PCALA_HI20 ++ENUMX ++ BFD_RELOC_LARCH_PCALA_LO12 ++ENUMX ++ BFD_RELOC_LARCH_PCALA64_LO20 ++ENUMX ++ BFD_RELOC_LARCH_PCALA64_HI12 ++ ++ENUMX ++ BFD_RELOC_LARCH_GOT_PC_HI20 ++ENUMX ++ BFD_RELOC_LARCH_GOT_PC_LO12 ++ENUMX ++ BFD_RELOC_LARCH_GOT64_PC_LO20 ++ENUMX ++ BFD_RELOC_LARCH_GOT64_PC_HI12 ++ENUMX ++ BFD_RELOC_LARCH_GOT_HI20 ++ENUMX ++ BFD_RELOC_LARCH_GOT_LO12 ++ENUMX ++ BFD_RELOC_LARCH_GOT64_LO20 ++ENUMX ++ BFD_RELOC_LARCH_GOT64_HI12 ++ ++ENUMX ++ BFD_RELOC_LARCH_TLS_LE_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_LE_LO12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_LE64_LO20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_LE64_HI12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE_PC_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE_PC_LO12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE64_PC_LO20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE64_PC_HI12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE_LO12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE64_LO20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_IE64_HI12 ++ENUMX ++ BFD_RELOC_LARCH_TLS_LD_PC_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_LD_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_GD_PC_HI20 ++ENUMX ++ BFD_RELOC_LARCH_TLS_GD_HI20 ++ ++ENUMX ++ BFD_RELOC_LARCH_32_PCREL ++ ++ENUMX ++ BFD_RELOC_LARCH_RELAX ++ +ENUMDOC + LARCH relocations. + @@ -5213,10 +6794,10 @@ index 7eefef9..972a2d0 100644 diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h new file mode 100644 -index 0000000..b7aa4ff +index 0000000..74757b8 --- /dev/null +++ b/include/elf/loongarch.h -@@ -0,0 +1,128 @@ +@@ -0,0 +1,267 @@ +/* Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. + @@ -5309,6 +6890,145 @@ index 0000000..b7aa4ff +RELOC_NUMBER (R_LARCH_GNU_VTINHERIT, 57) +RELOC_NUMBER (R_LARCH_GNU_VTENTRY, 58) + ++ ++/* B16: ++ beq/bne/blt/bge/bltu/bgeu/jirl ++ %b16 (sym). */ ++RELOC_NUMBER (R_LARCH_B16, 64) ++/* B21: ++ beqz/bnez ++ %b16 (sym). */ ++RELOC_NUMBER (R_LARCH_B21, 65) ++/* B26: ++ b/bl ++ %b26 (sym) or %plt (sym). */ ++RELOC_NUMBER (R_LARCH_B26, 66) ++ ++/* ABS: 32/64 ++ lu12i.w ++ %abs_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_ABS_HI20, 67) ++/* ABS: 32/64 ++ ori ++ %abs_lo12 (sym). */ ++RELOC_NUMBER (R_LARCH_ABS_LO12, 68) ++ ++/* ABS: 64 ++ lu32i.d ++ %abs64_lo20 (sym). */ ++RELOC_NUMBER (R_LARCH_ABS64_LO20, 69) ++/* ABS: 64 ++ lu52i.d ++ %abs64_hi12 (sym). */ ++RELOC_NUMBER (R_LARCH_ABS64_HI12, 70) ++ ++/* PCREL: 32/64 ++ pcalau12i ++ %pc_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_PCALA_HI20, 71) ++/* PCREL: 32/64 ++ addi.w/addi.d ++ %pc_lo12 (sym). */ ++RELOC_NUMBER (R_LARCH_PCALA_LO12, 72) ++/* PCREL: 64 ++ lu32i.d ++ %pc64_lo20 (sym). */ ++RELOC_NUMBER (R_LARCH_PCALA64_LO20, 73) ++/* PCREL: 64 ++ lu52i.d ++ %pc64_hi12 (sym). */ ++RELOC_NUMBER (R_LARCH_PCALA64_HI12, 74) ++ ++/* GOT: 32/64 ++ pcalau12i ++ %got_pc_hi20 (got). */ ++RELOC_NUMBER (R_LARCH_GOT_PC_HI20, 75) ++/* GOT: 32/64 ++ ld.w/ld.d ++ %got_pc_lo12 (got). */ ++RELOC_NUMBER (R_LARCH_GOT_PC_LO12, 76) ++/* GOT: 32/64 ++ lu32i.d ++ %got_pc_lo12 (got). */ ++RELOC_NUMBER (R_LARCH_GOT64_PC_LO20, 77) ++/* GOT64: PCREL ++ lu52i.d ++ %got64_pc_hi12 (got). */ ++RELOC_NUMBER (R_LARCH_GOT64_PC_HI12, 78) ++/* GOT32/64: ABS ++ lu12i.w ++ %got_hi20 (got). */ ++RELOC_NUMBER (R_LARCH_GOT_HI20, 79) ++/* GOT: 32/64: ABS ++ ori ++ %got_lo12 (got). */ ++RELOC_NUMBER (R_LARCH_GOT_LO12, 80) ++/* GOT64: ABS ++ lu32i.d ++ %got64_lo20 (got). */ ++RELOC_NUMBER (R_LARCH_GOT64_LO20, 81) ++/* GOT64: ABS ++ lu52i.d ++ %got64_hi12 (got). */ ++RELOC_NUMBER (R_LARCH_GOT64_HI12, 82) ++ ++/* TLS-LE: 32/64 ++ lu12i.w ++ %le_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LE_HI20, 83) ++/* TLS-LE: 32/64 ++ ori ++ %le_lo12 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LE_LO12, 84) ++/* TLS-LE: 64 ++ lu32i.d ++ %le64_lo20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LE64_LO20, 85) ++/* TLS-LE: 64 ++ lu52i.d ++ %le64_hi12 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LE64_HI12, 86) ++ ++/* TLS-IE: 32/64 ++ pcalau12i ++ %ie_pc_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_IE_PC_HI20, 87) ++RELOC_NUMBER (R_LARCH_TLS_IE_PC_LO12, 88) ++RELOC_NUMBER (R_LARCH_TLS_IE64_PC_LO20, 89) ++RELOC_NUMBER (R_LARCH_TLS_IE64_PC_HI12, 90) ++ ++/* TLS-IE: 32/64: ABS ++ lu12i.w ++ %ie_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_IE_HI20, 91) ++RELOC_NUMBER (R_LARCH_TLS_IE_LO12, 92) ++RELOC_NUMBER (R_LARCH_TLS_IE64_LO20, 93) ++RELOC_NUMBER (R_LARCH_TLS_IE64_HI12, 94) ++ ++/* TLS-LD: 32/64 ++ pcalau12i ++ %ld_pc_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LD_PC_HI20, 95) ++/* TLS-LD: 32/64: ABS ++ lu12i.w ++ %ld_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_LD_HI20, 96) ++ ++/* TLS-GD: 32/64 ++ pcalau12i ++ %gd_pc_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_GD_PC_HI20, 97) ++/* TLS-GD: 32/64: ABS ++ lu12i.w ++ %gd_hi20 (sym). */ ++RELOC_NUMBER (R_LARCH_TLS_GD_HI20, 98) ++ ++/* For eh_frame and debug info. */ ++RELOC_NUMBER (R_LARCH_32_PCREL, 99) ++ ++/* RELAX. */ ++RELOC_NUMBER (R_LARCH_RELAX, 100) ++ +END_RELOC_NUMBERS (R_LARCH_count) + +/* Processor specific flags for the ELF header e_flags field. */ @@ -5346,5 +7066,5 @@ index 0000000..b7aa4ff + +#endif /* _ELF_LOONGARCH_H */ -- -2.20.1 +2.36.0 diff --git a/0002-gdb-Add-LoongArch-opcodes-support.patch b/0002-gdb-Add-LoongArch-opcodes-support.patch index e9c0d79a498d0ff7c2df8d85fb3fc3a61695c692..a9aa424669c4e348ad00312dbb4edbd7a44fb856 100644 --- a/0002-gdb-Add-LoongArch-opcodes-support.patch +++ b/0002-gdb-Add-LoongArch-opcodes-support.patch @@ -1,27 +1,27 @@ -From f0b7f4b788c984bfc86c8e06c83185c827470b26 Mon Sep 17 00:00:00 2001 +From ad126df75ca6fa31231596f9fc308b174145e731 Mon Sep 17 00:00:00 2001 From: Qing Zhang -Date: Tue, 29 Mar 2022 16:10:14 +0800 -Subject: [PATCH 2/4] gdb-Add LoongArch opcodes support +Date: Thu, 22 Sep 2022 12:48:54 +0800 +Subject: [PATCH 2/5] gdb-Add LoongArch opcodes support Signed-off-by: Qing Zhang --- - gdb-11.1/include/dis-asm.h | 1 + - gdb-11.1/include/opcode/loongarch.h | 239 +++++++++ - gdb-11.1/opcodes/Makefile.am | 3 + - gdb-11.1/opcodes/Makefile.in | 6 + - gdb-11.1/opcodes/configure | 3 +- - gdb-11.1/opcodes/configure.ac | 1 + - gdb-11.1/opcodes/disassemble.c | 9 + - gdb-11.1/opcodes/disassemble.h | 1 + - gdb-11.1/opcodes/loongarch-coder.c | 481 +++++++++++++++++ - gdb-11.1/opcodes/loongarch-dis.c | 342 ++++++++++++ - gdb-11.1/opcodes/loongarch-opc.c | 798 ++++++++++++++++++++++++++++ - gdb-11.1/opcodes/po/POTFILES.in | 3 + - 12 files changed, 1886 insertions(+), 1 deletion(-) - create mode 100644 gdb-11.1/include/opcode/loongarch.h - create mode 100644 gdb-11.1/opcodes/loongarch-coder.c - create mode 100644 gdb-11.1/opcodes/loongarch-dis.c - create mode 100644 gdb-11.1/opcodes/loongarch-opc.c + include/dis-asm.h | 1 + + include/opcode/loongarch.h | 239 ++++++++++ + opcodes/Makefile.am | 3 + + opcodes/Makefile.in | 6 + + opcodes/configure | 1 + + opcodes/configure.ac | 1 + + opcodes/disassemble.c | 9 + + opcodes/disassemble.h | 1 + + opcodes/loongarch-coder.c | 481 ++++++++++++++++++++ + opcodes/loongarch-dis.c | 342 +++++++++++++++ + opcodes/loongarch-opc.c | 870 +++++++++++++++++++++++++++++++++++++ + opcodes/po/POTFILES.in | 3 + + 12 files changed, 1957 insertions(+) + create mode 100644 include/opcode/loongarch.h + create mode 100644 opcodes/loongarch-coder.c + create mode 100644 opcodes/loongarch-dis.c + create mode 100644 opcodes/loongarch-opc.c diff --git a/include/dis-asm.h b/include/dis-asm.h index 0b91ab4..c0bc1d5 100644 @@ -319,23 +319,14 @@ index 42c15f0..8ba01c9 100644 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m10200-opc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m10300-dis.Plo@am__quote@ diff --git a/opcodes/configure b/opcodes/configure -index 3513e40..8b0d15b 100755 +index 3513e40..aa46453 100755 --- a/opcodes/configure +++ b/opcodes/configure -@@ -11,7 +11,7 @@ - ## -------------------- ## - ## M4sh Initialization. ## - ## -------------------- ## -- -+ooooooooo - # Be more Bourne compatible - DUALCASE=1; export DUALCASE # for MKS sh - if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : @@ -12294,6 +12294,7 @@ if test x${all_targets} = xfalse ; then bfd_z80_arch) ta="$ta z80-dis.lo" ;; bfd_z8k_arch) ta="$ta z8k-dis.lo" ;; bfd_bpf_arch) ta="$ta bpf-asm.lo bpf-desc.lo bpf-dis.lo bpf-ibld.lo bpf-opc.lo" using_cgen=yes ;; -+ bfd_loongarch_arch) ta="$ta loongarch-dis.lo loongarch-opc.lo loongarch-coder.lo" ;; ++ bfd_loongarch_arch) ta="$ta loongarch-dis.lo loongarch-opc.lo loongarch-coder.lo" ;; "") ;; *) as_fn_error $? "*** unknown target architecture $arch" "$LINENO" 5 ;; @@ -1234,10 +1225,10 @@ index 0000000..9dcf989 +} diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c new file mode 100644 -index 0000000..62a2edb +index 0000000..be0de61 --- /dev/null +++ b/opcodes/loongarch-opc.c -@@ -0,0 +1,798 @@ +@@ -0,0 +1,870 @@ +/* LoongArch opcode support. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. @@ -1343,158 +1334,230 @@ index 0000000..62a2edb + "$xr24", "$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31", +}; + ++/* Can not use xx_pa for abs. */ ++ ++/* For LoongArch32 abs. */ ++#define INSN_LA_ABS32 \ ++ "lu12i.w %1,%%abs_hi20(%2);" \ ++ "ori %1,%1,%%abs_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_ABS64 \ ++ "lu12i.w %1,%%abs_hi20(%2);" \ ++ "ori %1,%1,%%abs_lo12(%2);" \ ++ "lu32i.d %1,%%abs64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%abs64_hi12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++ ++#define INSN_LA_PCREL32 \ ++ "pcalau12i %1,%%pc_hi20(%2);" \ ++ "addi.w %1,%1,%%pc_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_PCREL64 \ ++ "pcalau12i %1,%%pc_hi20(%2);" \ ++ "addi.d %1,%1,%%pc_lo12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++#define INSN_LA_PCREL64_LARGE \ ++ "pcalau12i %1,%%pc_hi20(%3);" \ ++ "addi.d %2,$r0,%%pc_lo12(%3);" \ ++ "lu32i.d %2,%%pc64_lo20(%3);" \ ++ "lu52i.d %2,%2,%%pc64_hi12(%3);" \ ++ "add.d %1,%1,%2;", \ ++ &LARCH_opts.ase_lp64, 0 ++ ++#define INSN_LA_GOT32 \ ++ "pcalau12i %1,%%got_pc_hi20(%2);" \ ++ "ld.w %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++/* got32 abs. */ ++#define INSN_LA_GOT32_ABS \ ++ "lu12i.w %1,%%got_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);" \ ++ "ld.w %1,%1,0;", \ ++ &LARCH_opts.ase_gabs, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_GOT64 \ ++ "pcalau12i %1,%%got_pc_hi20(%2);" \ ++ "ld.d %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++/* got64 abs. */ ++#define INSN_LA_GOT64_LARGE_ABS \ ++ "lu12i.w %1,%%got_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);" \ ++ "lu32i.d %1,%%got64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%got64_hi12(%2);" \ ++ "ld.d %1,%1,0", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gpcr ++/* got64 pic. */ ++#define INSN_LA_GOT64_LARGE_PCREL \ ++ "pcalau12i %1,%%got_pc_hi20(%3);" \ ++ "addi.d %2,$r0,%%got_pc_lo12(%3);" \ ++ "lu32i.d %2,%%got64_pc_lo20(%3);" \ ++ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\ ++ "ldx.d %1,%1,%2;", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gabs ++ ++/* For LoongArch32/64 cmode=normal. */ ++#define INSN_LA_TLS_LE \ ++ "lu12i.w %1,%%le_hi20(%2);" \ ++ "ori %1,%1,%%le_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, 0 ++ ++/* For LoongArch64 cmode=large. */ ++#define INSN_LA_TLS_LE64_LARGE \ ++ "lu12i.w %1,%%le_hi20(%2);" \ ++ "ori %1,%1,%%le_lo12(%2);" \ ++ "lu32i.d %1,%%le64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%le64_hi12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++ ++#define INSN_LA_TLS_IE32 \ ++ "pcalau12i %1,%%ie_pc_hi20(%2);" \ ++ "ld.w %1,%1,%%ie_pc_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++/* For ie32 abs. */ ++#define INSN_LA_TLS_IE32_ABS \ ++ "lu12i.w %1,%%ie_hi20(%2);" \ ++ "ori %1,%1,%%ie_lo12(%2);" \ ++ "ld.w %1,%1,0", \ ++ &LARCH_opts.ase_gabs, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_TLS_IE64 \ ++ "pcalau12i %1,%%ie_pc_hi20(%2);" \ ++ "ld.d %1,%1,%%ie_pc_lo12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++/* For ie64 pic. */ ++#define INSN_LA_TLS_IE64_LARGE_PCREL \ ++ "pcalau12i %1,%%ie_pc_hi20(%3);" \ ++ "addi.d %2,$r0,%%ie_pc_lo12(%3);" \ ++ "lu32i.d %2,%%ie64_pc_lo20(%3);" \ ++ "lu52i.d %2,%2,%%ie64_pc_hi12(%3);"\ ++ "ldx.d %1,%1,%2;", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gabs ++/* For ie64 abs. */ ++#define INSN_LA_TLS_IE64_LARGE_ABS \ ++ "lu12i.w %1,%%ie_hi20(%2);" \ ++ "ori %1,%1,%%ie_lo12(%2);" \ ++ "lu32i.d %1,%%ie64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%ie64_hi12(%2);" \ ++ "ld.d %1,%1,0", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gpcr ++ ++/* For LoongArch32/64 cmode=normal. */ ++#define INSN_LA_TLS_LD32 \ ++ "pcalau12i %1,%%ld_pc_hi20(%2);" \ ++ "addi.w %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_TLS_LD32_ABS \ ++ "lu12i.w %1,%%ld_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);", \ ++ &LARCH_opts.ase_gabs, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_TLS_LD64 \ ++ "pcalau12i %1,%%ld_pc_hi20(%2);" \ ++ "addi.d %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++#define INSN_LA_TLS_LD64_LARGE_PCREL \ ++ "pcalau12i %1,%%ld_pc_hi20(%3);" \ ++ "addi.d %2,$r0,%%got_pc_lo12(%3);" \ ++ "lu32i.d %2,%%got64_pc_lo20(%3);" \ ++ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\ ++ "add.d %1,%1,%2;", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gabs ++#define INSN_LA_TLS_LD64_LARGE_ABS \ ++ "lu12i.w %1,%%ld_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);" \ ++ "lu32i.d %1,%%got64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%got64_hi12(%2);", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gpcr ++ ++#define INSN_LA_TLS_GD32 \ ++ "pcalau12i %1,%%gd_pc_hi20(%2);" \ ++ "addi.w %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_ilp32, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_TLS_GD32_ABS \ ++ "lu12i.w %1,%%gd_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);", \ ++ &LARCH_opts.ase_gabs, \ ++ &LARCH_opts.ase_lp64 ++#define INSN_LA_TLS_GD64 \ ++ "pcalau12i %1,%%gd_pc_hi20(%2);" \ ++ "addi.d %1,%1,%%got_pc_lo12(%2);", \ ++ &LARCH_opts.ase_lp64, 0 ++#define INSN_LA_TLS_GD64_LARGE_PCREL \ ++ "pcalau12i %1,%%gd_pc_hi20(%3);" \ ++ "addi.d %2,$r0,%%got_pc_lo12(%3);" \ ++ "lu32i.d %2,%%got64_pc_lo20(%3);" \ ++ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\ ++ "add.d %1,%1,%2;", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gabs ++#define INSN_LA_TLS_GD64_LARGE_ABS \ ++ "lu12i.w %1,%%gd_hi20(%2);" \ ++ "ori %1,%1,%%got_lo12(%2);" \ ++ "lu32i.d %1,%%got64_lo20(%2);" \ ++ "lu52i.d %1,%1,%%got64_hi12(%2);", \ ++ &LARCH_opts.ase_lp64, \ ++ &LARCH_opts.ase_gpcr ++ ++ +static struct loongarch_opcode loongarch_macro_opcodes[] = +{ -+ /* match, mask, name, format, macro, include, exclude, pinfo. */ -+ { 0, 0, "li.w", "r,sc", "%f", 0, 0, 0}, -+ { 0, 0, "li.d", "r,sc", "%f", 0, 0, 0}, -+ { 0, 0, "la", "r,la", "la.global %1,%2", 0, 0, 0 }, -+ -+ { 0, 0, "la.global", "r,la", "la.pcrel %1,%2", -+ &LARCH_opts.ase_gpcr, 0, 0 }, -+ { 0, 0, "la.global", "r,r,la", "la.pcrel %1,%2,%3", -+ &LARCH_opts.ase_gpcr, 0, 0 }, -+ { 0, 0, "la.global", "r,la", "la.abs %1,%2", -+ &LARCH_opts.ase_gabs, 0, 0 }, -+ { 0, 0, "la.global", "r,r,la", "la.abs %1,%3", -+ &LARCH_opts.ase_gabs, 0, 0 }, -+ { 0, 0, "la.global", "r,l", "la.got %1,%2", 0, 0, 0 }, -+ { 0, 0, "la.global", "r,r,l", "la.got %1,%2,%3", 0, 0, 0 }, -+ -+ { 0, 0, "la.local", "r,la", "la.abs %1,%2", -+ &LARCH_opts.ase_labs, 0, 0 }, -+ { 0, 0, "la.local", "r,r,la", "la.abs %1,%3", -+ &LARCH_opts.ase_labs, 0, 0 }, -+ { 0, 0, "la.local", "r,la", "la.pcrel %1,%2", 0, 0, 0 }, -+ { 0, 0, "la.local", "r,r,la", "la.pcrel %1,%2,%3", 0, 0, 0 }, -+ -+ { 0, 0, "la.abs", "r,la", -+ "lu12i.w %1,%%abs(%2)>>12;" -+ "ori %1,%1,%%abs(%2)&0xfff;", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ { 0, 0, "la.abs", "r,la", -+ "lu12i.w %1,%%abs(%2)<<32>>44;" -+ "ori %1,%1,%%abs(%2)&0xfff;" -+ "lu32i.d %1,%%abs(%2)<<12>>44;" -+ "lu52i.d %1,%1,%%abs(%2)>>52;", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.pcrel", "r,la", -+ "pcaddu12i %1,%%pcrel(%2+0x800)<<32>>44;" -+ "addi.w %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ -+ { 0, 0, "la.pcrel", "r,la", -+ "pcaddu12i %1,%%pcrel(%2+0x800)>>12;" -+ "addi.d %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ { 0, 0, "la.pcrel", "r,r,la", -+ "pcaddu12i %1,(%%pcrel(%3)-(%%pcrel(%3+0x80000000)>>32<<32))<<32>>44;" -+ "ori %2,$r0,(%%pcrel(%3+4)-(%%pcrel(%3+4+0x80000000)>>32<<32))&0xfff;" -+ "lu32i.d %2,%%pcrel(%3+8+0x80000000)<<12>>44;" -+ "lu52i.d %2,%2,%%pcrel(%3+12+0x80000000)>>52;" -+ "add.d %1,%1,%2;", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.got", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))<<32>>44;" -+ "ld.w " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ -+ { 0, 0, "la.got", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))>>12;" -+ "ld.d " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ { 0, 0, "la.got", "r,r,l", -+ "pcaddu12i " -+ "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_" -+ "TABLE_+0x80000000)+%%gprel(%3))>>32<<32))<<32>>44;" -+ "ori " -+ "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%3)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x80000000)+%%gprel(%3))>>32<<32))&0xfff;" -+ "lu32i.d " -+ "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%gprel(%3))<<12>>44;" -+ "lu52i.d " -+ "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%gprel(%3))>>52;" -+ "ldx.d %1,%1,%2;", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.tls.le", "r,la", -+ "lu12i.w %1,%%tprel(%2)>>12;" -+ "ori %1,%1,%%tprel(%2)&0xfff", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ /* { 0, 0, "la.tls.le", "r,la", -+ * "lu12i.w %1,%%tprel(%2)>>12;" -+ * "ori %1,%1,%%tprel(%2)&0xfff" -+ * , &LARCH_opts.addrwidth_is_64, 0, 0}, */ -+ { 0, 0, "la.tls.le", "r,la", -+ "lu12i.w %1,%%tprel(%2)<<32>>44;" -+ "ori %1,%1,%%tprel(%2)&0xfff;" -+ "lu32i.d %1,%%tprel(%2)<<12>>44;" -+ "lu52i.d %1,%1,%%tprel(%2)>>52;", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.tls.ie", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))<<32>>44;" -+ "ld.w " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ -+ { 0, 0, "la.tls.ie", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))>>12;" -+ "ld.d " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ { 0, 0, "la.tls.ie", "r,r,l", -+ "pcaddu12i " -+ "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_" -+ "TABLE_+0x80000000)+%%tlsgot(%3))>>32<<32))<<32>>44;" -+ "ori " -+ "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x80000000)+%%tlsgot(%3))>>32<<32))&0xfff;" -+ "lu32i.d " -+ "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgot(%3))<<12>>44;" -+ "lu52i.d " -+ "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgot(%3))>>52;" -+ "ldx.d %1,%1,%2;", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.tls.ld", "r,l", "la.tls.gd %1,%2", 0, 0, 0 }, -+ { 0, 0, "la.tls.ld", "r,r,l", "la.tls.gd %1,%2,%3", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ -+ { 0, 0, "la.tls.gd", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))<<32>>44;" -+ "addi.w " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);", -+ &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 }, -+ -+ { 0, 0, "la.tls.gd", "r,l", -+ "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))>>12;" -+ "addi.d " -+ "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);", -+ &LARCH_opts.ase_lp64, 0, 0 }, -+ { 0, 0, "la.tls.gd", "r,r,l", -+ "pcaddu12i " -+ "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_" -+ "TABLE_+0x80000000)+%%tlsgd(%3))>>32<<32))<<32>>44;" -+ "ori " -+ "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_" -+ "OFFSET_TABLE_+4+0x80000000)+%%tlsgd(%3))>>32<<32))&0xfff;" -+ "lu32i.d " -+ "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgd(%3))<<12>>44;" -+ "lu52i.d " -+ "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgd(%3))>>52;" -+ "add.d %1,%1,%2;", -+ &LARCH_opts.ase_lp64, 0, 0 }, ++ /* match, mask, name, format, macro, include, exclude, pinfo. */ ++ { 0, 0, "li.w", "r,sc", "%f", 0, 0, 0 }, ++ { 0, 0, "li.d", "r,sc", "%f", 0, 0, 0 }, ++ ++ { 0, 0, "la", "r,la", "la.global %1,%2", 0, 0, 0 }, ++ { 0, 0, "la.global", "r,la", "la.pcrel %1,%2", &LARCH_opts.ase_gpcr, 0, 0 }, ++ { 0, 0, "la.global", "r,r,la", "la.pcrel %1,%2,%3", &LARCH_opts.ase_gpcr, 0, 0 }, ++ { 0, 0, "la.global", "r,la", "la.abs %1,%2", &LARCH_opts.ase_gabs, 0, 0 }, ++ { 0, 0, "la.global", "r,r,la", "la.abs %1,%3", &LARCH_opts.ase_gabs, 0, 0 }, ++ { 0, 0, "la.global", "r,la", "la.got %1,%2", 0, 0, 0 }, ++ { 0, 0, "la.global", "r,r,la", "la.got %1,%2,%3", &LARCH_opts.ase_lp64, 0, 0 }, ++ ++ { 0, 0, "la.local", "r,la", "la.abs %1,%2", &LARCH_opts.ase_labs, 0, 0 }, ++ { 0, 0, "la.local", "r,r,la", "la.abs %1,%3", &LARCH_opts.ase_labs, 0, 0 }, ++ { 0, 0, "la.local", "r,la", "la.pcrel %1,%2", 0, 0, 0 }, ++ { 0, 0, "la.local", "r,r,la", "la.pcrel %1,%2,%3", &LARCH_opts.ase_lp64, 0, 0 }, ++ ++ { 0, 0, "la.abs", "r,la", INSN_LA_ABS32, 0 }, ++ { 0, 0, "la.abs", "r,la", INSN_LA_ABS64, 0 }, ++ { 0, 0, "la.pcrel", "r,la", INSN_LA_PCREL32, 0 }, ++ { 0, 0, "la.pcrel", "r,la", INSN_LA_PCREL64, 0 }, ++ { 0, 0, "la.pcrel", "r,r,la", INSN_LA_PCREL64_LARGE, 0 }, ++ { 0, 0, "la.got", "r,la", INSN_LA_GOT32, 0 }, ++ { 0, 0, "la.got", "r,la", INSN_LA_GOT32_ABS, 0 }, ++ { 0, 0, "la.got", "r,la", INSN_LA_GOT64, 0 }, ++ { 0, 0, "la.got", "r,la", INSN_LA_GOT64_LARGE_ABS, 0 }, ++ { 0, 0, "la.got", "r,r,la", INSN_LA_GOT64_LARGE_PCREL, 0 }, ++ { 0, 0, "la.tls.le", "r,l", INSN_LA_TLS_LE, 0 }, ++ { 0, 0, "la.tls.le", "r,l", INSN_LA_TLS_LE64_LARGE, 0 }, ++ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE32, 0 }, ++ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE32_ABS, 0 }, ++ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE64, 0 }, ++ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE64_LARGE_ABS, 0 }, ++ { 0, 0, "la.tls.ie", "r,r,l", INSN_LA_TLS_IE64_LARGE_PCREL, 0 }, ++ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD32, 0 }, ++ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD32_ABS, 0 }, ++ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD64, 0 }, ++ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD64_LARGE_ABS, 0 }, ++ { 0, 0, "la.tls.ld", "r,r,l", INSN_LA_TLS_LD64_LARGE_PCREL, 0 }, ++ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD32, 0 }, ++ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD32_ABS, 0 }, ++ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD64, 0 }, ++ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD64_LARGE_ABS, 0 }, ++ { 0, 0, "la.tls.gd", "r,r,l", INSN_LA_TLS_GD64_LARGE_PCREL, 0 }, + + { 0 } /* Terminate the list. */ +}; @@ -1968,9 +2031,9 @@ index 0000000..62a2edb + +static struct loongarch_opcode loongarch_float_jmp_opcodes[] = +{ -+ { 0x0, 0x0, "bceqz", "c,la", "bceqz %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bceqz", "c,la", "bceqz %1,%%b21(%2)", 0, 0, 0 }, + { 0x48000000, 0xfc000300, "bceqz", "c5:3,sb0:5|10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bcnez", "c,la", "bcnez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bcnez", "c,la", "bcnez %1,%%b21(%2)", 0, 0, 0 }, + { 0x48000100, 0xfc000300, "bcnez", "c5:3,sb0:5|10:16<<2", 0, 0, 0, 0 }, + { 0 } /* Terminate the list. */ +}; @@ -1978,43 +2041,43 @@ index 0000000..62a2edb +static struct loongarch_opcode loongarch_jmp_opcodes[] = +{ + /* match, mask, name, format, macro, include, exclude, pinfo. */ -+ { 0x0, 0x0, "bltz", "r,la", "bltz %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bltz", "r,la", "bltz %1,%%b16(%2)", 0, 0, 0 }, + { 0x60000000, 0xfc00001f, "bltz", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgtz", "r,la", "bgtz %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bgtz", "r,la", "bgtz %1,%%b16(%2)", 0, 0, 0 }, + { 0x60000000, 0xfc0003e0, "bgtz", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgez", "r,la", "bgez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bgez", "r,la", "bgez %1,%%b16(%2)", 0, 0, 0 }, + { 0x64000000, 0xfc00001f, "bgez", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "blez", "r,la", "blez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "blez", "r,la", "blez %1,%%b16(%2)", 0, 0, 0 }, + { 0x64000000, 0xfc0003e0, "blez", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "beqz", "r,la", "beqz %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "beqz", "r,la", "beqz %1,%%b21(%2)", 0, 0, 0 }, + { 0x40000000, 0xfc000000, "beqz", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bnez", "r,la", "bnez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x0, 0x0, "bnez", "r,la", "bnez %1,%%b21(%2)", 0, 0, 0 }, + { 0x44000000, 0xfc000000, "bnez", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0 }, + { 0x0, 0x0, "jr", "r", "jirl $r0,%1,0", 0, 0, 0 }, + { 0x50000000, 0xfc000000, "b", "sb0:10|10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "b", "la", "b %%pcrel(%1)", 0, 0, 0 }, ++ { 0x0, 0x0, "b", "la", "b %%b26(%1)", 0, 0, 0 }, + { 0x4c000000, 0xfc000000, "jirl", "r0:5,r5:5,s10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bl", "la", "bl %%pcrel(%1)", 0, 0, 0 }, ++ { 0x0, 0x0, "bl", "la", "bl %%b26(%1)", 0, 0, 0 }, + { 0x54000000, 0xfc000000, "bl", "sb0:10|10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "beq", "r,r,la", "beq %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "beq", "r,r,la", "beq %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x58000000, 0xfc000000, "beq", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bne", "r,r,la", "bne %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bne", "r,r,la", "bne %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x5c000000, 0xfc000000, "bne", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "blt", "r,r,la", "blt %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "blt", "r,r,la", "blt %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x60000000, 0xfc000000, "blt", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgt", "r,r,la", "bgt %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bgt", "r,r,la", "bgt %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x60000000, 0xfc000000, "bgt", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bge", "r,r,la", "bge %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bge", "r,r,la", "bge %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x64000000, 0xfc000000, "bge", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "ble", "r,r,la", "ble %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "ble", "r,r,la", "ble %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x64000000, 0xfc000000, "ble", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bltu", "r,r,la", "bltu %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bltu", "r,r,la", "bltu %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x68000000, 0xfc000000, "bltu", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgtu", "r,r,la", "bgtu %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bgtu", "r,r,la", "bgtu %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x68000000, 0xfc000000, "bgtu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgeu", "r,r,la", "bgeu %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bgeu", "r,r,la", "bgeu %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x6c000000, 0xfc000000, "bgeu", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bleu", "r,r,la", "bleu %1,%2,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x0, 0x0, "bleu", "r,r,la", "bleu %1,%2,%%b16(%3)", 0, 0, 0 }, + { 0x6c000000, 0xfc000000, "bleu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, + { 0 } /* Terminate the list. */ +}; @@ -2051,5 +2114,5 @@ index 0659b99..b1037a4 100644 m10200-opc.c m10300-dis.c -- -2.20.1 +2.36.0 diff --git a/0003-gdb-Add-LoongArch-gdb-support.patch b/0003-gdb-Add-LoongArch-gdb-support.patch index f3b53e8bafd4b93b9d93a57749a01431a455459f..f8872a75c7e7eb200784e3bd4431e697f935bdb4 100644 --- a/0003-gdb-Add-LoongArch-gdb-support.patch +++ b/0003-gdb-Add-LoongArch-gdb-support.patch @@ -1,77 +1,77 @@ -From 5143f24613f98a3c7b3ce0fc133b41f3adaef752 Mon Sep 17 00:00:00 2001 +From ef2f4994997351182739fce55e32a6a1228739b0 Mon Sep 17 00:00:00 2001 From: Qing Zhang Date: Tue, 29 Mar 2022 16:11:47 +0800 -Subject: [PATCH 3/4] gdb-Add LoongArch gdb support +Subject: [PATCH 3/5] gdb-Add LoongArch gdb support Signed-off-by: Qing Zhang --- - gdb-11.1/gdb/Makefile.in | 13 + - gdb-11.1/gdb/arch/loongarch-linux-nat.c | 94 + - gdb-11.1/gdb/arch/loongarch-linux-nat.h | 35 + - gdb-11.1/gdb/arch/loongarch.c | 84 + - gdb-11.1/gdb/arch/loongarch.h | 37 + - gdb-11.1/gdb/configure.host | 3 + - gdb-11.1/gdb/configure.nat | 4 + - gdb-11.1/gdb/configure.tgt | 8 + - gdb-11.1/gdb/doc/gdb.texinfo | 10 + - gdb-11.1/gdb/features/Makefile | 10 + - gdb-11.1/gdb/features/loongarch/base32.c | 47 + - gdb-11.1/gdb/features/loongarch/base32.xml | 45 + - gdb-11.1/gdb/features/loongarch/base64.c | 47 + - gdb-11.1/gdb/features/loongarch/base64.xml | 45 + - gdb-11.1/gdb/features/loongarch/fpu32.c | 54 + - gdb-11.1/gdb/features/loongarch/fpu32.xml | 53 + - gdb-11.1/gdb/features/loongarch/fpu64.c | 62 + - gdb-11.1/gdb/features/loongarch/fpu64.xml | 58 + - gdb-11.1/gdb/features/loongarch/lasx.c | 80 + - gdb-11.1/gdb/features/loongarch/lasx.xml | 59 + - gdb-11.1/gdb/features/loongarch/lbt32.c | 19 + - gdb-11.1/gdb/features/loongarch/lbt32.xml | 17 + - gdb-11.1/gdb/features/loongarch/lbt64.c | 19 + - gdb-11.1/gdb/features/loongarch/lbt64.xml | 17 + - gdb-11.1/gdb/features/loongarch/lsx.c | 80 + - gdb-11.1/gdb/features/loongarch/lsx.xml | 59 + - gdb-11.1/gdb/loongarch-linux-nat.c | 876 ++++++++ - gdb-11.1/gdb/loongarch-linux-tdep.c | 699 ++++++ - gdb-11.1/gdb/loongarch-linux-tdep.h | 48 + - gdb-11.1/gdb/loongarch-tdep.c | 1925 +++++++++++++++++ - gdb-11.1/gdb/loongarch-tdep.h | 60 + - gdb-11.1/gdb/nat/loongarch-linux-watch.c | 330 +++ - gdb-11.1/gdb/nat/loongarch-linux-watch.h | 132 ++ - gdb-11.1/gdb/remote.c | 25 + - gdb-11.1/gdb/target.h | 3 + - gdb-11.1/gdb/testsuite/gdb.base/dump.exp | 4 + - gdb-11.1/gdb/testsuite/gdb.base/float.exp | 2 + - .../gdb/testsuite/gdb.trace/entry-values.exp | 2 + - gdb-11.1/gdb/testsuite/gdb.xml/tdesc-regs.exp | 5 + + gdb/Makefile.in | 13 + + gdb/arch/loongarch-linux-nat.c | 94 ++ + gdb/arch/loongarch-linux-nat.h | 35 + + gdb/arch/loongarch.c | 84 + + gdb/arch/loongarch.h | 37 + + gdb/configure.host | 3 + + gdb/configure.nat | 4 + + gdb/configure.tgt | 8 + + gdb/doc/gdb.texinfo | 10 + + gdb/features/Makefile | 10 + + gdb/features/loongarch/base32.c | 47 + + gdb/features/loongarch/base32.xml | 45 + + gdb/features/loongarch/base64.c | 47 + + gdb/features/loongarch/base64.xml | 45 + + gdb/features/loongarch/fpu32.c | 54 + + gdb/features/loongarch/fpu32.xml | 53 + + gdb/features/loongarch/fpu64.c | 62 + + gdb/features/loongarch/fpu64.xml | 58 + + gdb/features/loongarch/lasx.c | 80 + + gdb/features/loongarch/lasx.xml | 59 + + gdb/features/loongarch/lbt32.c | 19 + + gdb/features/loongarch/lbt32.xml | 17 + + gdb/features/loongarch/lbt64.c | 19 + + gdb/features/loongarch/lbt64.xml | 17 + + gdb/features/loongarch/lsx.c | 80 + + gdb/features/loongarch/lsx.xml | 59 + + gdb/loongarch-linux-nat.c | 876 ++++++++++ + gdb/loongarch-linux-tdep.c | 699 ++++++++ + gdb/loongarch-linux-tdep.h | 48 + + gdb/loongarch-tdep.c | 1925 ++++++++++++++++++++++ + gdb/loongarch-tdep.h | 60 + + gdb/nat/loongarch-linux-watch.c | 330 ++++ + gdb/nat/loongarch-linux-watch.h | 132 ++ + gdb/remote.c | 25 + + gdb/target.h | 3 + + gdb/testsuite/gdb.base/dump.exp | 4 + + gdb/testsuite/gdb.base/float.exp | 2 + + gdb/testsuite/gdb.trace/entry-values.exp | 2 + + gdb/testsuite/gdb.xml/tdesc-regs.exp | 5 + 39 files changed, 5170 insertions(+) - create mode 100644 gdb-11.1/gdb/arch/loongarch-linux-nat.c - create mode 100644 gdb-11.1/gdb/arch/loongarch-linux-nat.h - create mode 100644 gdb-11.1/gdb/arch/loongarch.c - create mode 100644 gdb-11.1/gdb/arch/loongarch.h - create mode 100644 gdb-11.1/gdb/features/loongarch/base32.c - create mode 100644 gdb-11.1/gdb/features/loongarch/base32.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/base64.c - create mode 100644 gdb-11.1/gdb/features/loongarch/base64.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/fpu32.c - create mode 100644 gdb-11.1/gdb/features/loongarch/fpu32.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/fpu64.c - create mode 100644 gdb-11.1/gdb/features/loongarch/fpu64.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/lasx.c - create mode 100644 gdb-11.1/gdb/features/loongarch/lasx.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/lbt32.c - create mode 100644 gdb-11.1/gdb/features/loongarch/lbt32.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/lbt64.c - create mode 100644 gdb-11.1/gdb/features/loongarch/lbt64.xml - create mode 100644 gdb-11.1/gdb/features/loongarch/lsx.c - create mode 100644 gdb-11.1/gdb/features/loongarch/lsx.xml - create mode 100644 gdb-11.1/gdb/loongarch-linux-nat.c - create mode 100644 gdb-11.1/gdb/loongarch-linux-tdep.c - create mode 100644 gdb-11.1/gdb/loongarch-linux-tdep.h - create mode 100644 gdb-11.1/gdb/loongarch-tdep.c - create mode 100644 gdb-11.1/gdb/loongarch-tdep.h - create mode 100644 gdb-11.1/gdb/nat/loongarch-linux-watch.c - create mode 100644 gdb-11.1/gdb/nat/loongarch-linux-watch.h + create mode 100644 gdb/arch/loongarch-linux-nat.c + create mode 100644 gdb/arch/loongarch-linux-nat.h + create mode 100644 gdb/arch/loongarch.c + create mode 100644 gdb/arch/loongarch.h + create mode 100644 gdb/features/loongarch/base32.c + create mode 100644 gdb/features/loongarch/base32.xml + create mode 100644 gdb/features/loongarch/base64.c + create mode 100644 gdb/features/loongarch/base64.xml + create mode 100644 gdb/features/loongarch/fpu32.c + create mode 100644 gdb/features/loongarch/fpu32.xml + create mode 100644 gdb/features/loongarch/fpu64.c + create mode 100644 gdb/features/loongarch/fpu64.xml + create mode 100644 gdb/features/loongarch/lasx.c + create mode 100644 gdb/features/loongarch/lasx.xml + create mode 100644 gdb/features/loongarch/lbt32.c + create mode 100644 gdb/features/loongarch/lbt32.xml + create mode 100644 gdb/features/loongarch/lbt64.c + create mode 100644 gdb/features/loongarch/lbt64.xml + create mode 100644 gdb/features/loongarch/lsx.c + create mode 100644 gdb/features/loongarch/lsx.xml + create mode 100644 gdb/loongarch-linux-nat.c + create mode 100644 gdb/loongarch-linux-tdep.c + create mode 100644 gdb/loongarch-linux-tdep.h + create mode 100644 gdb/loongarch-tdep.c + create mode 100644 gdb/loongarch-tdep.h + create mode 100644 gdb/nat/loongarch-linux-watch.c + create mode 100644 gdb/nat/loongarch-linux-watch.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b8729ed..c9cbc5d 100644 @@ -5646,5 +5646,5 @@ index 7402ba8..4b94747 100644 # If no core registers were specified, assume this target does not -- -2.20.1 +2.36.0 diff --git a/0004-gdbserver-Add-LoongArch-port-support.patch b/0004-gdbserver-Add-LoongArch-port-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ebbe3e99a16d13032ba9391af985fec497b5ceb --- /dev/null +++ b/0004-gdbserver-Add-LoongArch-port-support.patch @@ -0,0 +1,372 @@ +From 3eb5ddd01ebdcb1b05fb069bbf17bce0e07489d1 Mon Sep 17 00:00:00 2001 +From: Qing Zhang +Date: Thu, 2 Jun 2022 17:14:39 +0800 +Subject: [PATCH 4/5] gdbserver-Add LoongArch port support + +Signed-off-by: Qing Zhang +--- + gdb/arch/loongarch.c | 2 - + gdb/arch/loongarch.h | 2 - + gdbserver/Makefile.in | 2 + + gdbserver/configure.srv | 7 + + gdbserver/linux-loongarch-low.cc | 284 +++++++++++++++++++++++++++++++ + 5 files changed, 293 insertions(+), 4 deletions(-) + create mode 100644 gdbserver/linux-loongarch-low.cc + +diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c +index 007c638..34307f5 100644 +--- a/gdb/arch/loongarch.c ++++ b/gdb/arch/loongarch.c +@@ -19,8 +19,6 @@ + #include "gdbsupport/common-regcache.h" + #include "arch/loongarch.h" + +-const char *loongarch_expedite_regs[] = { "r3", "pc", NULL }; +- + unsigned int loongarch_debug = 0; + + #include <../features/loongarch/base32.c> +diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h +index 9d9f65b..dfe011f 100644 +--- a/gdb/arch/loongarch.h ++++ b/gdb/arch/loongarch.h +@@ -26,8 +26,6 @@ extern unsigned int loongarch_debug; + + struct target_desc; + +-extern const char *loongarch_expedite_regs[]; +- + extern struct target_desc *loongarch_get_base_target_description (int rlen); + + extern struct target_desc * +diff --git a/gdbserver/Makefile.in b/gdbserver/Makefile.in +index 12e9b27..ddd52ec 100644 +--- a/gdbserver/Makefile.in ++++ b/gdbserver/Makefile.in +@@ -192,6 +192,7 @@ SFILES = \ + $(srcdir)/linux-arc-low.cc \ + $(srcdir)/linux-arm-low.cc \ + $(srcdir)/linux-ia64-low.cc \ ++ $(srcdir)/linux-loongarch-low.cc \ + $(srcdir)/linux-low.cc \ + $(srcdir)/linux-m68k-low.cc \ + $(srcdir)/linux-mips-low.cc \ +@@ -226,6 +227,7 @@ SFILES = \ + $(srcdir)/../gdb/arch/arm.c \ + $(srcdir)/../gdb/arch/arm-get-next-pcs.c \ + $(srcdir)/../gdb/arch/arm-linux.c \ ++ $(srcdir)/../gdb/arch/loongarch.c \ + $(srcdir)/../gdb/arch/ppc-linux-common.c \ + $(srcdir)/../gdb/arch/riscv.c \ + $(srcdir)/../gdb/nat/aarch64-mte-linux-ptrace.c \ +diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv +index 971f537..136be26 100644 +--- a/gdbserver/configure.srv ++++ b/gdbserver/configure.srv +@@ -125,6 +125,13 @@ case "${gdbserver_host}" in + srv_tgtobj="$srv_linux_obj linux-ia64-low.o" + srv_linux_usrregs=yes + ;; ++ loongarch*-*-linux*) srv_tgtobj="arch/loongarch.o arch/loongarch-linux-nat.o" ++ srv_tgtobj="${srv_tgtobj} linux-loongarch-low.o" ++ srv_tgtobj="${srv_tgtobj} ${srv_linux_obj}" ++ srv_linux_regsets=yes ++ srv_linux_usrregs=yes ++ srv_linux_thread_db=yes ++ ;; + m68*-*-linux*) if test "$gdb_cv_m68k_is_coldfire" = yes; then + srv_regobj=reg-cf.o + else +diff --git a/gdbserver/linux-loongarch-low.cc b/gdbserver/linux-loongarch-low.cc +new file mode 100644 +index 0000000..cd8ad6e +--- /dev/null ++++ b/gdbserver/linux-loongarch-low.cc +@@ -0,0 +1,284 @@ ++/* GNU/Linux/LoongArch specific low level interface, for the remote server ++ for GDB. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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. If not, see . */ ++ ++#include "server.h" ++#include "linux-low.h" ++#include "tdesc.h" ++#include "elf/common.h" ++#include "arch/loongarch-linux-nat.h" ++ ++/* Linux target op definitions for the LoongArch architecture. */ ++ ++class loongarch_target : public linux_process_target ++{ ++public: ++ ++ const regs_info *get_regs_info () override; ++ ++ int breakpoint_kind_from_pc (CORE_ADDR *pcptr) override; ++ ++ const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override; ++ ++protected: ++ ++ void low_arch_setup () override; ++ ++ bool low_cannot_fetch_register (int regno) override; ++ ++ bool low_cannot_store_register (int regno) override; ++ ++ bool low_fetch_register (regcache *regcache, int regno) override; ++ ++ bool low_supports_breakpoints () override; ++ ++ CORE_ADDR low_get_pc (regcache *regcache) override; ++ ++ void low_set_pc (regcache *regcache, CORE_ADDR newpc) override; ++ ++ bool low_breakpoint_at (CORE_ADDR pc) override; ++}; ++ ++/* The singleton target ops object. */ ++ ++static loongarch_target the_loongarch_target; ++ ++bool ++loongarch_target::low_cannot_fetch_register (int regno) ++{ ++ gdb_assert_not_reached ("linux target op low_cannot_fetch_register " ++ "is not implemented by the target"); ++} ++ ++bool ++loongarch_target::low_cannot_store_register (int regno) ++{ ++ gdb_assert_not_reached ("linux target op low_cannot_store_register " ++ "is not implemented by the target"); ++} ++ ++/* Implementation of linux target ops method "low_arch_setup". */ ++ ++void ++loongarch_target::low_arch_setup () ++{ ++ static const char *expedite_regs[] = { "r3", "pc", NULL }; ++ int pid = lwpid_of (current_thread); ++ struct target_desc *tdesc = loongarch_linux_read_description_runtime (pid); ++ ++ if (!tdesc->expedite_regs) ++ init_target_desc (tdesc, expedite_regs); ++ current_process ()->tdesc = tdesc; ++} ++ ++/* Collect GPRs from REGCACHE into BUF. */ ++ ++static void ++loongarch_fill_gregset (struct regcache *regcache, void *buf) ++{ ++ const struct target_desc *tdesc = regcache->tdesc; ++ elf_gregset_t *regset = (elf_gregset_t *) buf; ++ int regno = find_regno (tdesc, "r0"); ++ int i; ++ ++ for (i = 1; i < 32; i++) ++ collect_register (regcache, regno + i, *regset + i); ++ collect_register_by_name (regcache, "orig_a0", *regset + 32); ++ collect_register_by_name (regcache, "pc", *regset + 33); ++ collect_register_by_name (regcache, "badv", *regset + 34); ++} ++ ++/* Supply GPRs from BUF into REGCACHE. */ ++ ++static void ++loongarch_store_gregset (struct regcache *regcache, const void *buf) ++{ ++ const struct target_desc *tdesc = regcache->tdesc; ++ const elf_gregset_t *regset = (const elf_gregset_t *) buf; ++ int regno = find_regno (tdesc, "r0"); ++ int i; ++ ++ supply_register_zeroed (regcache, regno); ++ for (i = 1; i < 32; i++) ++ supply_register (regcache, regno + i, *regset + i); ++ supply_register_by_name (regcache, "orig_a0", *regset + 32); ++ supply_register_by_name (regcache, "pc", *regset + 33); ++ supply_register_by_name (regcache, "badv", *regset + 34); ++} ++ ++/* Collect FPRs from REGCACHE into BUF. */ ++ ++static void ++loongarch_fill_fpregset (struct regcache *regcache, void *buf) ++{ ++ const struct target_desc *tdesc = regcache->tdesc; ++ int f = find_regno (tdesc, "f0"); ++ int fcc = find_regno (tdesc, "fcc0"); ++ int flen = register_size (regcache->tdesc, f); ++ gdb_byte *regbuf = (gdb_byte *) buf; ++ int i; ++ ++ for (i = 0; i < ELF_NFPREG - 2; i++, regbuf += flen) ++ collect_register (regcache, f + i, regbuf); ++ for (i = 0; i < 8; i++) ++ collect_register (regcache, fcc + i, regbuf++); ++ collect_register_by_name (regcache, "fcsr", regbuf); ++} ++ ++/* Supply FPRs from BUF into REGCACHE. */ ++ ++static void ++loongarch_store_fpregset (struct regcache *regcache, const void *buf) ++{ ++ const struct target_desc *tdesc = regcache->tdesc; ++ int f = find_regno (tdesc, "f0"); ++ int fcc = find_regno (tdesc, "fcc0"); ++ int flen = register_size (regcache->tdesc, f); ++ const gdb_byte *regbuf = (const gdb_byte *) buf; ++ int i; ++ ++ for (i = 0; i < ELF_NFPREG - 2; i++, regbuf += flen) ++ supply_register (regcache, f + i, regbuf); ++ for (i = 0; i < 8; i++) ++ supply_register (regcache, fcc + i, regbuf++); ++ supply_register_by_name (regcache, "fcsr", regbuf); ++} ++ ++/* LoongArch/Linux regsets. */ ++static struct regset_info loongarch_regsets[] = { ++ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t), ++ GENERAL_REGS, loongarch_fill_gregset, loongarch_store_gregset }, ++ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof (elf_fpregset_t), ++ FP_REGS, loongarch_fill_fpregset, loongarch_store_fpregset }, ++ NULL_REGSET ++}; ++ ++/* LoongArch/Linux regset information. */ ++static struct regsets_info loongarch_regsets_info = ++ { ++ loongarch_regsets, /* regsets */ ++ 0, /* num_regsets */ ++ NULL, /* disabled_regsets */ ++ }; ++ ++/* Definition of linux_target_ops data member "regs_info". */ ++static struct regs_info loongarch_regs = ++ { ++ NULL, /* regset_bitmap */ ++ NULL, /* usrregs */ ++ &loongarch_regsets_info, ++ }; ++ ++/* Implementation of linux target ops method "get_regs_info". */ ++ ++const regs_info * ++loongarch_target::get_regs_info () ++{ ++ return &loongarch_regs; ++} ++ ++/* Implementation of linux target ops method "low_fetch_register". */ ++ ++bool ++loongarch_target::low_fetch_register (regcache *regcache, int regno) ++{ ++ const struct target_desc *tdesc = regcache->tdesc; ++ ++ if (regno != find_regno (tdesc, "r0")) ++ return false; ++ supply_register_zeroed (regcache, regno); ++ return true; ++} ++ ++bool ++loongarch_target::low_supports_breakpoints () ++{ ++ return true; ++} ++ ++/* Implementation of linux target ops method "low_get_pc". */ ++ ++CORE_ADDR ++loongarch_target::low_get_pc (regcache *regcache) ++{ ++ if (register_size (regcache->tdesc, 0) == 8) ++ return linux_get_pc_64bit (regcache); ++ else ++ return linux_get_pc_32bit (regcache); ++} ++ ++/* Implementation of linux target ops method "low_set_pc". */ ++ ++void ++loongarch_target::low_set_pc (regcache *regcache, CORE_ADDR newpc) ++{ ++ if (register_size (regcache->tdesc, 0) == 8) ++ linux_set_pc_64bit (regcache, newpc); ++ else ++ linux_set_pc_32bit (regcache, newpc); ++} ++ ++#define loongarch_breakpoint_len 4 ++ ++/* LoongArch BRK software debug mode instruction. ++ This instruction needs to match gdb/loongarch-tdep.c ++ (loongarch_default_breakpoint). */ ++static const gdb_byte loongarch_breakpoint[] = {0x05, 0x00, 0x2a, 0x00}; ++ ++/* Implementation of target ops method "breakpoint_kind_from_pc". */ ++ ++int ++loongarch_target::breakpoint_kind_from_pc (CORE_ADDR *pcptr) ++{ ++ return loongarch_breakpoint_len; ++} ++ ++/* Implementation of target ops method "sw_breakpoint_from_kind". */ ++ ++const gdb_byte * ++loongarch_target::sw_breakpoint_from_kind (int kind, int *size) ++{ ++ *size = loongarch_breakpoint_len; ++ return (const gdb_byte *) &loongarch_breakpoint; ++} ++ ++/* Implementation of linux target ops method "low_breakpoint_at". */ ++ ++bool ++loongarch_target::low_breakpoint_at (CORE_ADDR pc) ++{ ++ gdb_byte insn[loongarch_breakpoint_len]; ++ ++ read_memory (pc, (unsigned char *) &insn, loongarch_breakpoint_len); ++ if (memcmp (insn, loongarch_breakpoint, loongarch_breakpoint_len) == 0) ++ return true; ++ ++ return false; ++} ++ ++/* The linux target ops object. */ ++ ++linux_process_target *the_linux_target = &the_loongarch_target; ++ ++/* Initialize the LoongArch/Linux target. */ ++ ++void ++initialize_low_arch () ++{ ++ initialize_regsets_info (&loongarch_regsets_info); ++} +-- +2.36.0 + diff --git a/0005-gdb-Add-LoongArch-clfs-system.patch b/0005-gdb-Add-LoongArch-clfs-system.patch new file mode 100644 index 0000000000000000000000000000000000000000..cc8ad75549c327bb22565af8392793bac5c267e4 --- /dev/null +++ b/0005-gdb-Add-LoongArch-clfs-system.patch @@ -0,0 +1,423 @@ +From 42629b25d8c650e73f1e1afcc99802cc797ebddb Mon Sep 17 00:00:00 2001 +From: Qing Zhang +Date: Fri, 23 Sep 2022 14:04:19 +0800 +Subject: [PATCH 5/5] gdb-Add LoongArch clfs system + +Signed-off-by: Qing Zhang +--- + gdb/arch/loongarch-linux-nat.c | 15 ++++---- + gdb/arch/loongarch.c | 18 ++++------ + gdb/arch/loongarch.h | 4 +-- + gdb/features/loongarch/base32.c | 3 +- + gdb/features/loongarch/base32.xml | 3 +- + gdb/features/loongarch/base64.c | 3 +- + gdb/features/loongarch/base64.xml | 3 +- + gdb/loongarch-linux-nat.c | 10 +++--- + gdb/loongarch-linux-tdep.c | 58 ++++++++++++++++++------------- + gdb/loongarch-linux-tdep.h | 4 +-- + gdb/loongarch-tdep.c | 14 +++++--- + gdb/loongarch-tdep.h | 3 +- + 12 files changed, 76 insertions(+), 62 deletions(-) + +diff --git a/gdb/arch/loongarch-linux-nat.c b/gdb/arch/loongarch-linux-nat.c +index 70bf742..baf59f8 100644 +--- a/gdb/arch/loongarch-linux-nat.c ++++ b/gdb/arch/loongarch-linux-nat.c +@@ -43,23 +43,23 @@ loongarch_cpucfg_may_ptrace (uint64_t rj, int tid) + struct target_desc * + loongarch_linux_read_description_runtime (int tid) + { +- int rlen, fpu32, fpu64, lbt, lsx, lasx; ++ int rlen, flen, lbt, lsx, lasx; + + uint32_t cpucfg1 = loongarch_cpucfg_may_ptrace (1, tid); + rlen = cpucfg1 & 0x2 /* LA64 */ ? 64 : 32; + + uint32_t cpucfg2 = loongarch_cpucfg_may_ptrace (2, tid); +- fpu32 = 0, fpu64 = 0; ++ flen = 0; + if (cpucfg2 & 0x4 /* FP_DP */) +- fpu64 = 1; ++ flen = 64; + else if (cpucfg2 & 0x2 /* FP_SP */) +- fpu32 = 1; +- if (fpu32 || fpu64) ++ flen = 32; ++ if (flen) + { + loongarch_elf_fpregset_t regset; + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) < 0) +- fpu32 = 0, fpu64 = 0; ++ flen = 0; + } + + lbt = 0; +@@ -89,6 +89,5 @@ loongarch_linux_read_description_runtime (int tid) + lasx = 1; + } + +- return loongarch_create_target_description (rlen, fpu32, fpu64, lbt, lsx, +- lasx); ++ return loongarch_create_target_description (rlen, flen, lbt, lsx, lasx); + } +diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c +index 34307f5..9eab0aa 100644 +--- a/gdb/arch/loongarch.c ++++ b/gdb/arch/loongarch.c +@@ -31,7 +31,7 @@ unsigned int loongarch_debug = 0; + #include <../features/loongarch/lasx.c> + + target_desc * +-loongarch_create_target_description (int rlen, int fpu32, int fpu64, int lbt, ++loongarch_create_target_description (int rlen, int flen, int lbt, + int lsx, int lasx) + { + gdb_assert (rlen == 32 || rlen == 64); +@@ -50,10 +50,10 @@ loongarch_create_target_description (int rlen, int fpu32, int fpu64, int lbt, + else + gdb_assert_not_reached ("rlen unknown"); + +- if (fpu32) +- regnum = create_feature_loongarch_fpu32 (tdesc.get (), regnum); +- else if (fpu64) ++ if (flen == 64) + regnum = create_feature_loongarch_fpu64 (tdesc.get (), regnum); ++ else if (flen == 32) ++ regnum = create_feature_loongarch_fpu32 (tdesc.get (), regnum); + + if (lbt && rlen == 32) + regnum = create_feature_loongarch_lbt32 (tdesc.get (), regnum); +@@ -70,13 +70,7 @@ loongarch_create_target_description (int rlen, int fpu32, int fpu64, int lbt, + } + + target_desc * +-loongarch_get_base_target_description (int rlen) ++loongarch_get_base_target_description (int rlen, int flen) + { +- if (rlen == 64) +- return loongarch_create_target_description (64, 0, 0, 0, 0, 0); +- else if (rlen == 32) +- return loongarch_create_target_description (32, 0, 0, 0, 0, 0); +- else +- gdb_assert_not_reached ("rlen unknown"); +- return NULL; ++ return loongarch_create_target_description (rlen, flen, 0, 0, 0); + } +diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h +index dfe011f..997afab 100644 +--- a/gdb/arch/loongarch.h ++++ b/gdb/arch/loongarch.h +@@ -26,10 +26,10 @@ extern unsigned int loongarch_debug; + + struct target_desc; + +-extern struct target_desc *loongarch_get_base_target_description (int rlen); ++extern struct target_desc *loongarch_get_base_target_description (int rlen, int flen); + + extern struct target_desc * +-loongarch_create_target_description (int rlen, int fpu32, int fpu64, int lbt, ++loongarch_create_target_description (int rlen, int flen, int lbt, + int lsx, int lasx); + + #endif +diff --git a/gdb/features/loongarch/base32.c b/gdb/features/loongarch/base32.c +index b6f2d06..3fb35ef 100644 +--- a/gdb/features/loongarch/base32.c ++++ b/gdb/features/loongarch/base32.c +@@ -41,7 +41,8 @@ create_feature_loongarch_base32 (struct target_desc *result, long regnum) + tdesc_create_reg (feature, "r29", regnum++, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r30", regnum++, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "r31", regnum++, 1, "general", 32, "uint32"); ++ tdesc_create_reg (feature, "orig_a0", regnum++, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "pc", regnum++, 1, "general", 32, "code_ptr"); +- tdesc_create_reg (feature, "badvaddr", regnum++, 1, "general", 32, "code_ptr"); ++ tdesc_create_reg (feature, "badv", regnum++, 1, "general", 32, "code_ptr"); + return regnum; + } +diff --git a/gdb/features/loongarch/base32.xml b/gdb/features/loongarch/base32.xml +index 0afe81b..4c44dbe 100644 +--- a/gdb/features/loongarch/base32.xml ++++ b/gdb/features/loongarch/base32.xml +@@ -40,6 +40,7 @@ + + + ++ + +- ++ + +diff --git a/gdb/features/loongarch/base64.c b/gdb/features/loongarch/base64.c +index 3ee2d9a..d84d425 100644 +--- a/gdb/features/loongarch/base64.c ++++ b/gdb/features/loongarch/base64.c +@@ -41,7 +41,8 @@ create_feature_loongarch_base64 (struct target_desc *result, long regnum) + tdesc_create_reg (feature, "r29", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r30", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "r31", regnum++, 1, "general", 64, "uint64"); ++ tdesc_create_reg (feature, "orig_a0", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "pc", regnum++, 1, "general", 64, "code_ptr"); +- tdesc_create_reg (feature, "badvaddr", regnum++, 1, "general", 64, "code_ptr"); ++ tdesc_create_reg (feature, "badv", regnum++, 1, "general", 64, "code_ptr"); + return regnum; + } +diff --git a/gdb/features/loongarch/base64.xml b/gdb/features/loongarch/base64.xml +index b53479f..05d766e 100644 +--- a/gdb/features/loongarch/base64.xml ++++ b/gdb/features/loongarch/base64.xml +@@ -40,6 +40,7 @@ + + + ++ + +- ++ + +diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c +index f31eff4..e79b660 100644 +--- a/gdb/loongarch-linux-nat.c ++++ b/gdb/loongarch-linux-nat.c +@@ -89,7 +89,7 @@ loongarch_linux_nat_target::read_description () + return loongarch_linux_read_description_runtime (inferior_ptid.pid ()); + } + +-/* Fill GDB's register array with the general-purpose, pc and badvaddr ++/* Fill GDB's register array with the general-purpose, orig_a0, pc and badv + register values from the current thread. */ + + static void +@@ -99,7 +99,8 @@ fetch_gregs_from_thread (struct regcache *regcache, int regno, pid_t tid) + loongarch_elf_gregset_t regset; + + if ((regno == -1) || (regs->r <= regno && regno < regs->r + 32) || +- (regs->pc == regno) || (regs->badvaddr == regno)) ++ (regs->orig_a0 == regno) || (regs->pc == regno) || ++ (regs->badv == regno)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + +@@ -111,7 +112,7 @@ fetch_gregs_from_thread (struct regcache *regcache, int regno, pid_t tid) + } + } + +-/* Store to the current thread the valid general-purpose, pc and badvaddr ++/* Store to the current thread the valid general-purpose, orig_a0, pc and badv + register values in the GDB's register array. */ + + static void +@@ -121,7 +122,8 @@ store_gregs_to_thread (struct regcache *regcache, int regno, pid_t tid) + loongarch_elf_gregset_t regset; + + if ((regno == -1) || (regs->r <= regno && regno < regs->r + 32) || +- (regs->pc == regno) || (regs->badvaddr == regno)) ++ (regs->orig_a0 == regno) || (regs->pc == regno) || ++ (regs->badv == regno)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + +diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c +index 1145d9e..7b4b9fa 100644 +--- a/gdb/loongarch-linux-tdep.c ++++ b/gdb/loongarch-linux-tdep.c +@@ -63,19 +63,24 @@ loongarch_supply_elf_gregset (const struct regset *r, + regcache->raw_supply (regs->r + i, (const void *)buf); + } + ++ /* Size base (orig_a0) = regsize * regs->orig_a0. */ ++ buf = (const gdb_byte*)gprs + regsize * regs->orig_a0; ++ regcache->raw_supply (regs->orig_a0, (const void *)buf); ++ + /* Size base (pc) = regsize * regs->pc. */ + buf = (const gdb_byte*)gprs + regsize * regs->pc; + regcache->raw_supply (regs->pc, (const void *)buf); + +- /* Size base (badvaddr) = regsize * regs->badvaddr. */ +- buf = (const gdb_byte*)gprs + regsize * regs->badvaddr; +- regcache->raw_supply (regs->badvaddr, (const void *)buf); ++ /* Size base (badv) = regsize * regs->badv. */ ++ buf = (const gdb_byte*)gprs + regsize * regs->badv; ++ regcache->raw_supply (regs->badv, (const void *)buf); + } + else if (regs->r == regno) + regcache->raw_supply_zeroed (regno); + else if ((regs->r < regno && regno < regs->r + 32) ++ || (regs->orig_a0 == regno) + || (regs->pc == regno) +- || (regs->badvaddr == regno)) ++ || (regs->badv == regno)) + { + /* Offset offset (regno) = regsize * (regno - regs->r). */ + buf = (const gdb_byte*)gprs + regsize * (regno - regs->r); +@@ -101,17 +106,22 @@ loongarch_fill_elf_gregset (const struct regset *r, + regcache->raw_collect (regs->r + i, (void *)buf); + } + ++ /* Size base (orig_a0) = regsize * regs->orig_a0. */ ++ buf = (gdb_byte *)gprs + regsize * regs->orig_a0; ++ regcache->raw_collect (regs->orig_a0, (void *)buf); ++ + /* Size base (pc) = regsize * regs->pc. */ + buf = (gdb_byte *)gprs + regsize * regs->pc; + regcache->raw_collect (regs->pc, (void *)buf); + +- /* Size base (badvaddr) = regsize * regs->badvaddr. */ +- buf = (gdb_byte *)gprs + regsize * regs->badvaddr; +- regcache->raw_collect (regs->badvaddr, (void *)buf); ++ /* Size base (badv) = regsize * regs->badv. */ ++ buf = (gdb_byte *)gprs + regsize * regs->badv; ++ regcache->raw_collect (regs->badv, (void *)buf); + } + else if ((regs->r <= regno && regno < regs->r + 32) ++ ||(regs->orig_a0 == regno) + ||(regs->pc == regno) +- ||(regs->badvaddr == regno)) ++ ||(regs->badv == regno)) + { + /* Offset offset (regno) = regsize * (regno - regs->r). */ + buf = (gdb_byte *)gprs + regsize * (regno - regs->r); +@@ -541,42 +551,42 @@ static const struct target_desc * + loongarch_linux_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, bfd *abfd) + { +- int rlen, fpu32, fpu64, lbt, lsx, lasx; ++ int rlen, flen, fpu64, lbt, lsx, lasx; + + rlen = 64; +- fpu32 = 0; + + fpu64 = !!bfd_get_section_by_name (abfd, ".reg2"); + lbt = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lbt"); + lsx = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lsx"); + lasx = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lasx"); + +- return loongarch_create_target_description (rlen, fpu32, fpu64, lbt, lsx, +- lasx); ++ if (fpu64) ++ flen = 64; ++ else ++ flen = 0; ++ ++ return loongarch_create_target_description (rlen, flen, lbt, lsx, lasx); + } + + /* The RT signal frames look like this: + struct rt_sigframe { +- u32 rs_ass[4]; +- u32 rs_pad[2]; + struct siginfo rs_info; +- struct ucontext rs_uc; ++ struct ucontext rs_uctx; + }; + + struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; +- struct sigcontext uc_mcontext; + sigset_t uc_sigmask; +- unsigned long long uc_extcontext[0]; +- }; */ +- +-#define RTSIGFRAME_SIGINFO_SIZE 136 +-#define RTSIGFRAME_SIGINFO_OFFSET (6 * 4) +-#define UCONTEXT_SIGCONTEXT_OFFSET 64 +-#define RTSIGFRAME_SIGCONTEXT_OFFSET (RTSIGFRAME_SIGINFO_OFFSET \ +- + RTSIGFRAME_SIGINFO_SIZE \ ++ _u8 __unused[1024 / 8 - sizeof(sigset_t)]; ++ struct sigcontext uc_mcontext; ++ }; ++}; */ ++ ++#define RTSIGFRAME_SIGINFO_SIZE 128 ++#define UCONTEXT_SIGCONTEXT_OFFSET 176 ++#define RTSIGFRAME_SIGCONTEXT_OFFSET (RTSIGFRAME_SIGINFO_SIZE \ + + UCONTEXT_SIGCONTEXT_OFFSET) + + static void +diff --git a/gdb/loongarch-linux-tdep.h b/gdb/loongarch-linux-tdep.h +index e3456a8..bb70043 100644 +--- a/gdb/loongarch-linux-tdep.h ++++ b/gdb/loongarch-linux-tdep.h +@@ -26,10 +26,10 @@ + #define ELF_NGREG 45 + #define ELF_NFPREG 34 + +-typedef uint64_t loongarch_elf_gregset_t[ELF_NGREG]; ++typedef unsigned long loongarch_elf_gregset_t[ELF_NGREG]; + extern const struct regset loongarch_elf_gregset; + +-typedef uint64_t loongarch_elf_fpregset_t[ELF_NFPREG]; ++typedef double loongarch_elf_fpregset_t[ELF_NFPREG]; + extern const struct regset loongarch_elf_fpregset; + + /* Regset variable size. */ +diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c +index 87331bd..d306bbc 100644 +--- a/gdb/loongarch-tdep.c ++++ b/gdb/loongarch-tdep.c +@@ -1383,7 +1383,8 @@ loongarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + return 1; + + if (group == general_reggroup +- && (regs->pc == regnum || regs->badvaddr == regnum ++ && (regs->orig_a0 == regnum || regs->pc == regnum ++ || regs->badv == regnum + || (regs->r <= regnum && regnum < regs->r + 32))) + return 1; + +@@ -1561,8 +1562,8 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + memset (tdep, 0, sizeof (*tdep)); + memset (&tdep->regs, -1, sizeof (tdep->regs)); + +- /* If abfd is nullptr then a EF_LOONGARCH_ABI_LP64 is returned in +- its default state. */ ++ /* If abfd is nullptr then a EF_LOONGARCH_ABI_LP64 | EF_LOONGARCH_FLOAT_ABI_DOUBLE ++ is returned in its default state. */ + if (info.abfd != NULL + && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) + { +@@ -1587,7 +1588,8 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + /* Check any target description for validity. */ + if (!tdesc_has_registers (tdesc)) + tdesc = loongarch_get_base_target_description ( +- EF_LOONGARCH_IS_ILP32 (tdep->ef_abi) ? 32 : 64); ++ EF_LOONGARCH_IS_ILP32 (tdep->ef_abi) ? 32 : 64, ++ EF_LOONGARCH_IS_SINGLE_FLOAT (tdep->ef_abi) ? 32 : 64); + + int valid_p = 1; + const struct tdesc_feature *feature; +@@ -1602,11 +1604,13 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) + for (i = 0; i < 32; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), regnum++, + loongarch_r_normal_name[i] + 1); ++ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), ++ tdep->regs.orig_a0 = regnum++, "orig_a0"); + valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), + tdep->regs.pc = regnum++, "pc"); + valid_p + &= tdesc_numbered_register (feature, tdesc_data.get (), +- tdep->regs.badvaddr = regnum++, "badvaddr"); ++ tdep->regs.badv = regnum++, "badv"); + + if ((feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.fpu"))) + { +diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h +index c673c9e..12bc78e 100644 +--- a/gdb/loongarch-tdep.h ++++ b/gdb/loongarch-tdep.h +@@ -37,8 +37,9 @@ struct gdbarch_tdep + int r; + int ra; + int sp; ++ int orig_a0; + int pc; +- int badvaddr; ++ int badv; + + int f; + int fcc; +-- +2.36.0 + diff --git a/gdb.spec b/gdb.spec index 2769b1b79c886af9498bd28440a4afd9e0eac310..9f525439de4f63931837016c7cf0f333688664cb 100644 --- a/gdb.spec +++ b/gdb.spec @@ -1,6 +1,6 @@ Name: gdb Version: 11.1 -Release: 3 +Release: 5 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL-1.3 Source: ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.xz @@ -99,6 +99,8 @@ Patch82: 0001-Make-c-exp.y-work-with-Bison-3.8.patch Patch83: 0001-gdb-Add-LoongArch-bfd-support.patch Patch84: 0002-gdb-Add-LoongArch-opcodes-support.patch Patch85: 0003-gdb-Add-LoongArch-gdb-support.patch +Patch86: 0004-gdbserver-Add-LoongArch-port-support.patch +Patch87: 0005-gdb-Add-LoongArch-clfs-system.patch %endif %global gdb_src gdb-%{version} @@ -371,6 +373,12 @@ rm -f $RPM_BUILD_ROOT%{_datadir}/gdb/python/gdb/command/backtrace.py %{_infodir}/gdb.info* %changelog +* Tue Sep 23 2022 Qing Zhang - 11.1-5 +- add loongarch clfs support + +* Tue Sep 23 2022 Qing Zhang - 11.1-4 +- revert loongarch support + * Thu Jun 02 2022 xu_ping - 11.1-3 - modify the patch for loongarch64