From 4539926a9c47638951f29f550f3a640e4c223032 Mon Sep 17 00:00:00 2001 From: Marcus Comstedt Date: Fri, 2 Aug 2019 19:45:16 +0200 Subject: [PATCH] riscv: tools: Add big endian target support to prelink-riscv Signed-off-by: Marcus Comstedt Cc: Rick Chen Reviewed-by: Rick Chen --- tools/prelink-riscv.c | 32 ++++++++++++++++++--- tools/prelink-riscv.inc | 62 ++++++++++++++++++++++------------------- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/tools/prelink-riscv.c b/tools/prelink-riscv.c index a900a1497a..b0467949eb 100644 --- a/tools/prelink-riscv.c +++ b/tools/prelink-riscv.c @@ -47,12 +47,28 @@ const char *argv0; exit(EXIT_FAILURE); \ } while (0) +#define PRELINK_BYTEORDER le #define PRELINK_INC_BITS 32 #include "prelink-riscv.inc" +#undef PRELINK_BYTEORDER #undef PRELINK_INC_BITS +#define PRELINK_BYTEORDER le #define PRELINK_INC_BITS 64 #include "prelink-riscv.inc" +#undef PRELINK_BYTEORDER +#undef PRELINK_INC_BITS + +#define PRELINK_BYTEORDER be +#define PRELINK_INC_BITS 32 +#include "prelink-riscv.inc" +#undef PRELINK_BYTEORDER +#undef PRELINK_INC_BITS + +#define PRELINK_BYTEORDER be +#define PRELINK_INC_BITS 64 +#include "prelink-riscv.inc" +#undef PRELINK_BYTEORDER #undef PRELINK_INC_BITS int main(int argc, const char *const *argv) @@ -88,11 +104,19 @@ int main(int argc, const char *const *argv) die("Invalid ELF file %s", argv[1]); bool is64 = e_ident[EI_CLASS] == ELFCLASS64; + bool isbe = e_ident[EI_DATA] == ELFDATA2MSB; - if (is64) - prelink64(data); - else - prelink32(data); + if (is64) { + if (isbe) + prelink_be64(data); + else + prelink_le64(data); + } else { + if (isbe) + prelink_be32(data); + else + prelink_le32(data); + } return 0; } diff --git a/tools/prelink-riscv.inc b/tools/prelink-riscv.inc index 86ce1aa93f..8b40ec430a 100644 --- a/tools/prelink-riscv.inc +++ b/tools/prelink-riscv.inc @@ -12,9 +12,9 @@ #define CONCAT(x, y) CONCAT_IMPL(x, y) #define CONCAT3(x, y, z) CONCAT(CONCAT(x, y), z) -#define prelink_nn CONCAT(prelink, PRELINK_INC_BITS) +#define prelink_bonn CONCAT3(prelink_, PRELINK_BYTEORDER, PRELINK_INC_BITS) #define uintnn_t CONCAT3(uint, PRELINK_INC_BITS, _t) -#define get_offset_nn CONCAT(get_offset_, PRELINK_INC_BITS) +#define get_offset_bonn CONCAT3(get_offset_, PRELINK_BYTEORDER, PRELINK_INC_BITS) #define Elf_Ehdr CONCAT3(Elf, PRELINK_INC_BITS, _Ehdr) #define Elf_Phdr CONCAT3(Elf, PRELINK_INC_BITS, _Phdr) #define Elf_Rela CONCAT3(Elf, PRELINK_INC_BITS, _Rela) @@ -23,35 +23,38 @@ #define Elf_Addr CONCAT3(Elf, PRELINK_INC_BITS, _Addr) #define ELF_R_TYPE CONCAT3(ELF, PRELINK_INC_BITS, _R_TYPE) #define ELF_R_SYM CONCAT3(ELF, PRELINK_INC_BITS, _R_SYM) -#define lenn_to_cpu CONCAT3(le, PRELINK_INC_BITS, _to_cpu) +#define target16_to_cpu CONCAT(PRELINK_BYTEORDER, 16_to_cpu) +#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) -static void* get_offset_nn (void* data, Elf_Phdr* phdrs, size_t phnum, Elf_Addr addr) +static void* get_offset_bonn (void* data, Elf_Phdr* phdrs, size_t phnum, Elf_Addr addr) { Elf_Phdr *p; for (p = phdrs; p < phdrs + phnum; ++p) - if (lenn_to_cpu(p->p_vaddr) <= addr && lenn_to_cpu(p->p_vaddr) + lenn_to_cpu(p->p_memsz) > addr) - return data + lenn_to_cpu(p->p_offset) + (addr - lenn_to_cpu(p->p_vaddr)); + if (targetnn_to_cpu(p->p_vaddr) <= addr && targetnn_to_cpu(p->p_vaddr) + targetnn_to_cpu(p->p_memsz) > addr) + return data + targetnn_to_cpu(p->p_offset) + (addr - targetnn_to_cpu(p->p_vaddr)); return NULL; } -static void prelink_nn(void *data) +static void prelink_bonn(void *data) { Elf_Ehdr *ehdr = data; Elf_Phdr *p; Elf_Dyn *dyn; Elf_Rela *r; - if (le16_to_cpu(ehdr->e_machine) != EM_RISCV) + if (target16_to_cpu(ehdr->e_machine) != EM_RISCV) die("Machine type is not RISC-V"); - Elf_Phdr *phdrs = data + lenn_to_cpu(ehdr->e_phoff); + Elf_Phdr *phdrs = data + targetnn_to_cpu(ehdr->e_phoff); Elf_Dyn *dyns = NULL; - for (p = phdrs; p < phdrs + le16_to_cpu(ehdr->e_phnum); ++p) { - if (le32_to_cpu(p->p_type) == PT_DYNAMIC) { - dyns = data + lenn_to_cpu(p->p_offset); + for (p = phdrs; p < phdrs + target16_to_cpu(ehdr->e_phnum); ++p) { + if (target32_to_cpu(p->p_type) == PT_DYNAMIC) { + dyns = data + targetnn_to_cpu(p->p_offset); break; } } @@ -63,14 +66,14 @@ static void prelink_nn(void *data) size_t rela_count = 0; Elf_Sym *dynsym = NULL; for (dyn = dyns;; ++dyn) { - if (lenn_to_cpu(dyn->d_tag) == DT_NULL) + if (targetnn_to_cpu(dyn->d_tag) == DT_NULL) break; - else if (lenn_to_cpu(dyn->d_tag) == DT_RELA) - rela_dyn = get_offset_nn(data, phdrs, le16_to_cpu(ehdr->e_phnum), + lenn_to_cpu(dyn->d_un.d_ptr)); - else if (lenn_to_cpu(dyn->d_tag) == DT_RELASZ) - rela_count = lenn_to_cpu(dyn->d_un.d_val) / sizeof(Elf_Rela); - else if (lenn_to_cpu(dyn->d_tag) == DT_SYMTAB) - dynsym = get_offset_nn(data, phdrs, le16_to_cpu(ehdr->e_phnum), + lenn_to_cpu(dyn->d_un.d_ptr)); + else if (targetnn_to_cpu(dyn->d_tag) == DT_RELA) + rela_dyn = get_offset_bonn(data, phdrs, target16_to_cpu(ehdr->e_phnum), + targetnn_to_cpu(dyn->d_un.d_ptr)); + else if (targetnn_to_cpu(dyn->d_tag) == DT_RELASZ) + rela_count = targetnn_to_cpu(dyn->d_un.d_val) / sizeof(Elf_Rela); + else if (targetnn_to_cpu(dyn->d_tag) == DT_SYMTAB) + dynsym = get_offset_bonn(data, phdrs, target16_to_cpu(ehdr->e_phnum), + targetnn_to_cpu(dyn->d_un.d_ptr)); } @@ -81,23 +84,23 @@ static void prelink_nn(void *data) die("No .dynsym found"); for (r = rela_dyn; r < rela_dyn + rela_count; ++r) { - void* buf = get_offset_nn(data, phdrs, le16_to_cpu(ehdr->e_phnum), lenn_to_cpu(r->r_offset)); + void* buf = get_offset_bonn(data, phdrs, target16_to_cpu(ehdr->e_phnum), targetnn_to_cpu(r->r_offset)); if (buf == NULL) continue; - if (ELF_R_TYPE(lenn_to_cpu(r->r_info)) == R_RISCV_RELATIVE) + if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_RELATIVE) *((uintnn_t*) buf) = r->r_addend; - else if (ELF_R_TYPE(lenn_to_cpu(r->r_info)) == R_RISCV_32) - *((uint32_t*) buf) = dynsym[ELF_R_SYM(lenn_to_cpu(r->r_info))].st_value; - else if (ELF_R_TYPE(lenn_to_cpu(r->r_info)) == R_RISCV_64) - *((uint64_t*) buf) = dynsym[ELF_R_SYM(lenn_to_cpu(r->r_info))].st_value; + 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; + 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; } } -#undef prelink_nn +#undef prelink_bonn #undef uintnn_t -#undef get_offset_nn +#undef get_offset_bonn #undef Elf_Ehdr #undef Elf_Phdr #undef Elf_Rela @@ -106,7 +109,10 @@ static void prelink_nn(void *data) #undef Elf_Addr #undef ELF_R_TYPE #undef ELF_R_SYM -#undef lenn_to_cpu +#undef target16_to_cpu +#undef target32_to_cpu +#undef target64_to_cpu +#undef targetnn_to_cpu #undef CONCAT_IMPL #undef CONCAT