* [PATCH v2 0/6] Add new relocations for LoongArch.
@ 2022-07-21 1:37 liuzhensong
2022-07-21 1:37 ` [PATCH v2 1/6] bfd: Add supported for LoongArch new relocations liuzhensong
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
This is the v2 version of patches to support new relocations for LoongArch.
The new reloc types docnments are on:
https://github.com/loongson/LoongArch-Documentation/pull/57/files
The testsuite status:
=== binutils Summary ===
# of expected passes 241
# of unsupported tests 6
=== gas Summary ===
# of expected passes 270
# of unsupported tests 7
=== ld Summary ===
# of expected passes 1457
# of expected failures 11
# of untested testcases 1
# of unsupported tests 154
The patch set changelog:
v1 -> v2
1. Rename some relocations.
2. Fix bug caused by a pointer point to global ifunc.
3. Fix bug in relocation R_LARCH_SOP_PUSH_GPREL.
3. Change some comments.
4. Add testcases.
liuzhensong (6):
bfd: Add supported for LoongArch new relocations.
LoongArch:opcodes: Add new reloc types.
LoongArch: gas: Add new reloc types.
LoongArch: Move ifunc info to rela.dyn from rela.plt.
bfd: Delete R_LARCH_NONE from dyn info of LoongArch.
LoongArch: Add testcases for new relocate types.
bfd/bfd-in2.h | 37 +
bfd/elfnn-loongarch.c | 1554 ++++++++++++-----
bfd/elfxx-loongarch.c | 1371 +++++++++++----
bfd/elfxx-loongarch.h | 4 +
bfd/libbfd.h | 37 +
bfd/reloc.c | 82 +
binutils/readelf.c | 2 +
gas/config/loongarch-lex.h | 3 +
gas/config/loongarch-parse.y | 72 +-
gas/config/tc-loongarch.c | 140 +-
gas/config/tc-loongarch.h | 7 +-
gas/testsuite/gas/all/gas.exp | 4 +-
gas/testsuite/gas/loongarch/jmp_op.d | 82 +-
gas/testsuite/gas/loongarch/jmp_op.s | 38 +-
gas/testsuite/gas/loongarch/macro_op.d | 778 +--------
gas/testsuite/gas/loongarch/macro_op.s | 44 +-
gas/testsuite/gas/loongarch/macro_op_32.d | 55 +
gas/testsuite/gas/loongarch/macro_op_32.s | 16 +
.../gas/loongarch/macro_op_large_abs.d | 77 +
.../gas/loongarch/macro_op_large_abs.s | 9 +
.../gas/loongarch/macro_op_large_pc.d | 77 +
.../gas/loongarch/macro_op_large_pc.s | 9 +
gas/testsuite/gas/loongarch/reloc.d | 167 ++
gas/testsuite/gas/loongarch/reloc.s | 144 ++
include/elf/loongarch.h | 139 ++
ld/testsuite/ld-elf/eh5.d | 2 +-
ld/testsuite/ld-elf/pr26936.d | 2 +-
ld/testsuite/ld-elf/shared.exp | 6 +-
ld/testsuite/ld-loongarch-elf/attr-ifunc-4.c | 23 +
.../ld-loongarch-elf/attr-ifunc-4.out | 1 +
ld/testsuite/ld-loongarch-elf/disas-jirl-32.d | 18 +-
ld/testsuite/ld-loongarch-elf/disas-jirl.d | 19 +-
ld/testsuite/ld-loongarch-elf/ifunc.exp | 34 +
ld/testsuite/ld-loongarch-elf/jmp_op.d | 84 +-
ld/testsuite/ld-loongarch-elf/jmp_op.s | 42 +-
.../ld-loongarch-elf/libnopic-global.s | 113 ++
ld/testsuite/ld-loongarch-elf/macro_op.d | 883 ++--------
ld/testsuite/ld-loongarch-elf/macro_op.s | 57 +-
ld/testsuite/ld-loongarch-elf/macro_op_32.d | 768 +-------
ld/testsuite/ld-loongarch-elf/macro_op_32.s | 43 +-
.../ld-loongarch-elf/nopic-global-so.rd | 5 +
.../ld-loongarch-elf/nopic-global-so.sd | 10 +
.../ld-loongarch-elf/nopic-global.out | 1 +
ld/testsuite/ld-loongarch-elf/nopic-global.s | 373 ++++
ld/testsuite/ld-loongarch-elf/nopic-global.sd | 5 +
ld/testsuite/ld-loongarch-elf/nopic-global.xd | 3 +
ld/testsuite/ld-loongarch-elf/nopic-local.out | 1 +
ld/testsuite/ld-loongarch-elf/nopic-local.rd | 0
ld/testsuite/ld-loongarch-elf/nopic-local.s | 383 ++++
ld/testsuite/ld-loongarch-elf/nopic-local.sd | 5 +
ld/testsuite/ld-loongarch-elf/nopic-local.xd | 3 +
.../ld-loongarch-elf/nopic-weak-global-so.rd | 5 +
.../ld-loongarch-elf/nopic-weak-global-so.sd | 10 +
.../ld-loongarch-elf/nopic-weak-global.out | 1 +
.../ld-loongarch-elf/nopic-weak-global.s | 374 ++++
.../ld-loongarch-elf/nopic-weak-global.sd | 5 +
.../ld-loongarch-elf/nopic-weak-global.xd | 3 +
.../ld-loongarch-elf/nopic-weak-local.out | 1 +
.../ld-loongarch-elf/nopic-weak-local.rd | 0
.../ld-loongarch-elf/nopic-weak-local.s | 383 ++++
.../ld-loongarch-elf/nopic-weak-local.sd | 5 +
.../ld-loongarch-elf/nopic-weak-local.xd | 3 +
ld/testsuite/ld-loongarch-elf/pic.exp | 202 +++
ld/testsuite/ld-loongarch-elf/pic.ld | 18 +
opcodes/loongarch-opc.c | 412 +++--
65 files changed, 5773 insertions(+), 3481 deletions(-)
create mode 100644 gas/testsuite/gas/loongarch/macro_op_32.d
create mode 100644 gas/testsuite/gas/loongarch/macro_op_32.s
create mode 100644 gas/testsuite/gas/loongarch/macro_op_large_abs.d
create mode 100644 gas/testsuite/gas/loongarch/macro_op_large_abs.s
create mode 100644 gas/testsuite/gas/loongarch/macro_op_large_pc.d
create mode 100644 gas/testsuite/gas/loongarch/macro_op_large_pc.s
create mode 100644 gas/testsuite/gas/loongarch/reloc.d
create mode 100644 gas/testsuite/gas/loongarch/reloc.s
create mode 100644 ld/testsuite/ld-loongarch-elf/attr-ifunc-4.c
create mode 100644 ld/testsuite/ld-loongarch-elf/attr-ifunc-4.out
create mode 100644 ld/testsuite/ld-loongarch-elf/ifunc.exp
create mode 100644 ld/testsuite/ld-loongarch-elf/libnopic-global.s
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global-so.rd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global-so.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global.out
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global.s
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-global.xd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-local.out
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-local.rd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-local.s
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-local.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-local.xd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global-so.rd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global-so.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global.out
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global.s
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-global.xd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-local.out
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-local.rd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-local.s
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-local.sd
create mode 100644 ld/testsuite/ld-loongarch-elf/nopic-weak-local.xd
create mode 100644 ld/testsuite/ld-loongarch-elf/pic.exp
create mode 100644 ld/testsuite/ld-loongarch-elf/pic.ld
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/6] bfd: Add supported for LoongArch new relocations.
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
@ 2022-07-21 1:37 ` liuzhensong
2022-07-21 1:37 ` [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types liuzhensong
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
Define new reloc types according to linker needs.
include/elf/
loongarch.h
bfd/
bfd-in2.h
libbfd.h
reloc.c
elfnn-loongarch.c
elfxx-loongarch.c
elfxx-loongarch.h
---
bfd/bfd-in2.h | 36 ++
bfd/elfnn-loongarch.c | 1202 +++++++++++++++++++++-------------
bfd/elfxx-loongarch.c | 1354 +++++++++++++++++++++++++++++----------
bfd/elfxx-loongarch.h | 4 +
bfd/libbfd.h | 36 ++
bfd/reloc.c | 79 +++
include/elf/loongarch.h | 136 ++++
7 files changed, 2095 insertions(+), 752 deletions(-)
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 4e1182e93d4..91e6ad76b9a 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6274,6 +6274,42 @@ assembler and not (currently) written to any object files. */
BFD_RELOC_LARCH_SUB24,
BFD_RELOC_LARCH_SUB32,
BFD_RELOC_LARCH_SUB64,
+ BFD_RELOC_LARCH_B16,
+ BFD_RELOC_LARCH_B21,
+ BFD_RELOC_LARCH_B26,
+ BFD_RELOC_LARCH_ABS_HI20,
+ BFD_RELOC_LARCH_ABS_LO12,
+ BFD_RELOC_LARCH_ABS64_LO20,
+ BFD_RELOC_LARCH_ABS64_HI12,
+ BFD_RELOC_LARCH_PCALA_HI20,
+ BFD_RELOC_LARCH_PCALA_LO12,
+ BFD_RELOC_LARCH_PCALA64_LO20,
+ BFD_RELOC_LARCH_PCALA64_HI12,
+ BFD_RELOC_LARCH_GOT_PC_HI20,
+ BFD_RELOC_LARCH_GOT_PC_LO12,
+ BFD_RELOC_LARCH_GOT64_PC_LO20,
+ BFD_RELOC_LARCH_GOT64_PC_HI12,
+ BFD_RELOC_LARCH_GOT_HI20,
+ BFD_RELOC_LARCH_GOT_LO12,
+ BFD_RELOC_LARCH_GOT64_LO20,
+ BFD_RELOC_LARCH_GOT64_HI12,
+ BFD_RELOC_LARCH_TLS_LE_HI20,
+ BFD_RELOC_LARCH_TLS_LE_LO12,
+ BFD_RELOC_LARCH_TLS_LE64_LO20,
+ BFD_RELOC_LARCH_TLS_LE64_HI12,
+ BFD_RELOC_LARCH_TLS_IE_PC_HI20,
+ BFD_RELOC_LARCH_TLS_IE_PC_LO12,
+ BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
+ BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
+ BFD_RELOC_LARCH_TLS_IE_HI20,
+ BFD_RELOC_LARCH_TLS_IE_LO12,
+ BFD_RELOC_LARCH_TLS_IE64_LO20,
+ BFD_RELOC_LARCH_TLS_IE64_HI12,
+ BFD_RELOC_LARCH_TLS_LD_PC_HI20,
+ BFD_RELOC_LARCH_TLS_LD_HI20,
+ BFD_RELOC_LARCH_TLS_GD_PC_HI20,
+ BFD_RELOC_LARCH_TLS_GD_HI20,
+ BFD_RELOC_LARCH_RELAX,
BFD_RELOC_UNUSED };
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 5b44901b9e0..21710dcb3fb 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -122,14 +122,16 @@ struct loongarch_elf_link_hash_table
#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_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
/* Generate a PLT header. */
@@ -607,9 +609,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
struct elf_link_hash_entry *h;
Elf_Internal_Sym *isym = NULL;
- int need_dynreloc;
- int only_need_pcrel;
-
r_symndx = ELFNN_R_SYM (rel->r_info);
r_type = ELFNN_R_TYPE (rel->r_info);
@@ -622,7 +621,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (r_symndx < symtab_hdr->sh_info)
{
/* A local symbol. */
- isym = 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;
@@ -655,17 +654,20 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
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++;
@@ -674,17 +676,27 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
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,
@@ -692,6 +704,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
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. */
@@ -703,6 +717,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
return false;
break;
+ case R_LARCH_TLS_LE_HI20:
case R_LARCH_SOP_PUSH_TLS_TPREL:
if (!bfd_link_executable (info))
return false;
@@ -715,6 +730,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
return false;
break;
+ 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
@@ -726,16 +742,45 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
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:
@@ -762,6 +807,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_LARCH_JUMP_SLOT:
case R_LARCH_32:
case R_LARCH_64:
+
need_dynreloc = 1;
/* If resolved symbol is defined in this object,
@@ -774,9 +820,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
Thus, only under pde, it needs pcrel only. We discard it. */
only_need_pcrel = bfd_link_pde (info);
- if (h != NULL)
- h->non_got_ref = 1;
-
if (h != NULL
&& (!bfd_link_pic (info)
|| h->type == STT_GNU_IFUNC))
@@ -899,9 +942,7 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct loongarch_elf_link_hash_table *htab;
- struct loongarch_elf_link_hash_entry *eh;
bfd *dynobj;
- asection *s, *srel;
htab = loongarch_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -951,73 +992,9 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
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
@@ -1039,6 +1016,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
info = (struct bfd_link_info *) inf;
htab = loongarch_elf_hash_table (info);
+ bool dyn = htab->elf.dynamic_sections_created;
BFD_ASSERT (htab != NULL);
do
@@ -1052,9 +1030,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
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)
@@ -1090,7 +1071,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
location in the .plt. This is required to make function
pointers compare as equal between the normal executable and
the shared library. */
- if (!bfd_link_pic(info)
+ if (!bfd_link_pic (info)
&& !h->def_regular)
{
h->root.u.def.section = plt;
@@ -1107,51 +1088,68 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (0 < h->got.refcount)
{
asection *s;
- bool dyn;
int tls_type = 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);
}
}
@@ -1161,7 +1159,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
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;
@@ -1178,13 +1182,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
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)
@@ -1200,8 +1211,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
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
@@ -1223,14 +1233,14 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
/* 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)
+ 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);
+
return true;
}
@@ -1238,7 +1248,7 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
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;
@@ -1249,7 +1259,7 @@ elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf)
|| 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
@@ -1367,16 +1377,21 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
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;
@@ -1389,11 +1404,11 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
/* 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
@@ -1542,10 +1557,13 @@ loongarch_top (int64_t *val)
static void
loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
{
+ BFD_ASSERT (s && s->contents);
const struct elf_backend_data *bed;
bfd_byte *loc;
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);
}
@@ -1594,19 +1612,15 @@ loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
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:
@@ -1679,6 +1693,8 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
case R_LARCH_SOP_POP_32_S_10_12:
case R_LARCH_SOP_POP_32_S_10_16:
case R_LARCH_SOP_POP_32_S_10_16_S2:
+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
case R_LARCH_SOP_POP_32_S_5_20:
case R_LARCH_SOP_POP_32_U_10_12:
case R_LARCH_SOP_POP_32_U:
@@ -1694,67 +1710,6 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
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:
@@ -1792,6 +1747,55 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
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;
}
@@ -1900,7 +1904,6 @@ loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
"-- Record dump end --\n\n");
}
-
static bool
loongarch_reloc_is_fatal (struct bfd_link_info *info,
bfd *input_bfd,
@@ -1945,8 +1948,27 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
return fatal;
}
-
-
+#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,
@@ -1983,8 +2005,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bool is_ie, is_undefweak, unresolved_reloc, defined_local;
bool resolved_local, resolved_dynly, resolved_to_const;
char tls_type;
- bfd_vma relocation;
- bfd_vma off, ie_off;
+ bfd_vma relocation, off, ie_off;
int i, j;
howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
@@ -2018,9 +2039,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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
{
@@ -2092,7 +2116,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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;
@@ -2150,20 +2174,25 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
+ 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 (htab->elf.splt != NULL)
+ sreloc = htab->elf.srelplt;
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
@@ -2172,7 +2201,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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);
}
@@ -2341,12 +2372,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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;
@@ -2427,10 +2453,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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,
@@ -2441,8 +2466,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* 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)
{
@@ -2455,79 +2479,76 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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
@@ -2541,9 +2562,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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,
@@ -2555,9 +2576,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* The offset must always be a multiple of the word size.
So, we can use the least significant bit to record
whether we have already processed this entry. */
- if ((off & 1) != 0)
- off &= ~1;
- else
+ if (local_got_offsets[r_symndx] == 0)
{
if (is_pic)
{
@@ -2586,160 +2605,519 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
}
}
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)
{
- 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;
+ BFD_ASSERT (rel->r_addend == 0);
+ 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. */
+ {
+ 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) */)
+ rela.r_offset = sec_addr (got) + got_off + ie_off;
+ if (SYMBOL_REFERENCES_LOCAL (info, h))
{
- 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) */
- {
- /* 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);
- relocation = off + (is_ie ? ie_off : 0);
+ break;
+
+ case R_LARCH_TLS_IE_PC_LO12:
+ case R_LARCH_TLS_IE64_PC_LO20:
+ case R_LARCH_TLS_IE64_PC_HI12:
+ case R_LARCH_TLS_IE_LO12:
+ case R_LARCH_TLS_IE64_LO20:
+ case R_LARCH_TLS_IE64_HI12:
+ unresolved_reloc = 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);
+
+ break;
+
+ case R_LARCH_RELAX:
break;
default:
@@ -2759,7 +3137,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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)
@@ -2825,7 +3203,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
}
fatal = true;
- break;
}
return !fatal;
@@ -2889,27 +3266,15 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
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))
- {
- 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);
- }
- else
- {
- /* 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;
- }
-
+ /* 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);
@@ -2930,15 +3295,14 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
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);
@@ -2963,7 +3327,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
}
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;
@@ -2993,7 +3356,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
}
else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
{
- BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr. */);
asection *sec = 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
@@ -3001,7 +3363,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
}
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;
@@ -3010,24 +3371,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
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;
@@ -3337,7 +3680,6 @@ loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
#define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
#define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
-
static bool
loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 4424969e579..f059f1a0c05 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -35,27 +35,30 @@ typedef struct loongarch_reloc_howto_type_struct
reloc_howto_type howto;
bfd_reloc_code_real_type bfd_type;
bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
-}loongarch_reloc_howto_type;
+ const char *larch_reloc_type_name;
+} loongarch_reloc_howto_type;
#define LOONGARCH_DEFAULT_HOWTO(r_name) \
{ HOWTO (R_LARCH_##r_name, 0, 4, 32, false, 0, complain_overflow_signed, \
bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES, \
- false), BFD_RELOC_LARCH_##r_name, NULL }
+ false), BFD_RELOC_LARCH_##r_name, NULL, NULL }
#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. */
@@ -76,7 +79,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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). */
@@ -93,7 +97,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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). */
@@ -110,7 +115,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -126,7 +132,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -141,8 +148,9 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -157,8 +165,9 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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). */
@@ -175,7 +184,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -191,7 +201,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -207,7 +218,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -223,7 +235,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -239,7 +252,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -255,7 +269,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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 */
@@ -271,63 +286,67 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
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. */
- 0, /* size. */
- 0, /* bitsize. */
+ 0, /* rightshift. */
+ 0, /* size. */
+ 0, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_MARK_LA", /* name. */
- false, /* partial_inplace. */
+ false, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
false, /* pcrel_offset */
BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
- 0, /* rightshift. */
- 0, /* size. */
- 0, /* bitsize. */
+ 0, /* rightshift. */
+ 0, /* size. */
+ 0, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_MARK_PCREL", /* name. */
- false, /* partial_inplace. */
+ false, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
false, /* pcrel_offset */
BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
- 2, /* rightshift. */
- 4, /* size. */
- 32, /* bitsize. */
+ 2, /* rightshift. */
+ 4, /* size. */
+ 32, /* bitsize. */
true /* FIXME: somewhat use this. */, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_PUSH_PCREL", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_PUSH_PCREL", /* name. */
+ false, /* partial_inplace. */
0x03ffffff, /* src_mask. */
0x03ffffff, /* dst_mask. */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
/* type 23-37. */
LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
@@ -347,343 +366,984 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
- 0, /* rightshift. */
- 4, /* size. */
- 5, /* bitsize. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 5, /* bitsize. */
false, /* pc_relative. */
- 10, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_10_5", /* name. */
- false, /* partial_inplace. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_10_5", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x7c00, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
- 0, /* rightshift. */
- 4, /* size. */
- 12, /* bitsize. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
false, /* pc_relative. */
- 10, /* bitpos. */
- complain_overflow_unsigned, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_U_10_12", /* name. */
- false, /* partial_inplace. */
+ 10, /* bitpos. */
+ complain_overflow_unsigned, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_U_10_12", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x3ffc00, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
- 0, /* rightshift. */
- 4, /* size. */
- 12, /* bitsize. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
false, /* pc_relative. */
- 10, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_10_12", /* name. */
- false, /* partial_inplace. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_10_12", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x3ffc00, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
- 0, /* rightshift. */
- 4, /* size. */
- 16, /* bitsize. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 16, /* bitsize. */
false, /* pc_relative. */
- 10, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_10_16", /* name. */
- false, /* partial_inplace. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_10_16", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x3fffc00, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
2, /* rightshift. */
- 4, /* size. */
- 16, /* bitsize. */
+ 4, /* size. */
+ 16, /* bitsize. */
false, /* pc_relative. */
- 10, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
- false, /* partial_inplace. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x3fffc00, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits_b16, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
- 0, /* rightshift. */
- 4, /* size. */
- 20, /* bitsize. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
false, /* pc_relative. */
- 5, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_5_20", /* name. */
- false, /* partial_inplace. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_5_20", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0x1ffffe0, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
/* type (44). */
2, /* rightshift. */
4, /* size. */
- 21, /* bitsize. */
+ 21, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
+ false, /* partial_inplace. */
0xfc0003e0, /* src_mask */
0xfc0003e0, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
/* bfd_reloc_code_real_type */
- loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
+ reloc_bits_b21, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
- 2, /* rightshift. */
- 4, /* size. */
- 26, /* bitsize. */
- false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
- false, /* partial_inplace. */
- 0xfc000000, /* src_mask */
- 0xfc000000, /* dst_mask */
+ 2, /* rightshift. */
+ 4, /* size. */
+ 26, /* bitsize. */
+ false, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x03ffffff, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
/* bfd_reloc_code_real_type */
- loongarch_adjust_reloc_bits_l16_h10), /* adjust_reloc_bits */
+ reloc_bits_b26, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
- 0, /* rightshift. */
- 4, /* size. */
- 32, /* bitsize. */
- false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_unsigned, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SOP_POP_32_S_U", /* name. */
- false, /* partial_inplace. */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 32, /* bitsize. */
+ false, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_unsigned, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SOP_POP_32_S_U", /* name. */
+ false, /* partial_inplace. */
0xffffffff00000000, /* src_mask */
0x00000000ffffffff, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
- loongarch_gen_adjust_reloc_bits), /* adjust_reloc_bits */
+ reloc_bits, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
- 0, /* rightshift. */
- 4, /* size. */
- 8, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 8, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_ADD8", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ADD8", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
- 0, /* rightshift. */
- 4, /* size. */
- 16, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 16, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_ADD16", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ADD16", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
- 0, /* rightshift. */
- 4, /* size. */
- 24, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 24, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_ADD24", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ADD24", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
- 0, /* rightshift. */
- 4, /* size. */
- 32, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 32, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_ADD32", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ADD32", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
- 0, /* rightshift. */
- 8, /* size. */
- 64, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
+ 0, /* rightshift. */
+ 8, /* size. */
+ 64, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_ADD64", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ADD64", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
- 0, /* rightshift. */
- 4, /* size. */
- 8, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 8, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SUB8", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SUB8", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
- 0, /* rightshift. */
- 4, /* size. */
- 16, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 16, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SUB16", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SUB16", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
- 0, /* rightshift. */
- 4, /* size. */
- 24, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 24, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SUB24", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SUB24", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
- 0, /* rightshift. */
- 4, /* size. */
- 32, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 32, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SUB32", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SUB32", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
- 0, /* rightshift. */
- 8, /* size. */
- 64, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
+ 0, /* rightshift. */
+ 8, /* size. */
+ 64, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_SUB64", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_SUB64", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
ALL_ONES, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
- 0, /* rightshift. */
- 0, /* size. */
- 0, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
+ 0, /* rightshift. */
+ 0, /* size. */
+ 0, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
- bfd_elf_generic_reloc, /* special_function. */
- "R_LARCH_GNU_VTINHERIT", /* name. */
- false, /* partial_inplace. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GNU_VTINHERIT", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
- 0, /* rightshift. */
- 0, /* size. */
- 0, /* bitsize. */
+ LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
+ 0, /* rightshift. */
+ 0, /* size. */
+ 0, /* bitsize. */
false, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_signed, /* complain_on_overflow. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
NULL, /* special_function. */
- "R_LARCH_GNU_VTENTRY", /* name. */
- false, /* partial_inplace. */
+ "R_LARCH_GNU_VTENTRY", /* name. */
+ false, /* partial_inplace. */
0, /* src_mask */
0, /* dst_mask */
false, /* pcrel_offset */
BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
- NULL), /* adjust_reloc_bits */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
+
+ LOONGARCH_EMPTY_HOWTO (59),
+ LOONGARCH_EMPTY_HOWTO (60),
+ LOONGARCH_EMPTY_HOWTO (61),
+ LOONGARCH_EMPTY_HOWTO (62),
+ LOONGARCH_EMPTY_HOWTO (63),
+
+ /* New reloc types. */
+ LOONGARCH_HOWTO (R_LARCH_B16, /* type (64). */
+ 2, /* rightshift. */
+ 4, /* size. */
+ 16, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_B16", /* name. */
+ false, /* partial_inplace. */
+ 0x3fffc00, /* src_mask */
+ 0x3fffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_B16, /* bfd_reloc_code_real_type */
+ reloc_bits_b16, /* adjust_reloc_bits */
+ "b16"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_B21, /* type (65). */
+ 2, /* rightshift. */
+ 4, /* size. */
+ 21, /* bitsize. */
+ false, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_B21", /* name. */
+ false, /* partial_inplace. */
+ 0xfc0003e0, /* src_mask */
+ 0xfc0003e0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_B21, /* bfd_reloc_code_real_type */
+ reloc_bits_b21, /* adjust_reloc_bits */
+ "b21"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_B26, /* type (66). */
+ 2, /* rightshift. */
+ 4, /* size. */
+ 26, /* bitsize. */
+ false, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_B26", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x03ffffff, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_B26, /* bfd_reloc_code_real_type */
+ reloc_bits_b26, /* adjust_reloc_bits */
+ "b26"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_ABS_HI20, /* type (67). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ABS_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_ABS_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "abs_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_ABS_LO12, /* type (68). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_unsigned, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ABS_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_ABS_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "abs_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_ABS64_LO20, /* type (69). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ABS64_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_ABS64_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "abs64_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_ABS64_HI12, /* type (70). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_ABS64_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_ABS64_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "abs64_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_PCALA_HI20, /* type (71). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_PCALA_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_PCALA_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "pc_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_PCALA_LO12, /* type (72). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_PCALA_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_PCALA_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "pc_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20, /* type (73). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_PCALA64_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_PCALA64_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "pc64_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12, /* type (74). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_PCALA64_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_PCALA64_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "pc64_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20, /* type (75). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT_PC_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT_PC_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got_pc_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12, /* type (76). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT_PC_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT_PC_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got_pc_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20, /* type (77). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT64_PC_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT64_PC_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got64_pc_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12, /* type (78). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT64_PC_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got64_pc_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT64_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got64_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_GOT64_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "got64_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LE_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "le_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LE_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "le_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LE64_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "le64_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LE64_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "le64_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE_PC_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie_pc_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_unsigned, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE_PC_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie_pc_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE64_PC_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie64_pc_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE64_PC_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie64_pc_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE_LO12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie_lo12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */
+ 32, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE64_LO20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie64_lo20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */
+ 52, /* rightshift. */
+ 4, /* size. */
+ 12, /* bitsize. */
+ false, /* pc_relative. */
+ 10, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_IE64_HI12", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ie64_hi12"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LD_PC_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ld_pc_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_LD_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "ld_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_GD_PC_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "gd_pc_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */
+ 12, /* rightshift. */
+ 4, /* size. */
+ 20, /* bitsize. */
+ false, /* pc_relative. */
+ 5, /* bitpos. */
+ complain_overflow_signed, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_TLS_GD_HI20", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0x1ffffe0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */
+ reloc_bits, /* adjust_reloc_bits */
+ "gd_hi20"), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (99). */
+ 0, /* rightshift */
+ 1, /* size */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_LARCH_RELAX", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
+
};
reloc_howto_type *
@@ -697,8 +1357,6 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
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];
@@ -734,6 +1392,17 @@ loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
{
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];
@@ -745,56 +1414,89 @@ loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
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_vma val = *fix_val;
- /* Check val low bits if rightshift != 0, before rightshift */
- if (howto->rightshift
- && (((0x1UL << howto->rightshift) - 1) & val))
+ bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift;
+
+ /* Perform insn bits field. */
+ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+ val <<= howto->bitpos;
+
+ *fix_val = (bfd_vma)val;
+
+ return true;
+}
+
+/* Adjust val to perform insn
+ R_LARCH_SOP_POP_32_S_10_16_S2
+ R_LARCH_B16. */
+static bool
+reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val)
+{
+ if (howto->complain_on_overflow != complain_overflow_signed)
+ return false;
+
+ bfd_signed_vma val = *fix_val;
+
+ /* Judge whether 4 bytes align. */
+ if (val & ((0x1UL << howto->rightshift) - 1))
return false;
int bitsize = howto->bitsize + howto->rightshift;
+ bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
- /* 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;
@@ -802,22 +1504,24 @@ bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
return true;
}
-/* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2. */
-bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
- bfd_vma *fix_val)
+/* 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)
{
@@ -827,14 +1531,15 @@ bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
}
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;
@@ -842,22 +1547,25 @@ bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
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)
{
@@ -867,14 +1575,15 @@ bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
}
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;
@@ -882,8 +1591,9 @@ bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
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 *)
diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h
index 8ea63d03fa5..7b8a72130f1 100644
--- a/bfd/elfxx-loongarch.h
+++ b/bfd/elfxx-loongarch.h
@@ -30,6 +30,10 @@ loongarch_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
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. */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 29e8187f95f..7eaa75ad11e 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3457,6 +3457,42 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_LARCH_SUB24",
"BFD_RELOC_LARCH_SUB32",
"BFD_RELOC_LARCH_SUB64",
+ "BFD_RELOC_LARCH_B16",
+ "BFD_RELOC_LARCH_B21",
+ "BFD_RELOC_LARCH_B26",
+ "BFD_RELOC_LARCH_ABS_HI20",
+ "BFD_RELOC_LARCH_ABS_LO12",
+ "BFD_RELOC_LARCH_ABS64_LO20",
+ "BFD_RELOC_LARCH_ABS64_HI12",
+ "BFD_RELOC_LARCH_PCALA_HI20",
+ "BFD_RELOC_LARCH_PCALA_LO12",
+ "BFD_RELOC_LARCH_PCALA64_LO20",
+ "BFD_RELOC_LARCH_PCALA64_HI12",
+ "BFD_RELOC_LARCH_GOT_PC_HI20",
+ "BFD_RELOC_LARCH_GOT_PC_LO12",
+ "BFD_RELOC_LARCH_GOT64_PC_LO20",
+ "BFD_RELOC_LARCH_GOT64_PC_HI12",
+ "BFD_RELOC_LARCH_GOT_HI20",
+ "BFD_RELOC_LARCH_GOT_LO12",
+ "BFD_RELOC_LARCH_GOT64_LO20",
+ "BFD_RELOC_LARCH_GOT64_HI12",
+ "BFD_RELOC_LARCH_TLS_LE_HI20",
+ "BFD_RELOC_LARCH_TLS_LE_LO12",
+ "BFD_RELOC_LARCH_TLS_LE64_LO20",
+ "BFD_RELOC_LARCH_TLS_LE64_HI12",
+ "BFD_RELOC_LARCH_TLS_IE_PC_HI20",
+ "BFD_RELOC_LARCH_TLS_IE_PC_LO12",
+ "BFD_RELOC_LARCH_TLS_IE64_PC_LO20",
+ "BFD_RELOC_LARCH_TLS_IE64_PC_HI12",
+ "BFD_RELOC_LARCH_TLS_IE_HI20",
+ "BFD_RELOC_LARCH_TLS_IE_LO12",
+ "BFD_RELOC_LARCH_TLS_IE64_LO20",
+ "BFD_RELOC_LARCH_TLS_IE64_HI12",
+ "BFD_RELOC_LARCH_TLS_LD_PC_HI20",
+ "BFD_RELOC_LARCH_TLS_LD_HI20",
+ "BFD_RELOC_LARCH_TLS_GD_PC_HI20",
+ "BFD_RELOC_LARCH_TLS_GD_HI20",
+ "BFD_RELOC_LARCH_RELAX",
"@@overflow: BFD_RELOC_UNUSED@@",
};
#endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 36999fe9a40..59c2aaa0d31 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8228,6 +8228,85 @@ ENUMX
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_RELAX
+
ENUMDOC
LARCH relocations.
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index b7aa4ff069c..2d2bb6a5161 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -90,6 +90,142 @@ RELOC_NUMBER (R_LARCH_SUB64, 56)
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)
+
+/* RELAX. */
+RELOC_NUMBER (R_LARCH_RELAX, 99)
+
END_RELOC_NUMBERS (R_LARCH_count)
/* Processor specific flags for the ELF header e_flags field. */
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types.
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
2022-07-21 1:37 ` [PATCH v2 1/6] bfd: Add supported for LoongArch new relocations liuzhensong
@ 2022-07-21 1:37 ` liuzhensong
2022-07-21 2:30 ` Xi Ruoyao
2022-07-21 1:37 ` [PATCH v2 3/6] LoongArch: gas: " liuzhensong
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
opcodes: Replace old insns with news and generate new relocate types
while macro insns expanding.
opcodes/
loongarch-opc.c
---
opcodes/loongarch-opc.c | 412 +++++++++++++++++++++++-----------------
1 file changed, 242 insertions(+), 170 deletions(-)
diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index 62a2edb1ca9..be0de61c3aa 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -103,158 +103,230 @@ const char *const loongarch_x_normal_name[32] =
"$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. */
};
@@ -728,9 +800,9 @@ static struct loongarch_opcode loongarch_double_float_load_store_opcodes[] =
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. */
};
@@ -738,43 +810,43 @@ static struct loongarch_opcode loongarch_float_jmp_opcodes[] =
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. */
};
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 3/6] LoongArch: gas: Add new reloc types.
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
2022-07-21 1:37 ` [PATCH v2 1/6] bfd: Add supported for LoongArch new relocations liuzhensong
2022-07-21 1:37 ` [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types liuzhensong
@ 2022-07-21 1:37 ` liuzhensong
2022-07-21 1:37 ` [PATCH v2 4/6] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
2022-07-21 1:37 ` [PATCH v2 5/6] bfd: Delete R_LARCH_NONE from dyn info of LoongArch liuzhensong
4 siblings, 0 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
Generate new relocate types while use new macro insns.
gas/config/
loongarch-lex.h
loongarch-parse.y
tc-loongarch.c
tc-loongarch.h
---
gas/config/loongarch-lex.h | 3 +
gas/config/loongarch-parse.y | 72 +++++-------------
gas/config/tc-loongarch.c | 140 ++++++++++++++++++++++++-----------
gas/config/tc-loongarch.h | 7 +-
4 files changed, 120 insertions(+), 102 deletions(-)
diff --git a/gas/config/loongarch-lex.h b/gas/config/loongarch-lex.h
index 59212442242..35d22dbdbc9 100644
--- a/gas/config/loongarch-lex.h
+++ b/gas/config/loongarch-lex.h
@@ -32,3 +32,6 @@ loongarch_parse_expr (const char *expr,
size_t max_reloc_num,
size_t *reloc_num,
offsetT *imm);
+bfd_reloc_code_real_type
+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *l_r_name);
diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y
index 710f854c74f..902d7204e8e 100644
--- a/gas/config/loongarch-parse.y
+++ b/gas/config/loongarch-parse.y
@@ -83,11 +83,11 @@ static const char *
my_getExpression (expressionS *ep, const char *str)
{
char *save_in, *ret;
+
if (*str == ':')
{
unsigned long j;
char *str_1 = (char *) str;
- str_1++;
j = strtol (str_1, &str_1, 10);
get_internal_label (ep, j, *str_1 == 'f');
return NULL;
@@ -104,65 +104,31 @@ static void
reloc (const char *op_c_str, const char *id_c_str, offsetT addend)
{
expressionS id_sym_expr;
+ bfd_reloc_code_real_type btype;
if (end <= top)
as_fatal (_("expr too huge"));
- if (id_c_str)
- {
- my_getExpression (&id_sym_expr, id_c_str);
- id_sym_expr.X_add_number += addend;
- }
+ /* For compatible old asm code. */
+ if (0 == strcmp (op_c_str, "plt"))
+ btype = BFD_RELOC_LARCH_B26;
else
- {
- id_sym_expr.X_op = O_constant;
- id_sym_expr.X_add_number = addend;
- }
+ btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str);
- if (strcmp (op_c_str, "abs") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE;
- top++;
- }
- else if (strcmp (op_c_str, "pcrel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL;
- top++;
- }
- else if (strcmp (op_c_str, "gprel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL;
- top++;
- }
- else if (strcmp (op_c_str, "tprel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL;
- top++;
- }
- else if (strcmp (op_c_str, "tlsgot") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT;
- top++;
- }
- else if (strcmp (op_c_str, "tlsgd") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GD;
- top++;
- }
- else if (strcmp (op_c_str, "plt") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL;
- top++;
- }
+ if (id_c_str)
+ {
+ my_getExpression (&id_sym_expr, id_c_str);
+ id_sym_expr.X_add_number += addend;
+ }
else
- as_fatal (_("unknown reloc hint: %s"), op_c_str);
+ {
+ id_sym_expr.X_op = O_constant;
+ id_sym_expr.X_add_number = addend;
+ }
+
+ top->value = id_sym_expr;
+ top->type = btype;
+ top++;
}
static void
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 08203d291bd..fbbaca55085 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -362,18 +362,6 @@ loongarch_mach (void)
static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
-static const char *
-my_getExpression (expressionS *ep, const char *str)
-{
- char *save_in, *ret;
- save_in = input_line_pointer;
- input_line_pointer = (char *) str;
- expression (ep);
- ret = input_line_pointer;
- input_line_pointer = save_in;
- return ret;
-}
-
static void
s_loongarch_align (int arg)
{
@@ -480,11 +468,6 @@ get_internal_label (expressionS *label_expr, unsigned long label,
label_expr->X_add_number = 0;
}
-extern int loongarch_parse_expr (const char *expr,
- struct reloc_info *reloc_stack_top,
- size_t max_reloc_num, size_t *reloc_num,
- offsetT *imm_if_no_reloc);
-
static int
is_internal_label (const char *c_str)
{
@@ -652,6 +635,15 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
as_fatal (
_("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
esc_ch1, esc_ch2, bit_field, arg);
+ if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
+ && ip->reloc_info[0].type < BFD_RELOC_LARCH_RELAX)
+ {
+ /* As we compact stack-relocs, it is no need for pop operation.
+ But break out until here in order to check the imm field.
+ May be reloc_num > 1 if implement relax? */
+ ip->reloc_num += reloc_num;
+ break;
+ }
reloc_num++;
ip->reloc_num += reloc_num;
ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
@@ -767,7 +759,12 @@ get_loongarch_opcode (struct loongarch_cl_insn *insn)
{
ase->name_hash_entry = str_htab_create ();
for (it = ase->opcodes; it->name; it++)
- str_hash_insert (ase->name_hash_entry, it->name, (void *) it, 0);
+ {
+ if ((!it->include || (it->include && *it->include))
+ && (!it->exclude || (it->exclude && !(*it->exclude))))
+ str_hash_insert (ase->name_hash_entry, it->name,
+ (void *) it, 0);
+ }
}
if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
@@ -800,10 +797,11 @@ static int
check_this_insn_before_appending (struct loongarch_cl_insn *ip)
{
int ret = 0;
- if (strcmp (ip->name, "la.abs") == 0)
+
+ if (strncmp (ip->name, "la.abs", 6) == 0)
{
ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
- my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]);
+ ip->reloc_info[ip->reloc_num].value = const_0;
ip->reloc_num++;
}
else if (ip->insn->mask == 0xffff8000
@@ -980,6 +978,7 @@ assember_macro_helper (const char *const args[], void *context_ptr)
ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
sizeof (args_buf));
}
+
return ret;
}
@@ -1096,6 +1095,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
static int64_t stack_top;
static int last_reloc_is_sop_push_pcrel_1 = 0;
int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
+ segT sub_segment;
last_reloc_is_sop_push_pcrel_1 = 0;
char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
@@ -1104,26 +1104,40 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
- case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
- case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL:
+ case BFD_RELOC_LARCH_TLS_LE_HI20:
+ case BFD_RELOC_LARCH_TLS_LE_LO12:
+ case BFD_RELOC_LARCH_TLS_LE64_LO20:
+ case BFD_RELOC_LARCH_TLS_LE64_HI12:
+ case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
+ case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
+ case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
+ case BFD_RELOC_LARCH_TLS_IE_HI20:
+ case BFD_RELOC_LARCH_TLS_IE_LO12:
+ case BFD_RELOC_LARCH_TLS_IE64_LO20:
+ case BFD_RELOC_LARCH_TLS_IE64_HI12:
+ case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_LD_HI20:
+ case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_GD_HI20:
+ /* Add tls lo (got_lo reloc type). */
if (fixP->fx_addsy == NULL)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Relocation against a constant"));
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
- if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
- || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
- || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT)
- S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
+ if (fixP->fx_addsy == NULL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Relocation against a constant"));
- if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL)
- {
- last_reloc_is_sop_push_pcrel_1 = 1;
- if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
- stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
- - (fixP->fx_where + fixP->fx_frag->fr_address));
- else
- stack_top = 0;
- }
+ last_reloc_is_sop_push_pcrel_1 = 1;
+ if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
+ stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+ - (fixP->fx_where + fixP->fx_frag->fr_address));
+ else
+ stack_top = 0;
break;
case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
@@ -1143,11 +1157,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_64:
case BFD_RELOC_32:
+ case BFD_RELOC_24:
+ case BFD_RELOC_16:
+ case BFD_RELOC_8:
+
+ if (fixP->fx_r_type == BFD_RELOC_32
+ && fixP->fx_addsy && fixP->fx_subsy
+ && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
+ && strcmp (sub_segment->name, ".eh_frame") == 0
+ && S_GET_VALUE (fixP->fx_subsy)
+ == fixP->fx_frag->fr_address + fixP->fx_where)
+ {
+ fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
+ fixP->fx_subsy = NULL;
+ break;
+ }
+
if (fixP->fx_subsy)
{
- case BFD_RELOC_24:
- case BFD_RELOC_16:
- case BFD_RELOC_8:
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
fixP->fx_next->fx_addsy = fixP->fx_subsy;
fixP->fx_next->fx_subsy = NULL;
@@ -1190,6 +1217,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
}
break;
+ case BFD_RELOC_LARCH_B16:
+ case BFD_RELOC_LARCH_B21:
+ case BFD_RELOC_LARCH_B26:
+ if (fixP->fx_addsy == NULL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _ ("Relocation against a constant."));
+ }
+ if (S_GET_SEGMENT (fixP->fx_addsy) == seg
+ && !S_FORCE_RELOC (fixP->fx_addsy, 1))
+ {
+ int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
+ int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
+ fix_reloc_insn (fixP, sym_addend - pc, buf);
+ fixP->fx_done = 1;
+ }
+
+ break;
+
default:
break;
}
@@ -1210,6 +1256,18 @@ md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
return 0;
}
+int
+loongarch_fix_adjustable (fixS *fix)
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fix->fx_addsy)
+ || S_IS_WEAK (fix->fx_addsy)
+ || S_FORCE_RELOC (fix->fx_addsy, true))
+ return 0;
+
+ return 1;
+}
+
/* Translate internal representation of relocation info to BFD target
format. */
arelent *
@@ -1249,12 +1307,6 @@ loongarch_cfi_frame_initial_instructions (void)
cfi_add_CFA_def_cfa_register (3 /* $sp */);
}
-int
-loongarch_dwarf2_addr_size (void)
-{
- return LARCH_opts.ase_lp64 ? 8 : 4;
-}
-
void
tc_loongarch_parse_to_dw2regnum (expressionS *exp)
{
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 2664da59f51..f05926d7d67 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -49,7 +49,8 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
/* This is called to see whether a reloc against a defined symbol
should be converted into a reloc against a section. */
-#define tc_fix_adjustable(fixp) 0
+extern int loongarch_fix_adjustable (struct fix *fix);
+#define tc_fix_adjustable(fixp) loongarch_fix_adjustable(fixp)
/* Values passed to md_apply_fix don't include symbol values. */
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
@@ -59,10 +60,6 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
#define TARGET_USE_CFIPOP 1
#define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra. */
#define DWARF2_CIE_DATA_ALIGNMENT -4
-extern int loongarch_dwarf2_addr_size (void);
-#define DWARF2_FDE_RELOC_SIZE loongarch_dwarf2_addr_size ()
-#define DWARF2_ADDR_SIZE(bfd) loongarch_dwarf2_addr_size ()
-#define CFI_DIFF_EXPR_OK 0
#define tc_cfi_frame_initial_instructions \
loongarch_cfi_frame_initial_instructions
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 4/6] LoongArch: Move ifunc info to rela.dyn from rela.plt.
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
` (2 preceding siblings ...)
2022-07-21 1:37 ` [PATCH v2 3/6] LoongArch: gas: " liuzhensong
@ 2022-07-21 1:37 ` liuzhensong
2022-07-21 1:37 ` [PATCH v2 5/6] bfd: Delete R_LARCH_NONE from dyn info of LoongArch liuzhensong
4 siblings, 0 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
Delete R_LARCH_IRELATIVE from dynamic loader (glibc ld.so) when
loading lazy function (rela.plt section).
In dynamic programes, move ifunc dynamic relocate info to section
srelgot from srelplt.
bfd/
elfnn-loongarch.c
---
bfd/elfnn-loongarch.c | 373 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 344 insertions(+), 29 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 21710dcb3fb..3d86e1422af 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -1207,6 +1207,259 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
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. */
@@ -1234,12 +1487,22 @@ elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* 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 (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;
}
@@ -2162,22 +2425,40 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
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);
+ 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 (htab->elf.splt != NULL)
- sreloc = htab->elf.srelplt;
+ 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)
{
@@ -2816,10 +3097,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
case R_LARCH_PCALA64_LO20:
case R_LARCH_PCALA64_HI12:
if (h && h->plt.offset != MINUS_ONE)
- {
- BFD_ASSERT (rel->r_addend == 0);
- relocation = sec_addr (plt) + h->plt.offset;
- }
+ relocation = sec_addr (plt) + h->plt.offset;
else
relocation += rel->r_addend;
@@ -3237,7 +3515,10 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
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;
@@ -3272,11 +3553,45 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
rela.r_offset = got_address;
- /* 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);
+ /* TRUE if this is a PLT reference to a local IFUNC. */
+ 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);
+ }
+
+ /* 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. */
+ 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);
+ }
if (!h->def_regular)
{
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 5/6] bfd: Delete R_LARCH_NONE from dyn info of LoongArch.
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
` (3 preceding siblings ...)
2022-07-21 1:37 ` [PATCH v2 4/6] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
@ 2022-07-21 1:37 ` liuzhensong
4 siblings, 0 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 1:37 UTC (permalink / raw)
To: binutils
Cc: xry111, i.swmail, maskray, xuchenghua, mengqinggang, huangpei,
chenglulu, caiyinyu, liuzhensong
Some R_LARCH_64 in section .eh_frame will to generate
R_LARCH_NONE, we change relocation to R_LARCH_32_PCREL
from R_LARCH_64 in setction .eh_frame and not generate
dynamic relocation for R_LARCH_32_PCREL.
Add New relocate type R_LARCH_32_PCREL for .eh_frame.
include/elf/
loongarch.h
bfd/
bfd/bfd-in2.h
libbfd.h
reloc.c
elfxx-loongarch.c
elfnn-loongarch.c
gas/config/
tc-loongarch.c
binutils/
readelf.c
ld/testsuite/ld-elf/
eh5.d
---
bfd/bfd-in2.h | 1 +
bfd/elfnn-loongarch.c | 11 +++++++++++
bfd/elfxx-loongarch.c | 19 ++++++++++++++++++-
bfd/libbfd.h | 1 +
bfd/reloc.c | 3 +++
binutils/readelf.c | 2 ++
include/elf/loongarch.h | 5 ++++-
ld/testsuite/ld-elf/eh5.d | 2 +-
8 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 91e6ad76b9a..2d6e1bbc0b0 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6309,6 +6309,7 @@ assembler and not (currently) written to any object files. */
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 };
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 3d86e1422af..4efe3d9370c 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -2010,6 +2010,17 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
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:
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index f059f1a0c05..0b00df556b7 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -1327,7 +1327,24 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
reloc_bits, /* adjust_reloc_bits */
"gd_hi20"), /* larch_reloc_type_name */
- LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (99). */
+ LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */
+ 0, /* rightshift. */
+ 4, /* size. */
+ 32, /* bitsize. */
+ true, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_dont, /* complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_LARCH_32_PCREL", /* name. */
+ false, /* partial_inplace. */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false, /* pcrel_offset */
+ BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */
+ NULL, /* adjust_reloc_bits */
+ NULL), /* larch_reloc_type_name */
+
+ LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */
0, /* rightshift */
1, /* size */
0, /* bitsize */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 7eaa75ad11e..c766722efb0 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3492,6 +3492,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"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@@",
};
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 59c2aaa0d31..268e4b13049 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8304,6 +8304,9 @@ ENUMX
ENUMX
BFD_RELOC_LARCH_TLS_GD_HI20
+ENUMX
+ BFD_RELOC_LARCH_32_PCREL
+
ENUMX
BFD_RELOC_LARCH_RELAX
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 6b7692d9dd5..4a3e448e30d 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -14389,6 +14389,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type)
case EM_AVR_OLD:
case EM_AVR:
return reloc_type == 36; /* R_AVR_32_PCREL. */
+ case EM_LOONGARCH:
+ return reloc_type == 99; /* R_LARCH_32_PCREL. */
case EM_MICROBLAZE:
return reloc_type == 2; /* R_MICROBLAZE_32_PCREL. */
case EM_OR1K:
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index 2d2bb6a5161..74757b82ca8 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -223,8 +223,11 @@ RELOC_NUMBER (R_LARCH_TLS_GD_PC_HI20, 97)
%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, 99)
+RELOC_NUMBER (R_LARCH_RELAX, 100)
END_RELOC_NUMBERS (R_LARCH_count)
diff --git a/ld/testsuite/ld-elf/eh5.d b/ld/testsuite/ld-elf/eh5.d
index d614251587c..4a697482355 100644
--- a/ld/testsuite/ld-elf/eh5.d
+++ b/ld/testsuite/ld-elf/eh5.d
@@ -4,7 +4,7 @@
#ld:
#readelf: -wf
#target: [check_as_cfi]
-#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-* loongarch64-*-*
+#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-*
Contents of the .eh_frame section:
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types.
2022-07-21 1:37 ` [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types liuzhensong
@ 2022-07-21 2:30 ` Xi Ruoyao
2022-07-21 6:02 ` liuzhensong
0 siblings, 1 reply; 10+ messages in thread
From: Xi Ruoyao @ 2022-07-21 2:30 UTC (permalink / raw)
To: liuzhensong, binutils
Cc: i.swmail, maskray, xuchenghua, mengqinggang, huangpei, chenglulu,
caiyinyu
On Thu, 2022-07-21 at 09:37 +0800, liuzhensong wrote:
> +#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
Is it possible to use
lu12i.w %1, %%abs_hi20(%2)
lu32i.d %1, %%abs_lo12(%2)
lu52i.d %1, %1, %%abs64_hi12(%2)
addi.d %1, %1, %%abs64_lo12(%2)
so a future linker relaxation (or some optimization, anyway) may combine
the last addi.d instruction with a following ld instruction? Like
la.abs64 $t0, foo
ld.d $t0, $t0, 0
=>
lu12i.w $t0, %abs_hi20(foo)
lu32i.d $t0, %abs_lo12(foo)
lu52i.d $t0, $t0, %abs64_hi12(foo)
ld.d $t0, $t0, %abs64_lo12(foo)
(Doing so will need to take the highest bit of lo12 as a carry into the
higher 52 bits.)
--
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types.
2022-07-21 2:30 ` Xi Ruoyao
@ 2022-07-21 6:02 ` liuzhensong
2022-07-21 7:51 ` Xi Ruoyao
0 siblings, 1 reply; 10+ messages in thread
From: liuzhensong @ 2022-07-21 6:02 UTC (permalink / raw)
To: Xi Ruoyao, binutils
Cc: i.swmail, maskray, xuchenghua, mengqinggang, huangpei, chenglulu,
caiyinyu
在 2022/7/21 上午10:30, Xi Ruoyao 写道:
> On Thu, 2022-07-21 at 09:37 +0800, liuzhensong wrote:
>> +#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
> Is it possible to use
>
> lu12i.w %1, %%abs_hi20(%2)
> lu32i.d %1, %%abs_lo12(%2)
> lu52i.d %1, %1, %%abs64_hi12(%2)
> addi.d %1, %1, %%abs64_lo12(%2)
>
> so a future linker relaxation (or some optimization, anyway) may combine
> the last addi.d instruction with a following ld instruction? Like
>
> la.abs64 $t0, foo
> ld.d $t0, $t0, 0
>
> =>
>
> lu12i.w $t0, %abs_hi20(foo)
> lu32i.d $t0, %abs_lo12(foo)
> lu52i.d $t0, $t0, %abs64_hi12(foo)
> ld.d $t0, $t0, %abs64_lo12(foo)
>
> (Doing so will need to take the highest bit of lo12 as a carry into the
> higher 52 bits.)
>
It seems default for addi.d/ld.d to access extreme address.
Simple example of abs32:
address range of abs32 : 0~0xffffffff
sym address: 0xfffff800
lui12.w $rd, 0xfffff
ori $rd, $d, 0x800
$rd is 0xfffff800
Obviously, lu12i.w and addi.w/ld.w can not get address > 0xfffff7fc abs64 is exactly same as abs32.
However, it is good idea to replace (lu12i.w,ori,ld.w) with (lu12i.w ld.w) if sym address in range -2G-2k ~~ +2G-2k?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types.
2022-07-21 6:02 ` liuzhensong
@ 2022-07-21 7:51 ` Xi Ruoyao
2022-07-21 8:26 ` liuzhensong
0 siblings, 1 reply; 10+ messages in thread
From: Xi Ruoyao @ 2022-07-21 7:51 UTC (permalink / raw)
To: liuzhensong, binutils
Cc: i.swmail, maskray, xuchenghua, mengqinggang, huangpei, chenglulu,
caiyinyu
On Thu, 2022-07-21 at 14:02 +0800, liuzhensong wrote:
>
> It seems default for addi.d/ld.d to access extreme address.
> Simple example of abs32:
> address range of abs32 : 0~0xffffffff
> sym address: 0xfffff800
> lui12.w $rd, 0xfffff
> ori $rd, $d, 0x800
> $rd is 0xfffff800
> Obviously, lu12i.w and addi.w/ld.w can not get address > 0xfffff7fc
Hmm... Wouldn't "addi.{w/d} $t0, $zero, -0x800" work for this?
--
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types.
2022-07-21 7:51 ` Xi Ruoyao
@ 2022-07-21 8:26 ` liuzhensong
0 siblings, 0 replies; 10+ messages in thread
From: liuzhensong @ 2022-07-21 8:26 UTC (permalink / raw)
To: Xi Ruoyao, binutils
Cc: i.swmail, maskray, xuchenghua, mengqinggang, huangpei, chenglulu,
caiyinyu
在 2022/7/21 下午3:51, Xi Ruoyao 写道:
> On Thu, 2022-07-21 at 14:02 +0800, liuzhensong wrote:
>
>> It seems default for addi.d/ld.d to access extreme address.
>> Simple example of abs32:
>> address range of abs32 : 0~0xffffffff
>> sym address: 0xfffff800
>> lui12.w $rd, 0xfffff
>> ori $rd, $d, 0x800
>> $rd is 0xfffff800
>> Obviously, lu12i.w and addi.w/ld.w can not get address > 0xfffff7fc
> Hmm... Wouldn't "addi.{w/d} $t0, $zero, -0x800" work for this?
>
>
This can be do in ld relax rather than as.
+#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
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-07-21 8:26 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-21 1:37 [PATCH v2 0/6] Add new relocations for LoongArch liuzhensong
2022-07-21 1:37 ` [PATCH v2 1/6] bfd: Add supported for LoongArch new relocations liuzhensong
2022-07-21 1:37 ` [PATCH v2 2/6] LoongArch:opcodes: Add new reloc types liuzhensong
2022-07-21 2:30 ` Xi Ruoyao
2022-07-21 6:02 ` liuzhensong
2022-07-21 7:51 ` Xi Ruoyao
2022-07-21 8:26 ` liuzhensong
2022-07-21 1:37 ` [PATCH v2 3/6] LoongArch: gas: " liuzhensong
2022-07-21 1:37 ` [PATCH v2 4/6] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
2022-07-21 1:37 ` [PATCH v2 5/6] bfd: Delete R_LARCH_NONE from dyn info of LoongArch liuzhensong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).