[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v11 09/11] LoongArch: Support new relocation types in v2.00 ABI
From: |
Xiaotian Wu |
Subject: |
[PATCH v11 09/11] LoongArch: Support new relocation types in v2.00 ABI |
Date: |
Fri, 2 Sep 2022 17:38:25 +0800 |
Link: https://github.com/loongson/LoongArch-Documentation/pull/57
Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn>
---
configure.ac | 17 ++++----
grub-core/kern/loongarch64/dl.c | 54 +++++++++++++++++++++--
grub-core/kern/loongarch64/dl_helper.c | 59 ++++++++++++++++++++++++++
include/grub/elf.h | 7 +++
include/grub/loongarch64/reloc.h | 6 +++
util/grub-mkimagexx.c | 49 ++++++++++++++++++++-
util/grub-module-verifier.c | 7 +++
7 files changed, 187 insertions(+), 12 deletions(-)
diff --git a/configure.ac b/configure.ac
index 71f65a70d..e7c0b3f88 100644
--- a/configure.ac
+++ b/configure.ac
@@ -859,17 +859,18 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" =
xx86_64 ); then
fi
if test "x$target_cpu" = xloongarch64; then
- AC_CACHE_CHECK([whether -Wa,-mla-global-with-abs works],
[grub_cv_cc_mla_global_with_abs], [
- CFLAGS="$TARGET_CFLAGS -Wa,-mla-global-with-abs -Werror"
+ AC_CACHE_CHECK([whether _mno_explicit_relocs works],
[grub_cv_cc_mno_explicit_relocs], [
+ CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
- [grub_cv_cc_mla_global_with_abs=yes],
- [grub_cv_cc_mla_global_with_abs=no])
+ [grub_cv_cc_mno_explicit_relocs=yes],
+ [grub_cv_cc_mno_explicit_relocs=no])
])
-
- if test "x$grub_cv_cc_mla_global_with_abs" = xyes; then
- TARGET_CFLAGS="$TARGET_CFLAGS -Wa,-mla-global-with-abs"
- TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs"
+ if test "x$grub_cv_cc_mno_explicit_relocs" = xyes; then
+ TARGET_CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -fno-plt"
+ TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mno-explicit-relocs -fno-plt"
fi
+ TARGET_CFLAGS="$TARGET_CFLAGS -Wa,-mla-global-with-abs"
+ TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs"
fi
# GRUB doesn't use float or doubles at all. Yet some toolchains may decide
diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c
index 3a6aa91cd..47196a219 100644
--- a/grub-core/kern/loongarch64/dl.c
+++ b/grub-core/kern/loongarch64/dl.c
@@ -58,7 +58,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
{
Elf_Sym *sym;
- grub_uint64_t *place;
+ void *place;
grub_uint64_t sym_addr;
if (rel->r_offset >= seg->size)
@@ -72,12 +72,19 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
if (s->sh_type == SHT_RELA)
sym_addr += ((Elf_Rela *) rel)->r_addend;
- place = (grub_uint64_t *) ((grub_addr_t)seg->addr + rel->r_offset);
+ place = (void *) ((grub_addr_t)seg->addr + rel->r_offset);
switch (ELF_R_TYPE (rel->r_info))
{
case R_LARCH_64:
- *place = sym_addr;
+ {
+ grub_uint64_t *abs_place = place;
+
+ grub_dprintf ("dl", "reloc_abs64 %p => 0x%016llx, %p\n",
+ place, (unsigned long long) sym_addr, abs_place);
+
+ *abs_place += (grub_uint64_t) sym_addr;
+ }
break;
case R_LARCH_MARK_LA:
break;
@@ -85,6 +92,47 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case R_LARCH_SOP_PUSH_PLT_PCREL:
grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place);
break;
+ case R_LARCH_B26:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_ssize_t off = sym_addr - (grub_addr_t) place;
+
+ grub_loongarch64_b26 (abs_place, off);
+ }
+ break;
+ case R_LARCH_ABS_HI20:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_loongarch64_xxx_hi20 (abs_place, sym_addr);
+ }
+ break;
+ case R_LARCH_ABS64_LO20:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_loongarch64_xxx64_lo20 (abs_place, sym_addr);
+ }
+ break;
+ case R_LARCH_ABS64_HI12:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_loongarch64_xxx64_hi12 (abs_place, sym_addr);
+ }
+ break;
+ case R_LARCH_PCALA_HI20:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_int32_t off = (((sym_addr + 0x800) & ~0xfffULL) -
((grub_addr_t)place & ~0xfffULL));
+
+ grub_loongarch64_xxx_hi20 (abs_place, off);
+ }
+ break;
+ case R_LARCH_ABS_LO12:
+ case R_LARCH_PCALA_LO12:
+ {
+ grub_uint32_t *abs_place = place;
+ grub_loongarch64_xxx_lo12 (abs_place, sym_addr);
+ }
+ break;
GRUB_LOONGARCH64_RELOCATION (&stack, place, sym_addr)
default:
{
diff --git a/grub-core/kern/loongarch64/dl_helper.c
b/grub-core/kern/loongarch64/dl_helper.c
index 627d1fff2..c15cd739f 100644
--- a/grub-core/kern/loongarch64/dl_helper.c
+++ b/grub-core/kern/loongarch64/dl_helper.c
@@ -200,3 +200,62 @@ grub_loongarch64_sop_32_s_0_10_10_16_s2
(grub_loongarch64_stack_t stack,
*place =(*place) | (((a >> 2) & 0xffff) << 10);
*place =(*place) | ((a >> 18) & 0x3ff);
}
+
+void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset)
+{
+ grub_uint32_t val;
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc000000);
+
+ grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%llx\n",
+ place, offset > 0 ? '+' : '-',
+ offset < 0 ? (long long) -(unsigned long long) offset : offset);
+
+ val = ((offset >> 18) & 0x3ff) | (((offset >> 2) & 0xffff) << 10);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
+void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f);
+ grub_uint32_t val;
+
+ offset >>= 12;
+ val = ((offset & 0xfffff) << 5);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
+void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (offset << 10) & ~insmask;
+}
+
+void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
+ grub_uint32_t val;
+
+ offset >>= 52;
+ val = ((offset & 0xfff) << 10);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
+void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset)
+{
+ const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f);
+ grub_uint32_t val;
+
+ offset >>= 32;
+ val = ((offset & 0xfffff) << 5);
+
+ *place &= insmask;
+ *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
diff --git a/include/grub/elf.h b/include/grub/elf.h
index beef94512..b2fda0d35 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -2558,6 +2558,13 @@ 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_B26 66
+#define R_LARCH_ABS_HI20 67
+#define R_LARCH_ABS_LO12 68
+#define R_LARCH_ABS64_LO20 69
+#define R_LARCH_ABS64_HI12 70
+#define R_LARCH_PCALA_HI20 71
+#define R_LARCH_PCALA_LO12 72
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 0b7d66ddc..2106ba22c 100644
--- a/include/grub/loongarch64/reloc.h
+++ b/include/grub/loongarch64/reloc.h
@@ -57,6 +57,12 @@ 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_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);
+void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset);
+void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset);
+
#define GRUB_LOONGARCH64_RELOCATION(STACK, PLACE, OFFSET) \
case R_LARCH_SOP_PUSH_ABSOLUTE: \
grub_loongarch64_sop_push (STACK, OFFSET); \
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 358b9ab47..baf3a472d 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -1128,11 +1128,20 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct
section_metadata *smd,
}
case EM_LOONGARCH:
{
+ grub_int64_t pc;
+
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
sym_addr += addend;
+
+ pc = offset + target_section_addr + image_target->vaddr_offset;
+
switch (ELF_R_TYPE (info))
{
case R_LARCH_64:
- *target = grub_host_to_target64 (grub_target_to_host64
(*target) + sym_addr);
+ {
+ grub_uint64_t *t64 = (grub_uint64_t *) target;
+ *t64 = grub_host_to_target64 (grub_target_to_host64
(*t64) + sym_addr);
+ }
break;
case R_LARCH_MARK_LA:
break;
@@ -1143,6 +1152,37 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct
section_metadata *smd,
+offset
+image_target->vaddr_offset));
break;
+ case R_LARCH_B26:
+ {
+ grub_int64_t off;
+
+ off = sym_addr - target_section_addr - offset -
image_target->vaddr_offset;
+
+ grub_loongarch64_b26 (t32, off);
+ }
+ break;
+ case R_LARCH_ABS_HI20:
+ grub_loongarch64_xxx_hi20 (t32, sym_addr);
+ break;
+ case R_LARCH_ABS64_LO20:
+ grub_loongarch64_xxx64_lo20 (t32, sym_addr);
+ break;
+ case R_LARCH_ABS64_HI12:
+ grub_loongarch64_xxx64_hi12 (t32, sym_addr);
+ break;
+ case R_LARCH_PCALA_HI20:
+ {
+ grub_int32_t hi20;
+
+ hi20 = (((sym_addr + 0x800) & ~0xfffULL) - (pc &
~0xfffULL));
+
+ grub_loongarch64_xxx_hi20 (t32, hi20);
+ }
+ break;
+ case R_LARCH_ABS_LO12:
+ case R_LARCH_PCALA_LO12:
+ grub_loongarch64_xxx_lo12 (t32, sym_addr);
+ break;
GRUB_LOONGARCH64_RELOCATION (&stack, target, sym_addr)
default:
grub_util_error (_("relocation 0x%x is not implemented
yet"),
@@ -1736,6 +1776,13 @@ 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_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:
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 b510461fa..91d9e8f88 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -140,6 +140,13 @@ 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_B26,
+ R_LARCH_ABS_HI20,
+ R_LARCH_ABS_LO12,
+ R_LARCH_ABS64_LO20,
+ R_LARCH_ABS64_HI12,
+ R_LARCH_PCALA_HI20,
+ R_LARCH_PCALA_LO12,
-1
}, (int[]){
-1
--
2.35.1
- [PATCH v11 00/11] Add support for LoongArch, Xiaotian Wu, 2022/09/02
- [PATCH v11 02/11] Add LoongArch definitions, Xiaotian Wu, 2022/09/02
- [PATCH v11 01/11] PE: Add LoongArch definitions, Xiaotian Wu, 2022/09/02
- [PATCH v11 03/11] LoongArch: Add setjmp implementation, Xiaotian Wu, 2022/09/02
- [PATCH v11 04/11] LoongArch: Add early startup code, Xiaotian Wu, 2022/09/02
- [PATCH v11 05/11] LoongArch: Add stubs for Linux loading commands, Xiaotian Wu, 2022/09/02
- [PATCH v11 06/11] LoongArch: Add awareness for LoongArch relocations, Xiaotian Wu, 2022/09/02
- [PATCH v11 07/11] LoongArch: Add auxiliary files, Xiaotian Wu, 2022/09/02
- [PATCH v11 08/11] LoongArch: Add to build system, Xiaotian Wu, 2022/09/02
- [PATCH v11 09/11] LoongArch: Support new relocation types in v2.00 ABI,
Xiaotian Wu <=
- [PATCH v11 11/11] tests: add support for LoongArch, Xiaotian Wu, 2022/09/02
- [PATCH v11 10/11] LoongArch: add efistub kernel support, Xiaotian Wu, 2022/09/02
- Re: [PATCH v11 00/11] Add support for LoongArch, Xiaotian Wu, 2022/09/19