Because the binutils of the loongarch architecture adds relaxation support [1], the next version of binutils will not be able to build grub.
So we added the R_LARCH_B16, R_LARCH_B21 and R_LARCH_RELAX [2] relocations to enhance grub compatibility. [1]: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=56576f4a722b7398d35802ecf7d4185c27d6d69b [2]: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#relocations Signed-off-by: Xiaotian Wu <wuxiaot...@loongson.cn> --- grub-core/kern/loongarch64/dl.c | 17 +++++++++++ grub-core/kern/loongarch64/dl_helper.c | 39 ++++++++++++++++++++++++++ include/grub/elf.h | 3 ++ include/grub/loongarch64/reloc.h | 2 ++ util/grub-mkimagexx.c | 22 +++++++++++++++ util/grub-module-verifier.c | 3 ++ 6 files changed, 86 insertions(+) diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c index 7f923b415..c22d2bd52 100644 --- a/grub-core/kern/loongarch64/dl.c +++ b/grub-core/kern/loongarch64/dl.c @@ -87,11 +87,28 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, } break; case R_LARCH_MARK_LA: + case R_LARCH_RELAX: break; case R_LARCH_SOP_PUSH_PCREL: case R_LARCH_SOP_PUSH_PLT_PCREL: grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place); break; + case R_LARCH_B16: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + + grub_loongarch64_b16 (abs_place, off); + } + break; + case R_LARCH_B21: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + + grub_loongarch64_b21 (abs_place, off); + } + break; case R_LARCH_B26: { grub_uint32_t *abs_place = place; diff --git a/grub-core/kern/loongarch64/dl_helper.c b/grub-core/kern/loongarch64/dl_helper.c index b5d39b282..a3569b1e5 100644 --- a/grub-core/kern/loongarch64/dl_helper.c +++ b/grub-core/kern/loongarch64/dl_helper.c @@ -204,6 +204,45 @@ grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack, *place =(*place) | ((a >> 18) & 0x3ff); } +/* + * B16 relocation for the 18-bit PC-relative jump + * (*(uint32_t *) PC) [25 ... 10] = (S+A-PC) [17 ... 2] + */ +void grub_loongarch64_b16 (grub_uint32_t *place, grub_int64_t offset) +{ + grub_uint32_t val; + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc0003ff); + + grub_dprintf ("dl", " reloc_b16 %p %c= 0x%" PRIxGRUB_INT64_T "\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? -offset : offset); + + val = ((offset >> 2) & 0xffff) << 10; + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +/* + * B21 relocation for the 23-bit PC-relative jump + * (*(uint32_t *) PC) [4 ... 0] = (S+A-PC) [22 ... 18] + * (*(uint32_t *) PC) [25 ... 10] = (S+A-PC) [17 ... 2] + */ +void grub_loongarch64_b21 (grub_uint32_t *place, grub_int64_t offset) +{ + grub_uint32_t val; + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc0003e0); + + grub_dprintf ("dl", " reloc_b21 %p %c= 0x%" PRIxGRUB_INT64_T "\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? -offset : offset); + + val = ((offset >> 18) & 0x1f) | (((offset >> 2) & 0xffff) << 10); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + /* * B26 relocation for the 28-bit PC-relative jump * (*(uint32_t *) PC) [9 ... 0] = (S+A-PC) [27 ... 18] diff --git a/include/grub/elf.h b/include/grub/elf.h index bd313a70b..12349c9e4 100644 --- a/include/grub/elf.h +++ b/include/grub/elf.h @@ -2558,6 +2558,8 @@ typedef Elf32_Addr Elf32_Conflict; #define R_LARCH_SOP_POP_32_S_5_20 43 #define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 #define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 +#define R_LARCH_B16 64 +#define R_LARCH_B21 65 #define R_LARCH_B26 66 #define R_LARCH_ABS_HI20 67 #define R_LARCH_ABS_LO12 68 @@ -2565,6 +2567,7 @@ typedef Elf32_Addr Elf32_Conflict; #define R_LARCH_ABS64_HI12 70 #define R_LARCH_PCALA_HI20 71 #define R_LARCH_PCALA_LO12 72 +#define R_LARCH_RELAX 100 extern grub_err_t grub_elf32_get_shnum (Elf32_Ehdr *e, Elf32_Shnum *shnum); extern grub_err_t grub_elf32_get_shstrndx (Elf32_Ehdr *e, Elf32_Word *shstrndx); diff --git a/include/grub/loongarch64/reloc.h b/include/grub/loongarch64/reloc.h index 8ba355385..01d4f6831 100644 --- a/include/grub/loongarch64/reloc.h +++ b/include/grub/loongarch64/reloc.h @@ -57,6 +57,8 @@ void grub_loongarch64_sop_32_s_0_5_10_16_s2 (grub_loongarch64_stack_t stack, void grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack, grub_uint64_t *place); +void grub_loongarch64_b16 (grub_uint32_t *place, grub_int64_t offset); +void grub_loongarch64_b21 (grub_uint32_t *place, grub_int64_t offset); void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset); void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset); void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index e50b29533..04c74d226 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -1144,6 +1144,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, } break; case R_LARCH_MARK_LA: + case R_LARCH_RELAX: break; case R_LARCH_SOP_PUSH_PCREL: case R_LARCH_SOP_PUSH_PLT_PCREL: @@ -1152,6 +1153,24 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, +offset +image_target->vaddr_offset)); break; + case R_LARCH_B16: + { + grub_int64_t off; + + off = sym_addr - pc; + + grub_loongarch64_b16 (t32, off); + } + break; + case R_LARCH_B21: + { + grub_int64_t off; + + off = sym_addr - pc; + + grub_loongarch64_b21 (t32, off); + } + break; case R_LARCH_B26: { grub_int64_t off; @@ -1777,6 +1796,8 @@ translate_relocation_pe (struct translate_context *ctx, case R_LARCH_SOP_POP_32_S_5_20: 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_B16: + case R_LARCH_B21: case R_LARCH_B26: case R_LARCH_ABS_HI20: case R_LARCH_ABS_LO12: @@ -1784,6 +1805,7 @@ translate_relocation_pe (struct translate_context *ctx, case R_LARCH_ABS64_HI12: case R_LARCH_PCALA_HI20: case R_LARCH_PCALA_LO12: + case R_LARCH_RELAX: grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c index 91d9e8f88..3d4c9a14b 100644 --- a/util/grub-module-verifier.c +++ b/util/grub-module-verifier.c @@ -140,6 +140,8 @@ struct grub_module_verifier_arch archs[] = { R_LARCH_SOP_POP_32_S_5_20, R_LARCH_SOP_POP_32_S_0_5_10_16_S2, R_LARCH_SOP_POP_32_S_0_10_10_16_S2, + R_LARCH_B16, + R_LARCH_B21, R_LARCH_B26, R_LARCH_ABS_HI20, R_LARCH_ABS_LO12, @@ -147,6 +149,7 @@ struct grub_module_verifier_arch archs[] = { R_LARCH_ABS64_HI12, R_LARCH_PCALA_HI20, R_LARCH_PCALA_LO12, + R_LARCH_RELAX, -1 }, (int[]){ -1 -- 2.20.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel