From 529e366dd9c7278b050ed0f8ed02e56e835afd46 Mon Sep 17 00:00:00 2001 From: mengqinggang Date: Sun, 7 Sep 2025 15:47:56 +0800 Subject: [PATCH] LoongArch: Add LA32 and LA32R relocations LA32 and LA32R do not have pcaddu18i. LA32R does not have pcalau12i. Add R_LARCH_CALL30 for pcaddu12i + jirl used in LA32 and LA32R. Add R_LARCH_*_PCADD_HI20 for pcaddu12i used in LA32R. Add R_LARCH_*_PCADD_LO12 for addi.w/ld.w used in LA32R. --- bfd/bfd-in2.h | 13 +++ bfd/elfnn-loongarch.c | 21 ++-- bfd/elfxx-loongarch.c | 222 ++++++++++++++++++++++++++++++++++++++++ bfd/libbfd.h | 13 +++ bfd/reloc.c | 27 +++++ include/elf/loongarch.h | 35 +++++++ 6 files changed, 318 insertions(+), 13 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index c89fe7ad8ac..ff0c5f88cdc 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -7444,6 +7444,19 @@ enum bfd_reloc_code_real BFD_RELOC_LARCH_TLS_LD_PCREL20_S2, BFD_RELOC_LARCH_TLS_GD_PCREL20_S2, BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, + BFD_RELOC_LARCH_CALL30, + BFD_RELOC_LARCH_PCADD_HI20, + BFD_RELOC_LARCH_PCADD_LO12, + BFD_RELOC_LARCH_GOT_PCADD_HI20, + BFD_RELOC_LARCH_GOT_PCADD_LO12, + BFD_RELOC_LARCH_TLS_IE_PCADD_HI20, + BFD_RELOC_LARCH_TLS_IE_PCADD_LO12, + BFD_RELOC_LARCH_TLS_LD_PCADD_HI20, + BFD_RELOC_LARCH_TLS_LD_PCADD_LO12, + BFD_RELOC_LARCH_TLS_GD_PCADD_HI20, + BFD_RELOC_LARCH_TLS_GD_PCADD_LO12, + BFD_RELOC_LARCH_TLS_DESC_PCADD_HI20, + BFD_RELOC_LARCH_TLS_DESC_PCADD_LO12, 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 ddb809760ab..dd6ac76a042 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -5136,9 +5136,8 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, if (local_exec) { /* DESC -> LE relaxation: - pcalalau12i $a0,%desc_pc_hi20(var) => - lu12i.w $a0,%le_hi20(var) - */ + pcalau12i $a0,%desc_pc_hi20(var) => + lu12i.w $a0,%le_hi20(var) */ bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_RD_A0, contents + rel->r_offset); rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_HI20); @@ -5146,9 +5145,8 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, else { /* DESC -> IE relaxation: - pcalalau12i $a0,%desc_pc_hi20(var) => - pcalalau12i $a0,%ie_pc_hi20(var) - */ + pcalau12i $a0,%desc_pc_hi20(var) => + pcalau12i $a0,%ie_pc_hi20(var) */ rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_IE_PC_HI20); } return true; @@ -5158,8 +5156,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, { /* DESC -> LE relaxation: addi.d $a0,$a0,%desc_pc_lo12(var) => - ori $a0,$a0,le_lo12(var) - */ + ori $a0,$a0,le_lo12(var) */ insn = LARCH_OP_ORI | LARCH_RD_RJ_A0; bfd_put (32, abfd, LARCH_OP_ORI | LARCH_RD_RJ_A0, contents + rel->r_offset); @@ -5181,8 +5178,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, case R_LARCH_TLS_DESC_CALL: /* DESC -> LE/IE relaxation: ld.d $ra,$a0,%desc_ld(var) => NOP - jirl $ra,$ra,%desc_call(var) => NOP - */ + jirl $ra,$ra,%desc_call(var) => NOP */ rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE); bfd_put (32, abfd, LARCH_NOP, contents + rel->r_offset); /* link with -relax option will delete NOP. */ @@ -5194,9 +5190,8 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, if (local_exec) { /* IE -> LE relaxation: - pcalalau12i $rd,%ie_pc_hi20(var) => - lu12i.w $rd,%le_hi20(var) - */ + pcalau12i $rd,%ie_pc_hi20(var) => + lu12i.w $rd,%le_hi20(var) */ insn = bfd_getl32 (contents + rel->r_offset); bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_GET_RD(insn), contents + rel->r_offset); diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c index ce1032f30e9..b29ca218f24 100644 --- a/bfd/elfxx-loongarch.c +++ b/bfd/elfxx-loongarch.c @@ -1882,6 +1882,228 @@ static loongarch_reloc_howto_type loongarch_howto_table[] = BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, /* bfd_reloc_code_real_type. */ reloc_sign_bits, /* adjust_reloc_bits. */ "desc_pcrel_20"), /* larch_reloc_type_name. */ + + /* For LA32R medium call. */ + LOONGARCH_HOWTO (R_LARCH_CALL30, /* type (127). */ + 2, /* rightshift. */ + 8, /* size. */ + 30, /* bitsize. */ + true, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_CALL30", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask. */ + 0x000ffc0001ffffe0, /* dst_mask. */ + false, /* pcrel_offset. */ + BFD_RELOC_LARCH_CALL30, /* bfd_reloc_code_real_type. */ + reloc_sign_bits, /* adjust_reloc_bits. */ + "call30"), /* larch_reloc_type_name. */ + + LOONGARCH_HOWTO (R_LARCH_PCADD_HI20, /* type (128). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + true, /* pcrel_offset */ + BFD_RELOC_LARCH_PCADD_HI20, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "pcadd_hi20"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_PCADD_LO12, /* type (129). */ + 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_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "pcadd_lo12"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_GOT_PCADD_HI20, /* type (130). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_GOT_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + true, /* pcrel_offset */ + BFD_RELOC_LARCH_GOT_PCADD_HI20, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "got_pcadd_hi20"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_GOT_PCADD_LO12, /* type (131). */ + 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_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_GOT_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "got_pcadd_lo12"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_IE_PCADD_HI20, /* type (132). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_TLS_IE_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + true, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_IE_PCADD_HI20, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "ie_pcadd_hi20"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_IE_PCADD_LO12, /* type (133). */ + 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_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_IE_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "ie_pcadd_lo12"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCADD_HI20, /* type (134). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_TLS_LD_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + true, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_LD_PCADD_HI20, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "ld_pcadd_hi20"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCADD_LO12, /* type (135). */ + 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_LD_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_LD_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "ld_pcadd_lo12"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCADD_HI20, /* type (136). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_TLS_GD_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x1ffffe0, /* dst_mask */ + true, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_GD_PCADD_HI20, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "gd_pcadd_hi20"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCADD_LO12, /* type (137). */ + 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_GD_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_GD_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "gd_pcadd_lo12"), /* larch_reloc_type_name */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCADD_HI20, /* type (138). */ + 12, /* rightshift. */ + 4, /* size. */ + 20, /* bitsize. */ + true, /* pc_relative. */ + 5, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_LARCH_TLS_DESC_PCADD_HI20", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask. */ + 0x1ffffe0, /* dst_mask. */ + true, /* pcrel_offset. */ + BFD_RELOC_LARCH_TLS_DESC_PCADD_HI20, /* bfd_reloc_code_real_type. */ + reloc_bits, /* adjust_reloc_bits. */ + "desc_pcadd_hi20"), /* larch_reloc_type_name. */ + + LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCADD_LO12, /* type (139). */ + 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_DESC_PCADD_LO12", /* name. */ + false, /* partial_inplace. */ + 0, /* src_mask */ + 0x3ffc00, /* dst_mask */ + false, /* pcrel_offset */ + BFD_RELOC_LARCH_TLS_DESC_PCADD_LO12, /* bfd_reloc_code_real_type */ + reloc_bits, /* adjust_reloc_bits */ + "desc_pcadd_lo12"), /* larch_reloc_type_name */ }; reloc_howto_type * diff --git a/bfd/libbfd.h b/bfd/libbfd.h index c22665935c9..c8249710dff 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -3590,6 +3590,19 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2", "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2", "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2", + "BFD_RELOC_LARCH_CALL30", + "BFD_RELOC_LARCH_PCADD_HI20", + "BFD_RELOC_LARCH_PCADD_LO12", + "BFD_RELOC_LARCH_GOT_PCADD_HI20", + "BFD_RELOC_LARCH_GOT_PCADD_LO12", + "BFD_RELOC_LARCH_TLS_IE_PCADD_HI20", + "BFD_RELOC_LARCH_TLS_IE_PCADD_LO12", + "BFD_RELOC_LARCH_TLS_LD_PCADD_HI20", + "BFD_RELOC_LARCH_TLS_LD_PCADD_LO12", + "BFD_RELOC_LARCH_TLS_GD_PCADD_HI20", + "BFD_RELOC_LARCH_TLS_GD_PCADD_LO12", + "BFD_RELOC_LARCH_TLS_DESC_PCADD_HI20", + "BFD_RELOC_LARCH_TLS_DESC_PCADD_LO12", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif diff --git a/bfd/reloc.c b/bfd/reloc.c index 112f3439c70..699c042cece 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -8248,6 +8248,33 @@ ENUMX ENUMX BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2 +ENUMX + BFD_RELOC_LARCH_CALL30 +ENUMX + BFD_RELOC_LARCH_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_PCADD_LO12 +ENUMX + BFD_RELOC_LARCH_GOT_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_GOT_PCADD_LO12 +ENUMX + BFD_RELOC_LARCH_TLS_IE_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_TLS_IE_PCADD_LO12 +ENUMX + BFD_RELOC_LARCH_TLS_LD_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_TLS_LD_PCADD_LO12 +ENUMX + BFD_RELOC_LARCH_TLS_GD_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_TLS_GD_PCADD_LO12 +ENUMX + BFD_RELOC_LARCH_TLS_DESC_PCADD_HI20 +ENUMX + BFD_RELOC_LARCH_TLS_DESC_PCADD_LO12 + ENUMDOC LARCH relocations. diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h index ca031a18dad..06641133a5c 100644 --- a/include/elf/loongarch.h +++ b/include/elf/loongarch.h @@ -289,6 +289,41 @@ RELOC_NUMBER (R_LARCH_TLS_LD_PCREL20_S2, 124) RELOC_NUMBER (R_LARCH_TLS_GD_PCREL20_S2, 125) RELOC_NUMBER (R_LARCH_TLS_DESC_PCREL20_S2, 126) +/* LA32R medium call + pcaddu12i + jirl + %call30(sym). */ +RELOC_NUMBER (R_LARCH_CALL30, 127) + +/* LA32R PCREL: pcaddu12i, %pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_PCADD_HI20, 128) +/* LA32R PCREL: addi.w/ld.[bhw], %pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_PCADD_LO12, 129) + +/* LA32R GOT: pcaddu12i, %got_pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_GOT_PCADD_HI20, 130) +/* LA32R GOT: ld.w, %got_pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_GOT_PCADD_LO12, 131) + +/* LA32R TLS IE: pcaddu12i, %ie_pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_TLS_IE_PCADD_HI20, 132) +/* LA32R TLS IE: ld.w, %ie_pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_TLS_IE_PCADD_LO12, 133) + +/* LA32R TLS LD: pcaddu12i, %ld_pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_TLS_LD_PCADD_HI20, 134) +/* LA32R TLS LD: addi.w, %ld_pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_TLS_LD_PCADD_LO12, 135) + +/* LA32R TLS GD: pcaddu12i, %gd_pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_TLS_GD_PCADD_HI20, 136) +/* LA32R TLS GD: addi.w, %gd_pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_TLS_GD_PCADD_LO12, 137) + +/* LA32R TLS DESC: pcaddu12i, %desc_pcadd_hi20(sym). */ +RELOC_NUMBER (R_LARCH_TLS_DESC_PCADD_HI20, 138) +/* LA32R TLS DESC: addi.w, %desc_pcadd_lo12(sym). */ +RELOC_NUMBER (R_LARCH_TLS_DESC_PCADD_LO12, 139) + END_RELOC_NUMBERS (R_LARCH_count) /* Processor specific flags for the ELF header e_flags field. */ -- 2.47.3