From b4cabde4a4fec129378988987e14b7148c074c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Fri, 13 Oct 2023 20:10:33 +0200 Subject: [PATCH] LibELF: Add initial RISC-V support This is an almost-minimal patchset to get RISC-V ELF files to pass validation. Unlike other architectures, eflags are actually used here. --- Userland/Libraries/LibELF/ELFABI.h | 12 ++++++++++++ Userland/Libraries/LibELF/Validation.cpp | 22 +++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibELF/ELFABI.h b/Userland/Libraries/LibELF/ELFABI.h index 1f54afe89f..2372d6587e 100644 --- a/Userland/Libraries/LibELF/ELFABI.h +++ b/Userland/Libraries/LibELF/ELFABI.h @@ -204,6 +204,7 @@ typedef struct { #define EM_X86_64 EM_AMD64 #define EM_VAX 75 /* DEC VAX */ #define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */ +#define EM_RISCV 243 /* RISC-V */ /* Non-standard */ #define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */ @@ -219,6 +220,17 @@ typedef struct { /* Magic for e_phnum: get real value from sh_info of first section header */ #define PN_XNUM 0xffff +/* RISC-V specific e_flags */ +/* See: RISC-V ABI Specification 1.0, Section 8.1: File Header */ +#define EF_RISCV_RVC 0x0001 /* Binary targets the Compressed ABI */ +#define EF_RISCV_FLOAT_ABI_SOFT 0x0000 /* No hardware float ABI in use */ +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002 /* 32-bit hardware float ABI */ +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004 /* 64-bit hardware float ABI */ +#define EF_RISCV_FLOAT_ABI_QUAD 0x0006 /* 128-bit hardware float ABI */ +#define EF_RISCV_FLOAT_ABI 0x0006 /* Test mask for float ABIs */ +#define EF_RISCV_RVE 0x0008 /* Binary targets the Embedded ABI */ +#define EF_RISCV_TSO 0x0010 /* Binary requires Ztso extension */ + /* Section Header */ typedef struct { Elf32_Word sh_name; /* name - index into section header diff --git a/Userland/Libraries/LibELF/Validation.cpp b/Userland/Libraries/LibELF/Validation.cpp index 2d898678c6..8ccb39b3dc 100644 --- a/Userland/Libraries/LibELF/Validation.cpp +++ b/Userland/Libraries/LibELF/Validation.cpp @@ -59,8 +59,8 @@ bool validate_elf_header(ElfW(Ehdr) const& elf_header, size_t file_size, bool ve return false; } - auto expected_machines = Array { EM_X86_64, EM_AARCH64 }; - auto expected_machine_names = Array { "x86-64"sv, "aarch64"sv }; + auto expected_machines = Array { EM_X86_64, EM_AARCH64, EM_RISCV }; + auto expected_machine_names = Array { "x86-64"sv, "aarch64"sv, "riscv64"sv }; if (!expected_machines.span().contains_slow(elf_header.e_machine)) { if (verbose) @@ -117,9 +117,21 @@ bool validate_elf_header(ElfW(Ehdr) const& elf_header, size_t file_size, bool ve } if (0 != elf_header.e_flags) { - if (verbose) - dbgln("File has incorrect ELF header flags...? ({}), expected ({}).", elf_header.e_flags, 0); - return false; + // TODO: Refuse to run C ABI binaries on system without the C extension. + // TODO: Refuse to run TSO ABI binaries on system without the Ztso extension. + if (elf_header.e_machine == EM_RISCV) { + auto float_abi = elf_header.e_flags & EF_RISCV_FLOAT_ABI; + // TODO: Support 32-bit hardware float ABI somehow? + if (float_abi != EF_RISCV_FLOAT_ABI_DOUBLE) { + if (verbose) + dbgln("File has unsupported float ABI ({}), only double ({}) is supported.", float_abi, EF_RISCV_FLOAT_ABI_DOUBLE); + return false; + } + } else { + if (verbose) + dbgln("File has incorrect ELF header flags...? ({}), expected ({}).", elf_header.e_flags, 0); + return false; + } } if (0 != elf_header.e_phnum && sizeof(ElfW(Phdr)) != elf_header.e_phentsize) {