From a0935f0aadf1d2ea1fbafc582d7bca1774b2f430 Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Fri, 20 Oct 2023 16:14:01 +0200 Subject: [PATCH] ELF: added support for SHT_RISCV_ATTRIBUTES seg --- src/bootloader/elf/elf.c | 168 ++++++++++++++++++++------------------- src/bootloader/elf/elf.h | 1 + 2 files changed, 87 insertions(+), 82 deletions(-) diff --git a/src/bootloader/elf/elf.c b/src/bootloader/elf/elf.c index 1d72f7e..0052368 100644 --- a/src/bootloader/elf/elf.c +++ b/src/bootloader/elf/elf.c @@ -8,94 +8,98 @@ uint32_t elf_32_load(void* file) { - // Parse/verify the header - elf_header_32_t* header = file; + // Parse/verify the header + elf_header_32_t* header = file; - // Verify magic number - uint8_t* m = header->ELF; - if((m[0] != 0x7F) || (m[1] != 'E') || (m[2] != 'L') || (m[3] != 'F')) - { - fprintf(stderr, "Not a valid ELF file (wrong magic)\n"); - exit(EXIT_FAILURE); - } + // Verify magic number + uint8_t* m = header->ELF; + if((m[0] != 0x7F) || (m[1] != 'E') || (m[2] != 'L') || (m[3] != 'F')) + { + fprintf(stderr, "Not a valid ELF file (wrong magic)\n"); + exit(EXIT_FAILURE); + } - // Verify architecture - if(header->instruction_set != INSTRUCTION_SET_RISCV) - { - switch(header->instruction_set) - { - case INSTRUCTION_SET_X86: - fprintf(stderr, "Provided ELF file targets x86 ; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); - break; - case INSTRUCTION_SET_X86_64: - fprintf(stderr, "Provided ELF file targets x86_64; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); - break; - default: - fprintf(stderr, "Provided ELF file is for an unknown instruction set architecture (0x%x), please provide a RISC-V ELF\n", header->instruction_set); - break; - } - exit(EXIT_FAILURE); - } + // Verify architecture + if(header->instruction_set != INSTRUCTION_SET_RISCV) + { + switch(header->instruction_set) + { + case INSTRUCTION_SET_X86: + fprintf(stderr, "Provided ELF file targets x86 ; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); + break; + case INSTRUCTION_SET_X86_64: + fprintf(stderr, "Provided ELF file targets x86_64; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); + break; + default: + fprintf(stderr, "Provided ELF file is for an unknown instruction set architecture (0x%x), please provide a RISC-V ELF\n", header->instruction_set); + break; + } + exit(EXIT_FAILURE); + } - // Verify bit count - if(header->bits != BITS_32) - { - switch(header->bits) - { - case BITS_64: - fprintf(stderr, "Provided ELF file targets RISC-V 64 bits ; please provide a 32-bits ELF\n"); - break; - default: - fprintf(stderr, "Provided ELF file targets an unknown bit count (not 32 bits) ; please provide a 32-bits ELF\n"); - break; - } - exit(EXIT_FAILURE); - } + // Verify bit count + if(header->bits != BITS_32) + { + switch(header->bits) + { + case BITS_64: + fprintf(stderr, "Provided ELF file targets RISC-V 64 bits ; please provide a 32-bits ELF\n"); + break; + default: + fprintf(stderr, "Provided ELF file targets an unknown bit count (not 32 bits) ; please provide a 32-bits ELF\n"); + break; + } + exit(EXIT_FAILURE); + } - // Verify endianness - if(header->endianness != ELF_LITTLE_ENDIAN) - { - fprintf(stderr, "Provided ELF file is encoded in big endian ; please provide a little endian ELF\n"); - exit(EXIT_FAILURE); - } + // Verify endianness + if(header->endianness != ELF_LITTLE_ENDIAN) + { + fprintf(stderr, "Provided ELF file is encoded in big endian ; please provide a little endian ELF\n"); + exit(EXIT_FAILURE); + } - // File should be correct ; now load it, using program header table - elf_program_header_32_t* program_header = (elf_program_header_32_t*) (((uint8_t*) file) + header->program_header_table_32); - size_t program_header_count = header->program_entry_amount; - for(size_t i = 0; i < program_header_count; i++) - { - elf_program_header_32_t current = program_header[i]; - - // Check segment type - if(current.segment_type != SEGMENT_TYPE_LOAD) - { - fprintf(stderr, "WARNING: Unknown segment type %u in ELF file ; skipping\n", current.segment_type); - continue; - } + // File should be correct ; now load it, using program header table + elf_program_header_32_t* program_header = (elf_program_header_32_t*) (((uint8_t*) file) + header->program_header_table_32); + size_t program_header_count = header->program_entry_amount; + for(size_t i = 0; i < program_header_count; i++) + { + elf_program_header_32_t current = program_header[i]; - // Check memory size - size_t memsz = current.segment_memory_size; - if(!memsz) - { - fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n"); - continue; - } + // Check segment type + if(current.segment_type != SEGMENT_TYPE_LOAD) + { + // Don't message for riscv-specific attributes segment + if(current.segment_type != SEGMENT_TYPE_RISCV_SPECIFIC_SHT_RISCV_ATTRIBUTES) + { + fprintf(stderr, "WARNING: Unknown segment type %u in ELF file ; skipping\n", current.segment_type); + } + continue; + } - // Map the segment : first the part in the file, then the zeros - if(memory_size < (current.virtual_address + memsz)) - { - fprintf(stderr, "FATAL: Not enough memory while loading ELF file\n"); - exit(EXIT_FAILURE); - } - if(current.segment_file_size != 0) - { - memcpy(&memory[current.virtual_address], ((uint8_t*) file) + current.segment_offset, current.segment_file_size); - } - if(memsz > current.segment_file_size) - { - memset(&memory[current.virtual_address] + current.segment_file_size, 0, memsz - current.segment_file_size); - } - } + // Check memory size + size_t memsz = current.segment_memory_size; + if(!memsz) + { + fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n"); + continue; + } - return header->entry_32; + // Map the segment : first the part in the file, then the zeros + if(memory_size < (current.virtual_address + memsz)) + { + fprintf(stderr, "FATAL: Not enough memory while loading ELF file\n"); + exit(EXIT_FAILURE); + } + if(current.segment_file_size != 0) + { + memcpy(&memory[current.virtual_address], ((uint8_t*) file) + current.segment_offset, current.segment_file_size); + } + if(memsz > current.segment_file_size) + { + memset(&memory[current.virtual_address] + current.segment_file_size, 0, memsz - current.segment_file_size); + } + } + + return header->entry_32; } diff --git a/src/bootloader/elf/elf.h b/src/bootloader/elf/elf.h index 070fa2c..16fa2a3 100644 --- a/src/bootloader/elf/elf.h +++ b/src/bootloader/elf/elf.h @@ -77,6 +77,7 @@ typedef struct ELF_PROGRAM_HEADER_32 #define SEGMENT_TYPE_DYNAMIC 2 #define SEGMENT_TYPE_INTERP 3 #define SEGMENT_TYPE_NOTE 4 +#define SEGMENT_TYPE_RISCV_SPECIFIC_SHT_RISCV_ATTRIBUTES 0x70000003 uint32_t elf_32_load(void* file);