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