Files
Espresso/drivers/elf_load.c

196 lines
5.6 KiB
C
Raw Permalink Normal View History

2025-06-27 14:48:06 -05:00
/*#include <stdlib.h>
#include <drivers/elf_load.h>*/
/*
ELF Header
The ELF header is always found at the start of the file.
Position (32 bit) Position (64 bit) Value
0-3 0-3 Magic number - 0x7F, then 'ELF' in ASCII
4 4 1 = 32 bit, 2 = 64 bit
5 5 1 = little endian, 2 = big endian
6 6 ELF header version
7 7 OS ABI - usually 0 for System V
8-15 8-15 Unused/padding
16-17 16-17 Type (1 = relocatable, 2 = executable, 3 = shared, 4 = core)
18-19 18-19 Instruction set - see table below
20-23 20-23 ELF Version (currently 1)
24-27 24-31 Program entry offset
28-31 32-39 Program header table offset
32-35 40-47 Section header table offset
36-39 48-51 Flags - architecture dependent; see note below
40-41 52-53 ELF Header size
42-43 54-55 Size of an entry in the program header table
44-45 56-57 Number of entries in the program header table
46-47 58-59 Size of an entry in the section header table
48-49 60-61 Number of entries in the section header table
50-51 62-63 Section index to the section header string table
The flags entry can probably be ignored for x86 ELFs, as no flags are actually defined.
Instruction Set Architectures:
Architecture Value
No Specific 0x00
Sparc 0x02
x86 0x03
MIPS 0x08
PowerPC 0x14
ARM 0x28
SuperH 0x2A
IA-64 0x32
x86-64 0x3E
AArch64 0xB7
RISC-V 0xF3
Program header
This is an array of N (given in the main header) entries in the following format. Make sure to use the correct version depending on whether the file is 32 bit or 64 bit as the tables are quite different.
32 bit version:
Position Value
0-3 Type of segment (see below)
4-7 The offset in the file that the data for this segment can be found (p_offset)
8-11 Where you should start to put this segment in virtual memory (p_vaddr)
12-15 Reserved for segment's physical address (p_paddr)
16-19 Size of the segment in the file (p_filesz)
20-23 Size of the segment in memory (p_memsz, at least as big as p_filesz)
24-27 Flags (see below)
28-31 The required alignment for this section (usually a power of 2)
64 bit version:
Position Value
0-3 Type of segment (see below)
4-7 Flags (see below)
8-15 The offset in the file that the data for this segment can be found (p_offset)
16-23 Where you should start to put this segment in virtual memory (p_vaddr)
24-31 Reserved for segment's physical address (p_paddr)
32-39 Size of the segment in the file (p_filesz)
40-47 Size of the segment in memory (p_memsz, at least as big as p_filesz)
48-55 The required alignment for this section (usually a power of 2)
Segment types: 0 = null - ignore the entry; 1 = load - clear p_memsz bytes at p_vaddr to 0, then copy p_filesz bytes from p_offset to p_vaddr; 2 = dynamic - requires dynamic linking; 3 = interp - contains a file path to an executable to use as an interpreter for the following segment; 4 = note section. There are more values, but mostly contain architecture/environment specific information, which is probably not required for the majority of ELF files.
Flags: 1 = executable, 2 = writable, 4 = readable.
*/
/*typedef struct elf_header {
uint32_t elf_magic;
uint8_t bitness;*/ /* 1 = 32 bit, 2 = 64 bit */
/*uint8_t endianess;*/ /* 1 = little endian, 2 = big endian */
/*uint8_t elf_header_version;
uint8_t os_abi;*/ /* usually 0 for System V */
/*uint8_t unused_padding[8];
uint16_t type;
uint16_t isa;
uint32_t elf_version;
uint32_t program_entry_offset;
uint32_t program_header_offset;
uint32_t section_header_offset;
uint32_t flags;
uint16_t elf_header_size;
uint16_t program_header_entry_size;
uint16_t program_header_num_entries;
uint16_t section_header_entry_size;
uint16_t section_header_num_entries;
uint16_t section_header_string_table_index;
} elf_header_t;
typedef struct program_header_entry {
uint32_t type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t flags;
uint32_t alignment_required;
} program_header_entry_t;*/
/*int32_t elf_check(void* executable)
{
elf_header_t* e_header = (elf_header_t*)executable;
char* elf_magic = (char*)e_header->elf_magic;
if (elf_magic[0] != 0x7F || elf_magic[1] != 'E' || elf_magic[2] != 'L' || elf_magic[3] != 'F')
{
return -1;
}
if (e_header->bitness != 1 || e_header->endianess != 1)
{
return -2;
}
uint32_t* cph_addr = (uint32_t*)e_header + e_header->program_header_offset
program_header_entry_t* p_header = (program_header_entry_t*)cph_addr;
uint8_t load = 0;
uin16_t num_phs = 1;
while (p_header)
{
if (num_phs == program_header_num_entries)
{
break;
}
if (p_header->type == 1)
{
load = 1;
break;
}
cph_addr += e_header->program_header_entry_size;
p_header = (program_header_entry_t*)cph_addr;
num_phs++;
}
uint32_t memsz = p_header->p_vaddr + p_header->p_memsz;
void* new_mem = malloc(memsz);
void* memloc = memclr(new_mem, (size_t)memsz);
void *memcpy(void *dst, const void *src, uint32_t n);
void* program_header_table_end = (e_header->program_header_entry_size + e_header->program_header_num_entries);
void* data_begin = (p_header->p_offset + p_header->p_filesz);
memcpy(memloc, p_header->p_offset*/
/*
typedef struct program_header_entry {
uint32_t type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t flags;
uint32_t alignment_required;
} program_header_entry_t;
*/
/*}*/