ELF: added support for SHT_RISCV_ATTRIBUTES seg
This commit is contained in:
		@@ -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
 | 
							// Check segment type
 | 
				
			||||||
        if(current.segment_type != SEGMENT_TYPE_LOAD)
 | 
							if(current.segment_type != SEGMENT_TYPE_LOAD)
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            fprintf(stderr, "WARNING: Unknown segment type %u in ELF file ; skipping\n", current.segment_type);
 | 
					            // Don't message for riscv-specific attributes segment
 | 
				
			||||||
            continue;
 | 
								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;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check memory size
 | 
							// Check memory size
 | 
				
			||||||
        size_t memsz = current.segment_memory_size;
 | 
							size_t memsz = current.segment_memory_size;
 | 
				
			||||||
        if(!memsz)
 | 
							if(!memsz)
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n");
 | 
								fprintf(stderr, "WARNING: LOAD segment with null size in ELF file ; skipping\n");
 | 
				
			||||||
            continue;
 | 
								continue;
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Map the segment : first the part in the file, then the zeros
 | 
							// Map the segment : first the part in the file, then the zeros
 | 
				
			||||||
        if(memory_size < (current.virtual_address + memsz))
 | 
							if(memory_size < (current.virtual_address + memsz))
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            fprintf(stderr, "FATAL: Not enough memory while loading ELF file\n");
 | 
								fprintf(stderr, "FATAL: Not enough memory while loading ELF file\n");
 | 
				
			||||||
            exit(EXIT_FAILURE);
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
        if(current.segment_file_size != 0)
 | 
							if(current.segment_file_size != 0)
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            memcpy(&memory[current.virtual_address], ((uint8_t*) file) + current.segment_offset, current.segment_file_size);
 | 
								memcpy(&memory[current.virtual_address], ((uint8_t*) file) + current.segment_offset, current.segment_file_size);
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
        if(memsz > 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);
 | 
								memset(&memory[current.virtual_address] + current.segment_file_size, 0, memsz - current.segment_file_size);
 | 
				
			||||||
        }
 | 
							}
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return header->entry_32;
 | 
						return header->entry_32;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,6 +77,7 @@ typedef struct ELF_PROGRAM_HEADER_32
 | 
				
			|||||||
#define SEGMENT_TYPE_DYNAMIC 2
 | 
					#define SEGMENT_TYPE_DYNAMIC 2
 | 
				
			||||||
#define SEGMENT_TYPE_INTERP 3
 | 
					#define SEGMENT_TYPE_INTERP 3
 | 
				
			||||||
#define SEGMENT_TYPE_NOTE 4
 | 
					#define SEGMENT_TYPE_NOTE 4
 | 
				
			||||||
 | 
					#define SEGMENT_TYPE_RISCV_SPECIFIC_SHT_RISCV_ATTRIBUTES 0x70000003
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t elf_32_load(void* file);
 | 
					uint32_t elf_32_load(void* file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user