|
|
@ -8,94 +8,98 @@ |
|
|
|
|
|
|
|
|
|
|
|
uint32_t elf_32_load(void* file) |
|
|
|
uint32_t elf_32_load(void* file) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Parse/verify the header
|
|
|
|
// Parse/verify the header
|
|
|
|
elf_header_32_t* header = file; |
|
|
|
elf_header_32_t* header = file; |
|
|
|
|
|
|
|
|
|
|
|
// Verify magic number
|
|
|
|
// Verify magic number
|
|
|
|
uint8_t* m = header->ELF; |
|
|
|
uint8_t* m = header->ELF; |
|
|
|
if((m[0] != 0x7F) || (m[1] != 'E') || (m[2] != 'L') || (m[3] != 'F')) |
|
|
|
if((m[0] != 0x7F) || (m[1] != 'E') || (m[2] != 'L') || (m[3] != 'F')) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fprintf(stderr, "Not a valid ELF file (wrong magic)\n"); |
|
|
|
fprintf(stderr, "Not a valid ELF file (wrong magic)\n"); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Verify architecture
|
|
|
|
// Verify architecture
|
|
|
|
if(header->instruction_set != INSTRUCTION_SET_RISCV) |
|
|
|
if(header->instruction_set != INSTRUCTION_SET_RISCV) |
|
|
|
{ |
|
|
|
{ |
|
|
|
switch(header->instruction_set) |
|
|
|
switch(header->instruction_set) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case INSTRUCTION_SET_X86: |
|
|
|
case INSTRUCTION_SET_X86: |
|
|
|
fprintf(stderr, "Provided ELF file targets x86 ; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); |
|
|
|
fprintf(stderr, "Provided ELF file targets x86 ; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case INSTRUCTION_SET_X86_64: |
|
|
|
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"); |
|
|
|
fprintf(stderr, "Provided ELF file targets x86_64; perhaps you forgot to cross-compile ? Please provide a RISC-V ELF\n"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
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); |
|
|
|
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; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Verify bit count
|
|
|
|
// Verify bit count
|
|
|
|
if(header->bits != BITS_32) |
|
|
|
if(header->bits != BITS_32) |
|
|
|
{ |
|
|
|
{ |
|
|
|
switch(header->bits) |
|
|
|
switch(header->bits) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case BITS_64: |
|
|
|
case BITS_64: |
|
|
|
fprintf(stderr, "Provided ELF file targets RISC-V 64 bits ; please provide a 32-bits ELF\n"); |
|
|
|
fprintf(stderr, "Provided ELF file targets RISC-V 64 bits ; please provide a 32-bits ELF\n"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
fprintf(stderr, "Provided ELF file targets an unknown bit count (not 32 bits) ; please provide a 32-bits ELF\n"); |
|
|
|
fprintf(stderr, "Provided ELF file targets an unknown bit count (not 32 bits) ; please provide a 32-bits ELF\n"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Verify endianness
|
|
|
|
// Verify endianness
|
|
|
|
if(header->endianness != ELF_LITTLE_ENDIAN) |
|
|
|
if(header->endianness != ELF_LITTLE_ENDIAN) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fprintf(stderr, "Provided ELF file is encoded in big endian ; please provide a little endian ELF\n"); |
|
|
|
fprintf(stderr, "Provided ELF file is encoded in big endian ; please provide a little endian ELF\n"); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// File should be correct ; now load it, using program header table
|
|
|
|
// 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); |
|
|
|
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; |
|
|
|
size_t program_header_count = header->program_entry_amount; |
|
|
|
for(size_t i = 0; i < program_header_count; i++) |
|
|
|
for(size_t i = 0; i < program_header_count; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
elf_program_header_32_t current = program_header[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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check memory size
|
|
|
|
// Check segment type
|
|
|
|
size_t memsz = current.segment_memory_size; |
|
|
|
if(current.segment_type != SEGMENT_TYPE_LOAD) |
|
|
|
if(!memsz) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Don't message for riscv-specific attributes segment
|
|
|
|
fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n"); |
|
|
|
if(current.segment_type != SEGMENT_TYPE_RISCV_SPECIFIC_SHT_RISCV_ATTRIBUTES) |
|
|
|
continue; |
|
|
|
{ |
|
|
|
} |
|
|
|
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
|
|
|
|
// Check memory size
|
|
|
|
if(memory_size < (current.virtual_address + memsz)) |
|
|
|
size_t memsz = current.segment_memory_size; |
|
|
|
{ |
|
|
|
if(!memsz) |
|
|
|
fprintf(stderr, "FATAL: Not enough memory while loading ELF file\n"); |
|
|
|
{ |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n"); |
|
|
|
} |
|
|
|
continue; |
|
|
|
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; |
|
|
|
// 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; |
|
|
|
} |
|
|
|
} |
|
|
|