1From 1dea576eac4289602adc4a37f48c80330bf82e63 Mon Sep 17 00:00:00 2001 2From: Damien Le Moal <damien.lemoal@wdc.com> 3Date: Wed, 9 Sep 2020 17:31:33 +0900 4Subject: [PATCH] elf2flt: add riscv 64-bits support 5 6Add support for riscv 64bits ISA by defining the relocation types 7R_RISCV_32_PCREL, R_RISCV_ADD32, R_RISCV_SUB32, R_RISCV_32 and 8R_RISCV_64. riscv64 support also needs the __global_pointer$ symbol to 9be defined right after the relocation tables in the data section. 10Furthermore, the .got and .got.plt sections must be reversed. These 2 11requirements are handled with runtime modifications of the default 12linker script using the append_sed() function. 13(1) For the .got.plt and .got sections order swap, append_sed() is used 14to rename "(.got.plt)" to "(.got.tmp)" and to rename "(.got)" to 15"(.got.plt)". A last call finalize the name swap by replacing 16"(.got.tmp)" with "(.got)" 17(2) For the global pointer synbol, a definition line starting with 18"RISCV_GP" is added. The "RISCV_GP" string is removed if the target CPU 19type is riscv64. The definition line is dropped for other CPU types. 20 21With these changes, buildroot/busybox builds and run on NOMMU 22systems with kernel 5.13. Tested on Canaan Kendryte K210 boards. 23 24This patch is based on earlier work by Christoph Hellwig <hch@lst.de>. 25 26Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> 27--- 28 elf2flt.c | 23 +++++++++++++++++++++++ 29 elf2flt.ld.in | 9 +++++---- 30 ld-elf2flt.c | 16 ++++++++++++++++ 31 3 files changed, 44 insertions(+), 4 deletions(-) 32 33diff --git a/elf2flt.c b/elf2flt.c 34index f87f1fc..dbce467 100644 35--- a/elf2flt.c 36+++ b/elf2flt.c 37@@ -80,6 +80,8 @@ const char *elf2flt_progname; 38 #include <elf/v850.h> 39 #elif defined(TARGET_xtensa) 40 #include <elf/xtensa.h> 41+#elif defined(TARGET_riscv64) 42+#include <elf/riscv.h> 43 #endif 44 45 #if defined(__MINGW32__) 46@@ -122,6 +124,8 @@ const char *elf2flt_progname; 47 #define ARCH "nios2" 48 #elif defined(TARGET_xtensa) 49 #define ARCH "xtensa" 50+#elif defined(TARGET_riscv64) 51+#define ARCH "riscv64" 52 #else 53 #error "Don't know how to support your CPU architecture??" 54 #endif 55@@ -797,6 +801,16 @@ output_relocs ( 56 goto good_32bit_resolved_reloc; 57 default: 58 goto bad_resolved_reloc; 59+#elif defined(TARGET_riscv64) 60+ case R_RISCV_32_PCREL: 61+ case R_RISCV_ADD32: 62+ case R_RISCV_SUB32: 63+ continue; 64+ case R_RISCV_32: 65+ case R_RISCV_64: 66+ goto good_32bit_resolved_reloc; 67+ default: 68+ goto bad_resolved_reloc; 69 #else 70 default: 71 /* The default is to assume that the 72@@ -1806,6 +1820,15 @@ int main(int argc, char *argv[]) 73 if (!load_to_ram && !pfile) 74 load_to_ram = 1; 75 76+#if defined(TARGET_riscv64) 77+ /* 78+ * riscv only supports loading text and data contiguously. 79+ * So fail if load_to_ram is false. 80+ */ 81+ if (!load_to_ram) 82+ fatal("Loading to RAM ('-r' option) is required"); 83+#endif 84+ 85 fname = argv[argc-1]; 86 87 if (pfile) { 88diff --git a/elf2flt.ld.in b/elf2flt.ld.in 89index ec1fe6f..c0c44b8 100644 90--- a/elf2flt.ld.in 91+++ b/elf2flt.ld.in 92@@ -70,10 +70,11 @@ W_RODAT *(.gnu.linkonce.r*) 93 . = ALIGN(0x20) ; 94 LONG(-1) 95 . = ALIGN(0x20) ; 96-R_RODAT *(.rodata) 97-R_RODAT *(.rodata1) 98-R_RODAT *(.rodata.*) 99-R_RODAT *(.gnu.linkonce.r*) 100+RISCV_GP: __global_pointer$ = . + 0x800 ; 101+R_RODAT *(.rodata) 102+R_RODAT *(.rodata1) 103+R_RODAT *(.rodata.*) 104+R_RODAT *(.gnu.linkonce.r*) 105 *(.data) 106 *(.data1) 107 *(.data.*) 108diff --git a/ld-elf2flt.c b/ld-elf2flt.c 109index e5de506..31b565f 100644 110--- a/ld-elf2flt.c 111+++ b/ld-elf2flt.c 112@@ -324,6 +324,22 @@ static int do_final_link(void) 113 append_option(&other_options, concat(got_offset, "=", buf, NULL)); 114 } 115 116+ if (streq(TARGET_CPU, "riscv64")) { 117+ /* 118+ * The .got section must come before the .got.plt section 119+ * (gcc/ld bug ?). 120+ */ 121+ append_sed(&sed, "(.got.plt)", "(.got.tmp)"); 122+ append_sed(&sed, "(.got.plt)", "(.got)"); 123+ append_sed(&sed, "(.got.tmp)", "(.got.plt)"); 124+ 125+ /* The global pointer symbol is defined after the GOT. */ 126+ append_sed(&sed, "^RISCV_GP:", ""); 127+ } else { 128+ /* Get rid of the global pointer definition. */ 129+ append_sed(&sed, "^RISCV_GP:", NULL); 130+ } 131+ 132 /* Locate the default linker script, if we don't have one provided. */ 133 if (!linker_script) 134 linker_script = concat(ldscriptpath, "/elf2flt.ld", NULL); 135-- 1362.31.1 137 138