[U-Boot] [PATCH] riscv: tools: Handle addend to absolute reloc in prelink-riscv

Marcus Comstedt marcus at mc.pp.se
Sun Aug 11 09:29:57 UTC 2019

Previously the handling of R_RISCV_32 and R_RISCV_64 would simply
insert the value of the symbol and ignore any addend.  However, there
exist relocs where the addend is non-zero:

0000000080250900 R_RISCV_64        efi_runtime_services+0x0000000000000068
0000000080250910 R_RISCV_64        efi_runtime_services+0x0000000000000038
0000000080250920 R_RISCV_64        efi_runtime_services+0x0000000000000018
0000000080250930 R_RISCV_64        efi_runtime_services+0x0000000000000020
0000000080250980 R_RISCV_64        efi_runtime_services+0x0000000000000048
0000000080250990 R_RISCV_64        efi_runtime_services+0x0000000000000050
00000000802509a0 R_RISCV_64        efi_runtime_services+0x0000000000000058
0000000080250940 R_RISCV_64        systab+0x0000000000000030
0000000080250950 R_RISCV_64        systab+0x0000000000000040
0000000080250960 R_RISCV_64        systab+0x0000000000000050
0000000080250970 R_RISCV_64        systab+0x0000000000000060

In these cases the addend needs to be added to the symbol value to get
the correct value for the reloc.

Signed-off-by: Marcus Comstedt <marcus at mc.pp.se>
Cc: Rick Chen <rick at andestech.com>
Note:  This patch applies on top of the previous endianness patches.

While the bug is orthogonal to the endianness changes and indeed
existed before them, additional byteswaps are needed to perform the
actual arithmetic, which makes the changes interdependent.  Also, the
endianness fixes are already on the custodian branch, so it should be
easier to merge this way.

Currently only the EFI runtime is affected by this bug, which is
probably why it was not noticed earlier.

 tools/prelink-riscv.inc | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/prelink-riscv.inc b/tools/prelink-riscv.inc
index 8b40ec430a..f2b5467f5b 100644
--- a/tools/prelink-riscv.inc
+++ b/tools/prelink-riscv.inc
@@ -27,6 +27,8 @@
 #define target32_to_cpu CONCAT(PRELINK_BYTEORDER, 32_to_cpu)
 #define target64_to_cpu CONCAT(PRELINK_BYTEORDER, 64_to_cpu)
 #define targetnn_to_cpu CONCAT3(PRELINK_BYTEORDER, PRELINK_INC_BITS, _to_cpu)
+#define cpu_to_target32 CONCAT3(cpu_to_, PRELINK_BYTEORDER, 32)
+#define cpu_to_target64 CONCAT3(cpu_to_, PRELINK_BYTEORDER, 64)
 static void* get_offset_bonn (void* data, Elf_Phdr* phdrs, size_t phnum, Elf_Addr addr)
@@ -92,9 +94,9 @@ static void prelink_bonn(void *data)
 		if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_RELATIVE)
 			*((uintnn_t*) buf) = r->r_addend;
 		else if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_32)
-			*((uint32_t*) buf) = dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value;
+			*((uint32_t*) buf) = cpu_to_target32(targetnn_to_cpu(dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value) + targetnn_to_cpu(r->r_addend));
 		else if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_64)
-			*((uint64_t*) buf) = dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value;
+			*((uint64_t*) buf) = cpu_to_target64(targetnn_to_cpu(dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value) + targetnn_to_cpu(r->r_addend));
@@ -113,6 +115,8 @@ static void prelink_bonn(void *data)
 #undef target32_to_cpu
 #undef target64_to_cpu
 #undef targetnn_to_cpu
+#undef cpu_to_target32
+#undef cpu_to_target64
 #undef CONCAT

More information about the U-Boot mailing list