[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v1 1/1] loongarch: add relaxation support
From: |
Xiaotian Wu |
Subject: |
[PATCH v1 1/1] loongarch: add relaxation support |
Date: |
Tue, 6 Jun 2023 10:34:06 +0800 |
Add R_LARCH_B16, R_LARCH_B21 and R_LARCH_RELAX relocation types to support
LoongArch relaxation.
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=56576f4a722b7398d35802ecf7d4185c27d6d69b
https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#relocations
Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn>
---
grub-core/kern/loongarch64/dl.c | 21 +++++++-
grub-core/kern/loongarch64/dl_helper.c | 72 ++++++++++++++++++++++++--
include/grub/elf.h | 3 ++
include/grub/loongarch64/reloc.h | 6 ++-
util/grub-mkimagexx.c | 28 ++++++++--
util/grub-module-verifier.c | 3 ++
6 files changed, 122 insertions(+), 11 deletions(-)
diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c
index 43080e72e..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;
@@ -109,13 +126,13 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case R_LARCH_ABS64_LO20:
{
grub_uint32_t *abs_place = place;
- grub_loongarch64_xxx64_lo20 (abs_place, sym_addr);
+ grub_loongarch64_abs64_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);
+ grub_loongarch64_abs64_hi12 (abs_place, sym_addr);
}
break;
case R_LARCH_PCALA_HI20:
diff --git a/grub-core/kern/loongarch64/dl_helper.c
b/grub-core/kern/loongarch64/dl_helper.c
index cda1a53c8..2809eeb7f 100644
--- a/grub-core/kern/loongarch64/dl_helper.c
+++ b/grub-core/kern/loongarch64/dl_helper.c
@@ -24,6 +24,10 @@
#include <grub/i18n.h>
#include <grub/loongarch64/reloc.h>
+/*
+ * LoongArch relocations documentation:
+ * https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#relocations
+ */
static void grub_loongarch64_stack_push (grub_loongarch64_stack_t stack,
grub_uint64_t x);
static grub_uint64_t grub_loongarch64_stack_pop (grub_loongarch64_stack_t
stack);
@@ -200,14 +204,58 @@ 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 ? (grub_int64_t) -(grub_uint64_t) 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 ? (grub_int64_t) -(grub_uint64_t) 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]
+ * (*(uint32_t *) PC) [25 ... 10] = (S+A-PC) [17 ... 2]
+ */
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",
+ grub_dprintf ("dl", " reloc_b26 %p %c= 0x%"PRIxGRUB_INT64_T"\n",
place, offset > 0 ? '+' : '-',
- offset < 0 ? (long long) -(unsigned long long) offset : offset);
+ offset < 0 ? (grub_int64_t) -(grub_uint64_t) offset : offset);
val = ((offset >> 18) & 0x3ff) | (((offset >> 2) & 0xffff) << 10);
@@ -215,6 +263,10 @@ void grub_loongarch64_b26 (grub_uint32_t *place,
grub_int64_t offset)
*place |= grub_cpu_to_le32 (val) & ~insmask;
}
+/*
+ * ABS_HI20/PCALA_HI20 relocations for 32/64-bit absolute address/PC-relative
offset
+ * (*(uint32_t *) PC) [24 ... 5] = (S+A) [31 ... 12]
+ */
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);
@@ -227,6 +279,10 @@ void grub_loongarch64_xxx_hi20 (grub_uint32_t *place,
grub_int64_t offset)
*place |= grub_cpu_to_le32 (val) & ~insmask;
}
+/*
+ * ABS_LO12/PCALA_LO12 relocations for 32/64-bit absolute address
+ * (*(uint32_t *) PC) [21 ... 10] = (S+A) [11 ... 0]
+ */
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);
@@ -235,7 +291,11 @@ void grub_loongarch64_xxx_lo12 (grub_uint32_t *place,
grub_int64_t offset)
*place |= grub_cpu_to_le32 (offset << 10) & ~insmask;
}
-void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset)
+/*
+ * ABS64_HI12 relocation for the 64-bit absolute address
+ * (*(uint32_t *) PC) [21 ... 10] = (S+A) [63 ... 52]
+ */
+void grub_loongarch64_abs64_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;
@@ -247,7 +307,11 @@ void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place,
grub_int64_t offset)
*place |= grub_cpu_to_le32 (val) & ~insmask;
}
-void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset)
+/*
+ * ABS64_LO20 relocation for the 64-bit absolute address
+ * (*(uint32_t *) PC) [24 ... 5] = (S+A) [51 ... 32]
+ */
+void grub_loongarch64_abs64_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;
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 dec7a6b36..01d4f6831 100644
--- a/include/grub/loongarch64/reloc.h
+++ b/include/grub/loongarch64/reloc.h
@@ -57,11 +57,13 @@ 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);
-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);
+void grub_loongarch64_abs64_hi12 (grub_uint32_t *place, grub_int64_t offset);
+void grub_loongarch64_abs64_lo20 (grub_uint32_t *place, grub_int64_t offset);
#define GRUB_LOONGARCH64_RELOCATION(STACK, PLACE, OFFSET) \
case R_LARCH_SOP_PUSH_ABSOLUTE: \
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index e7d5bc631..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,11 +1153,29 @@ 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;
- off = sym_addr - target_section_addr - offset -
image_target->vaddr_offset;
+ off = sym_addr - pc;
grub_loongarch64_b26 (t32, off);
}
@@ -1165,10 +1184,10 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct
section_metadata *smd,
grub_loongarch64_xxx_hi20 (t32, sym_addr);
break;
case R_LARCH_ABS64_LO20:
- grub_loongarch64_xxx64_lo20 (t32, sym_addr);
+ grub_loongarch64_abs64_lo20 (t32, sym_addr);
break;
case R_LARCH_ABS64_HI12:
- grub_loongarch64_xxx64_hi12 (t32, sym_addr);
+ grub_loongarch64_abs64_hi12 (t32, sym_addr);
break;
case R_LARCH_PCALA_HI20:
{
@@ -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.40.1