Improved ELF loading, and overall OS performances.
This commit is contained in:
+229
-326
@@ -21,207 +21,213 @@
|
||||
#include "fs/vfs.h"
|
||||
#include "assert.h"
|
||||
|
||||
/// @brief Reads the elf header from file.
|
||||
/// @param file the file from which we extract the elf header.
|
||||
/// @param header where we store the content we read.
|
||||
/// @return true on success, false on failure.
|
||||
static inline bool_t read_elf_header(vfs_file_t *file, elf_header_t *header)
|
||||
// ============================================================================
|
||||
// GET ELF TABLES
|
||||
// ============================================================================
|
||||
|
||||
/// @brief Returns the pointer to where the section headers reside.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return a pointer to the section headers table.
|
||||
static inline elf_section_header_t *elf_get_section_header_table(elf_header_t *header)
|
||||
{
|
||||
size_t expected = sizeof(elf_header_t);
|
||||
ssize_t nread = vfs_read(file, header, 0, expected);
|
||||
if (nread != expected) {
|
||||
pr_err("Failed to read elf header (read: %ld, expected: %ld)\n", nread, expected);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return (elf_section_header_t *)((uintptr_t)header + header->shoff);
|
||||
}
|
||||
|
||||
/// @brief Reads the program header from file.
|
||||
/// @param file The file from which we extract the program header.
|
||||
/// @param header A pointer to the ELF header.
|
||||
/// @param idx The index of the program header.
|
||||
/// @param phdr Where we store the content we read.
|
||||
/// @return The amount of bytes we read.
|
||||
static inline ssize_t read_elf_program_header(vfs_file_t *file, const elf_header_t *header, unsigned idx, elf_program_header_t *phdr)
|
||||
/// @brief Returns the pointer to where the program headers reside.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return a pointer to the program headers table.
|
||||
static inline elf_program_header_t *elf_get_program_header_table(elf_header_t *header)
|
||||
{
|
||||
return vfs_read(file, phdr, header->phoff + header->phentsize * idx, sizeof(elf_program_header_t));
|
||||
return (elf_program_header_t *)((uintptr_t)header + header->phoff);
|
||||
}
|
||||
|
||||
/// @brief Reads the section header from file.
|
||||
/// @param file The file from which we extract the section header.
|
||||
/// @param header A pointer to the ELF header.
|
||||
// ============================================================================
|
||||
// GET ELF OBJECTS
|
||||
// ============================================================================
|
||||
|
||||
/// @brief Returns a pointer to the desired section header.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @param idx The index of the section header.
|
||||
/// @param shdr Where we store the content we read.
|
||||
/// @return The amount of bytes we read.
|
||||
static inline ssize_t read_elf_section_header(vfs_file_t *file, const elf_header_t *header, unsigned idx, elf_section_header_t *shdr)
|
||||
/// @return a pointer to the desired section header.
|
||||
static inline elf_section_header_t *elf_get_section_header(elf_header_t *header, unsigned idx)
|
||||
{
|
||||
return vfs_read(file, shdr, header->shoff + header->shentsize * idx, sizeof(elf_section_header_t));
|
||||
return &elf_get_section_header_table(header)[idx];
|
||||
}
|
||||
|
||||
/// @brief Reads the symbol from file.
|
||||
/// @param file The file from which we extract the symbol.
|
||||
/// @param shdr A pointer to the ELF symbol table header.
|
||||
/// @param idx The index of the symbol.
|
||||
/// @param symbol Where we store the content we read.
|
||||
/// @return The amount of bytes we read.
|
||||
static inline ssize_t read_elf_symbol(vfs_file_t *file, const elf_section_header_t *shdr, unsigned idx, elf_symbol_t *symbol)
|
||||
{
|
||||
// TODO: Here it should use `shdr->entsize`.
|
||||
return vfs_read(file, symbol, shdr->offset + sizeof(elf_symbol_t) * idx, sizeof(elf_symbol_t));
|
||||
}
|
||||
|
||||
/// @brief Reads the symbol from file.
|
||||
/// @param file The file from which we extract the symbol.
|
||||
/// @param shdr A pointer to the ELF symbol table header.
|
||||
/// @param idx The index of the symbol.
|
||||
/// @param symbol Where we store the content we read.
|
||||
/// @return The amount of bytes we read.
|
||||
static inline ssize_t read_elf_symbol_name(vfs_file_t *file, const elf_section_header_t *shdr, unsigned offset, char *name, size_t name_len)
|
||||
{
|
||||
return vfs_read(file, name, shdr->offset + offset, name_len);
|
||||
}
|
||||
|
||||
/// @brief Reads all program headers from file.
|
||||
/// @param file the file from which we extract the program header.
|
||||
/// @brief Returns a pointer to the desired program header.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return The program headers, free them when finished.
|
||||
static inline elf_program_header_t *read_elf_program_headers(vfs_file_t *file, const elf_header_t *header)
|
||||
/// @param idx the index of the program header.
|
||||
/// @return a pointer to the desired section header.
|
||||
static inline elf_program_header_t *elf_get_program_header(elf_header_t *header, unsigned idx)
|
||||
{
|
||||
assert(sizeof(elf_program_header_t) == header->phentsize);
|
||||
// Compute the size.
|
||||
size_t size = header->phnum * header->phentsize;
|
||||
// Allocate the memory for the headers.
|
||||
elf_program_header_t *program_headers = (elf_program_header_t *)kmalloc(size);
|
||||
if (program_headers == NULL) {
|
||||
pr_err("Failed to allocate memory for program headers.\n");
|
||||
return NULL;
|
||||
}
|
||||
// Clean up the memory.
|
||||
memset(program_headers, 0, size);
|
||||
// Read the headers.
|
||||
if (vfs_read(file, program_headers, header->phoff, size) != size) {
|
||||
pr_err("Failed to read program headers.\n");
|
||||
kfree(program_headers);
|
||||
return NULL;
|
||||
}
|
||||
return program_headers;
|
||||
return &elf_get_program_header_table(header)[idx];
|
||||
}
|
||||
|
||||
/// @brief Reads all section headers from file.
|
||||
/// @param file the file from which we extract the section header.
|
||||
// ============================================================================
|
||||
// GET STRING TABLES
|
||||
// ============================================================================
|
||||
|
||||
/// @brief Returns a pointer to the section header string table.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return The section headers, free them when finished.
|
||||
static inline elf_section_header_t *read_elf_section_headers(vfs_file_t *file, const elf_header_t *header)
|
||||
/// @return a pointer to the section header string table, or NULL on failure.
|
||||
static inline const char *elf_get_section_header_string_table(elf_header_t *header)
|
||||
{
|
||||
assert(sizeof(elf_section_header_t) == header->shentsize);
|
||||
// Compute the size.
|
||||
size_t size = header->shnum * header->shentsize;
|
||||
// Allocate the memory for the headers.
|
||||
elf_section_header_t *section_headers = (elf_section_header_t *)kmalloc(size);
|
||||
if (section_headers == NULL) {
|
||||
pr_err("Failed to allocate memory for section headers.\n");
|
||||
if (header->shstrndx == SHT_NULL)
|
||||
return NULL;
|
||||
}
|
||||
// Clean up the memory.
|
||||
memset(section_headers, 0, size);
|
||||
// Read the headers.
|
||||
if (vfs_read(file, section_headers, header->shoff, size) != size) {
|
||||
pr_err("Failed to read section headers.\n");
|
||||
kfree(section_headers);
|
||||
return NULL;
|
||||
}
|
||||
return section_headers;
|
||||
return (const char *)((uintptr_t)header + elf_get_section_header(header, header->shstrndx)->offset);
|
||||
}
|
||||
|
||||
static inline char *read_elf_strtable(
|
||||
vfs_file_t *file,
|
||||
const elf_header_t *header,
|
||||
const elf_section_header_t *section_header)
|
||||
/// @brief Returns a pointer to the section header string table.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return a pointer to the section header string table, or NULL on failure.
|
||||
static inline const char *elf_get_symbol_string_table(elf_header_t *header, elf_section_header_t *section_header)
|
||||
{
|
||||
// Check if the header points to a string table.
|
||||
if (section_header->type != SHT_STRTAB) {
|
||||
pr_err("The header is not a STRTAB but a `%s` instead.\n", elf_type_to_string(section_header->type));
|
||||
if (section_header->link == SHT_NULL)
|
||||
return NULL;
|
||||
}
|
||||
// Allocate the memory for the string table.
|
||||
char *strtab = kmalloc(section_header->size);
|
||||
// Initialize the memory.
|
||||
memset(strtab, 0, section_header->size);
|
||||
// Read the string table.
|
||||
if (vfs_read(file, strtab, section_header->offset, section_header->size) != section_header->size) {
|
||||
pr_err("Failed to read the string table at %d.\n", section_header->offset);
|
||||
kfree(strtab);
|
||||
return NULL;
|
||||
}
|
||||
return strtab;
|
||||
return (const char *)((uintptr_t)header + elf_get_section_header(header, section_header->link)->offset);
|
||||
}
|
||||
|
||||
static inline elf_symbol_t *read_elf_symtable(
|
||||
vfs_file_t *file,
|
||||
const elf_header_t *header,
|
||||
const elf_section_header_t *section_header)
|
||||
// ============================================================================
|
||||
// GET ELF OBJECTS NAME
|
||||
// ============================================================================
|
||||
|
||||
/// @brief Returns the name of the given entry in the section header string table.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @param name_offset the offset where the desired name resides inside the table.
|
||||
/// @return a pointer to the name, or NULL on failure.
|
||||
static inline const char *elf_get_section_header_name(elf_header_t *header, elf_section_header_t *section_header)
|
||||
{
|
||||
// Check if the header points to a string table.
|
||||
if (section_header->type != SHT_SYMTAB) {
|
||||
pr_err("The header is not a SYMTAB but a `%s` instead.\n", elf_type_to_string(section_header->type));
|
||||
const char *strtab = elf_get_section_header_string_table(header);
|
||||
if (strtab == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (sizeof(elf_symbol_t) != section_header->entsize) {
|
||||
pr_err("Entities inside the symbol table have wrong size, %ld instead of %ld.\n",
|
||||
section_header->entsize, sizeof(elf_symbol_t));
|
||||
return NULL;
|
||||
}
|
||||
// Allocate the memory for the string table.
|
||||
elf_symbol_t *symtab = kmalloc(section_header->size);
|
||||
// Initialize the memory.
|
||||
memset(symtab, 0, section_header->size);
|
||||
// Read the string table.
|
||||
if (vfs_read(file, symtab, section_header->offset, section_header->size) != section_header->size) {
|
||||
pr_err("Failed to read the symbol table at %d.\n", section_header->offset);
|
||||
kfree(symtab);
|
||||
return NULL;
|
||||
}
|
||||
return symtab;
|
||||
return strtab + section_header->name;
|
||||
}
|
||||
|
||||
static inline const elf_section_header_t *elf_find_section_header(
|
||||
const elf_header_t *header,
|
||||
const elf_section_header_t *section_headers,
|
||||
const char *shstrtab,
|
||||
const char *name)
|
||||
/// @brief Returns a pointer to the section header string table.
|
||||
/// @param header a pointer to the ELF header.
|
||||
/// @return a pointer to the section header string table, or NULL on failure.
|
||||
static inline const char *elf_get_symbol_name(elf_header_t *header, elf_section_header_t *section_header, elf_symbol_t *symbol)
|
||||
{
|
||||
for (unsigned i = 0; i < header->shnum; ++i)
|
||||
if (strcmp(shstrtab + section_headers[i].name, name) == 0)
|
||||
return §ion_headers[i];
|
||||
const char *strtab = elf_get_symbol_string_table(header, section_header);
|
||||
if (strtab == NULL)
|
||||
return NULL;
|
||||
return strtab + symbol->name;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SEARCH FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
static inline elf_section_header_t *elf_find_section_header(elf_header_t *header, const char *name)
|
||||
{
|
||||
for (unsigned i = 0; i < header->shnum; ++i) {
|
||||
// Get the section header.
|
||||
elf_section_header_t *section_header = elf_get_section_header(header, i);
|
||||
// Get the section header name.
|
||||
const char *section_header_name = elf_get_section_header_name(header, section_header);
|
||||
if (section_header_name) {
|
||||
// Check the section header name.
|
||||
if (strcmp(section_header_name, name) == 0) {
|
||||
return section_header;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const elf_symbol_t *elf_find_symbol(
|
||||
const elf_section_header_t *symbol_table_header,
|
||||
const elf_symbol_t *symbol_table,
|
||||
const char *symbol_table_strtab,
|
||||
const char *name)
|
||||
static inline elf_symbol_t *elf_find_symbol(elf_header_t *header, const char *name)
|
||||
{
|
||||
// Compute the entries in the symbol table.
|
||||
uint32_t symtab_entries = symbol_table_header->size / sizeof(elf_symbol_t);
|
||||
// Search the symbol.
|
||||
for (unsigned i = 0; i < symtab_entries; ++i)
|
||||
if (strcmp(symbol_table_strtab + symbol_table[i].name, name) == 0)
|
||||
return &symbol_table[i];
|
||||
for (unsigned i = 0; i < header->shnum; ++i) {
|
||||
// Get the section header.
|
||||
elf_section_header_t *section_header = elf_get_section_header(header, i);
|
||||
// Check if it is valid, and it is a symbol table.
|
||||
if (section_header && (section_header->type == SHT_SYMTAB)) {
|
||||
// Count the number of entries.
|
||||
unsigned symtab_entries = section_header->size / section_header->entsize;
|
||||
// Get the addresss of the symbol table.
|
||||
elf_symbol_t *symtab = (elf_symbol_t *)((uintptr_t)header + section_header->offset);
|
||||
// Iterate the entries.
|
||||
for (unsigned j = 0; j < symtab_entries; ++j) {
|
||||
// Get the symbol.
|
||||
elf_symbol_t *symbol = &symtab[j];
|
||||
// Get the name of the symbol.
|
||||
const char *symbol_name = elf_get_symbol_name(header, section_header, symbol);
|
||||
if (symbol_name) {
|
||||
// Check the symbol name.
|
||||
if (strcmp(symbol_name, name) == 0) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int elf_load_sigreturn(
|
||||
const elf_section_header_t *symbol_table_header,
|
||||
const elf_symbol_t *symbol_table,
|
||||
const char *symbol_table_strtab,
|
||||
task_struct *task)
|
||||
// ============================================================================
|
||||
// DUMP FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
static inline void elf_dump_section_headers(elf_header_t *header)
|
||||
{
|
||||
const elf_symbol_t *sigreturn = elf_find_symbol(symbol_table_header, symbol_table, symbol_table_strtab, "sigreturn");
|
||||
pr_debug("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n");
|
||||
for (unsigned idx = 0; idx < header->shnum; ++idx) {
|
||||
// Get the section header.
|
||||
elf_section_header_t *section_header = elf_get_section_header(header, idx);
|
||||
// Get the section header name.
|
||||
const char *section_header_name = elf_get_section_header_name(header, section_header);
|
||||
// Dump the information.
|
||||
pr_debug("[%2d] %-20s %-15s %08x %06x %06x %2u %3u %2u %3u %2u\n",
|
||||
idx, section_header_name, elf_section_header_type_to_string(section_header->type),
|
||||
section_header->addr, section_header->offset, section_header->size,
|
||||
section_header->entsize, section_header->flags, section_header->link,
|
||||
section_header->info, section_header->addralign);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void elf_dump_symbol_table(elf_header_t *header)
|
||||
{
|
||||
for (unsigned i = 0; i < header->shnum; ++i) {
|
||||
// Get the section header.
|
||||
elf_section_header_t *section_header = elf_get_section_header(header, i);
|
||||
if (section_header->type != SHT_SYMTAB)
|
||||
continue;
|
||||
// Count the number of entries.
|
||||
uint32_t symtab_entries = section_header->size / section_header->entsize;
|
||||
// Get the addresss of the symbol table.
|
||||
elf_symbol_t *symtab = (elf_symbol_t *)((uintptr_t)header + section_header->offset);
|
||||
// Dump the table.
|
||||
for (int j = 0; j < symtab_entries; ++j) {
|
||||
// Get the symbol.
|
||||
elf_symbol_t *symbol = &symtab[j];
|
||||
// Get the name of the symbol.
|
||||
const char *symbol_name = elf_get_symbol_name(header, section_header, symbol);
|
||||
if (symbol_name == NULL) {
|
||||
pr_err("Null symbol name.\n");
|
||||
return;
|
||||
}
|
||||
// Dump the symbol.
|
||||
pr_debug("[%4d] %08x %5d %-7s %-6s %-8s %3d %s\n", j, symbol->value, symbol->size,
|
||||
elf_symbol_type_to_string(ELF32_ST_TYPE(symbol->info)),
|
||||
elf_symbol_bind_to_string(ELF32_ST_BIND(symbol->info)),
|
||||
"-", symbol->ndx, symbol_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// EXEC-RELATED FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
static inline int elf_set_sigreturn(elf_header_t *header, task_struct *task)
|
||||
{
|
||||
elf_symbol_t *sigreturn = elf_find_symbol(header, "sigreturn");
|
||||
if (sigreturn == NULL) {
|
||||
pr_err("Failed to find `sigreturn`!\n");
|
||||
return false;
|
||||
}
|
||||
task->sigreturn_eip = sigreturn->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -230,78 +236,35 @@ static inline int elf_load_sigreturn(
|
||||
/// @param file The ELF file.
|
||||
/// @param header The header of the ELF file.
|
||||
/// @return The ELF entry.
|
||||
static inline int elf_load_exec(
|
||||
task_struct *task,
|
||||
vfs_file_t *file,
|
||||
const elf_header_t *header,
|
||||
const elf_program_header_t *phdrs)
|
||||
static inline int elf_load_exec(elf_header_t *header, task_struct *task)
|
||||
{
|
||||
#if 0
|
||||
pr_debug(" Type | Mem. Size | File Size | VADDR\n");
|
||||
for (unsigned i = 0; i < header->phnum; ++i) {
|
||||
// Get the header.
|
||||
elf_program_header_t *program_header = elf_get_program_header(header, i);
|
||||
// Dump the information about the header.
|
||||
pr_debug(" %-9s | %9s | %9s | 0x%08x - 0x%08x\n",
|
||||
elf_type_to_string(phdrs[i].type),
|
||||
to_human_size(phdrs[i].memsz),
|
||||
to_human_size(phdrs[i].filesz),
|
||||
phdrs[i].vaddr, phdrs[i].vaddr + phdrs[i].memsz);
|
||||
if (phdrs[i].type == PT_LOAD) {
|
||||
uint32_t virt_addr = create_vm_area(task->mm, phdrs[i].vaddr, phdrs[i].memsz, MM_USER | MM_RW | MM_COW, GFP_KERNEL);
|
||||
virt_map_page_t *vpage = virt_map_alloc(phdrs[i].memsz);
|
||||
uint32_t dst_addr = virt_map_vaddress(task->mm, vpage, virt_addr, phdrs[i].memsz);
|
||||
elf_type_to_string(program_header->type),
|
||||
to_human_size(program_header->memsz),
|
||||
to_human_size(program_header->filesz),
|
||||
program_header->vaddr,
|
||||
program_header->vaddr + program_header->memsz);
|
||||
if (program_header->type == PT_LOAD) {
|
||||
uint32_t virt_addr = create_vm_area(task->mm, program_header->vaddr, program_header->memsz, MM_USER | MM_RW | MM_COW, GFP_KERNEL);
|
||||
virt_map_page_t *vpage = virt_map_alloc(program_header->memsz);
|
||||
uint32_t dst_addr = virt_map_vaddress(task->mm, vpage, virt_addr, program_header->memsz);
|
||||
|
||||
// Load the memory area.
|
||||
vfs_read(file, (void *)dst_addr, phdrs[i].offset, phdrs[i].filesz);
|
||||
memcpy((void *)dst_addr, (void *)((uintptr_t)header + program_header->offset), program_header->filesz);
|
||||
|
||||
if (phdrs[i].memsz > phdrs[i].filesz) {
|
||||
uint32_t zmem_sz = phdrs[i].memsz - phdrs[i].filesz;
|
||||
memset((void *)(dst_addr + phdrs[i].filesz), 0, zmem_sz);
|
||||
if (program_header->memsz > program_header->filesz) {
|
||||
uint32_t zmem_sz = program_header->memsz - program_header->filesz;
|
||||
memset((void *)(dst_addr + program_header->filesz), 0, zmem_sz);
|
||||
}
|
||||
virt_unmap_pg(vpage);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dump_elf_section_headers(
|
||||
vfs_file_t *file,
|
||||
const elf_header_t *header,
|
||||
const elf_section_header_t *shdrs,
|
||||
const char *shstrtab)
|
||||
{
|
||||
pr_debug("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n");
|
||||
for (int i = 0; i < header->shnum; ++i) {
|
||||
pr_debug("[%2d] %-20s %-15s %08x %06x %06x %2u %3u %2u %3u %2u\n",
|
||||
i, shstrtab + shdrs[i].name, elf_section_header_type_to_string(shdrs[i].type),
|
||||
shdrs[i].addr, shdrs[i].offset, shdrs[i].size,
|
||||
shdrs[i].entsize, shdrs[i].flags, shdrs[i].link, shdrs[i].info, shdrs[i].addralign);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dump_elf_symbol_table(
|
||||
vfs_file_t *file,
|
||||
const elf_header_t *header,
|
||||
const elf_section_header_t *symtab_header,
|
||||
const char *symtab_strtab)
|
||||
{
|
||||
// Count the number of entries.
|
||||
uint32_t symtab_entries = symtab_header->size / sizeof(elf_symbol_t);
|
||||
pr_debug("Symbol table '.symtab' contains %d entries (%d/%d):\n", symtab_entries, symtab_header->size, sizeof(elf_symbol_t));
|
||||
pr_debug("[ Nr ] Value Size Type Bind Vis Ndx Name\n");
|
||||
elf_symbol_t symbol;
|
||||
for (int i = 0; i < symtab_entries; ++i) {
|
||||
if (read_elf_symbol(file, symtab_header, i, &symbol) == -1) {
|
||||
pr_err("Failed to read the elf symbol at index %d.\n", i);
|
||||
continue;
|
||||
}
|
||||
pr_debug("[%4d] %08x %5d %-7s %-6s %-8s %3d %s\n", i, symbol.value, symbol.size,
|
||||
elf_symbol_type_to_string(ELF32_ST_TYPE(symbol.info)),
|
||||
elf_symbol_bind_to_string(ELF32_ST_BIND(symbol.info)),
|
||||
"-",
|
||||
symbol.ndx,
|
||||
symtab_strtab + symbol.name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry)
|
||||
@@ -309,121 +272,61 @@ int elf_load_file(task_struct *task, vfs_file_t *file, uint32_t *entry)
|
||||
// Open the file.
|
||||
if (file == NULL)
|
||||
return false;
|
||||
|
||||
// Read the elf header.
|
||||
elf_header_t header;
|
||||
if (!read_elf_header(file, &header))
|
||||
// Get the size of the file.
|
||||
stat_t stat_buf;
|
||||
if (vfs_fstat(file, &stat_buf) < 0) {
|
||||
pr_err("Failed to stat the file `%s`.\n", file->name);
|
||||
return false;
|
||||
|
||||
}
|
||||
// Allocate the memory for the file.
|
||||
char *buffer = kmalloc(stat_buf.st_size);
|
||||
if (buffer == NULL) {
|
||||
pr_err("Failed to allocate %d bytes of memory for reading the file `%s`.\n", stat_buf.st_size, file->name);
|
||||
return false;
|
||||
}
|
||||
// Clean the memory.
|
||||
memset(buffer, 0, stat_buf.st_size);
|
||||
// Read the file.
|
||||
if (vfs_read(file, buffer, 0, stat_buf.st_size) != stat_buf.st_size) {
|
||||
pr_err("Failed to read %d bytes from the file `%s`.\n", stat_buf.st_size, file->name);
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
// The first thing inside the file is the ELF header.
|
||||
elf_header_t *header = (elf_header_t *)buffer;
|
||||
// Print header info.
|
||||
pr_debug("Version : 0x%x\n", header.version);
|
||||
pr_debug("Entry : 0x%x\n", header.entry);
|
||||
pr_debug("Headers offset : 0x%x\n", header.phoff);
|
||||
pr_debug("Headers count : %d\n", header.phnum);
|
||||
|
||||
pr_debug("Type : %s\n", elf_type_to_string(header->type));
|
||||
pr_debug("Version : 0x%x\n", header->version);
|
||||
pr_debug("Entry : 0x%x\n", header->entry);
|
||||
pr_debug("Headers offset : 0x%x\n", header->phoff);
|
||||
pr_debug("Headers count : %d\n", header->phnum);
|
||||
// Check the elf header.
|
||||
if (!elf_check_file_header(&header))
|
||||
return false;
|
||||
|
||||
if (!elf_check_file_header(header)) {
|
||||
pr_err("File %s is not a valid ELF file.\n", stat_buf.st_size, file->name);
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
// Check if the elf file is an executable.
|
||||
if (header.type != ET_EXEC) {
|
||||
if (header->type != ET_EXEC) {
|
||||
pr_err("Elf file is not an executable.\n");
|
||||
return false;
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
// Set the sigreturn of the task.
|
||||
if (!elf_set_sigreturn(header, task)) {
|
||||
pr_err("Failed to set `sigreturn` for the executable.\n");
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
if (!elf_load_exec(header, task)) {
|
||||
pr_err("Failed to load the executable.\n");
|
||||
goto return_error_free_buffer;
|
||||
}
|
||||
|
||||
// Load section headers.
|
||||
elf_section_header_t *section_headers = read_elf_section_headers(file, &header);
|
||||
if (section_headers == NULL) {
|
||||
pr_err("Failed to load section headers.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load program headers.
|
||||
elf_program_header_t *program_headers = read_elf_program_headers(file, &header);
|
||||
if (program_headers == NULL) {
|
||||
pr_err("Failed to load program headers.\n");
|
||||
goto free_section_headers;
|
||||
}
|
||||
|
||||
// Get the header pointing to the section headers string table.
|
||||
elf_section_header_t *shstrtab_hdr = §ion_headers[header.shstrndx];
|
||||
// Read the section headers string table.
|
||||
char *shstrtab = read_elf_strtable(file, &header, shstrtab_hdr);
|
||||
if (shstrtab == NULL) {
|
||||
pr_err("Cannot retrieve the symbol table.\n");
|
||||
goto free_program_headers;
|
||||
}
|
||||
|
||||
// Find the symbol table header.
|
||||
const elf_section_header_t *symtab_header = elf_find_section_header(&header, section_headers, shstrtab, ".symtab");
|
||||
if (symtab_header == NULL) {
|
||||
pr_err("Cannot find symbol table.\n");
|
||||
goto free_string_table;
|
||||
}
|
||||
|
||||
// Find the string table header associated with the symbol table header.
|
||||
const elf_section_header_t *symtab_strtab_header = §ion_headers[symtab_header->link];
|
||||
if (symtab_strtab_header == NULL) {
|
||||
pr_err("Cannot find strtab of symbol table.\n");
|
||||
goto free_string_table;
|
||||
}
|
||||
|
||||
// Load the symbol table.
|
||||
elf_symbol_t *symtab = read_elf_symtable(file, &header, symtab_header);
|
||||
if (symtab == NULL) {
|
||||
pr_err("Cannot load symbol table.\n");
|
||||
goto free_symbol_table_strtab;
|
||||
}
|
||||
|
||||
// Read the symbol table section header.
|
||||
char *symtab_strtab = read_elf_strtable(file, &header, symtab_strtab_header);
|
||||
if (symtab_strtab == NULL) {
|
||||
pr_err("Cannot retrieve the symbol table.\n");
|
||||
goto free_symbol_table;
|
||||
}
|
||||
|
||||
if (elf_load_sigreturn(symtab_header, symtab, symtab_strtab, task) == -1) {
|
||||
pr_err("Failed to load `sigreturn`.\n");
|
||||
goto free_symbol_table;
|
||||
}
|
||||
dump_elf_section_headers(file, &header, section_headers, shstrtab);
|
||||
dump_elf_symbol_table(file, &header, symtab_header, symtab_strtab);
|
||||
|
||||
|
||||
free_symbol_table:
|
||||
kfree(symtab_strtab);
|
||||
free_symbol_table_strtab:
|
||||
kfree(symtab);
|
||||
free_string_table:
|
||||
kfree(shstrtab);
|
||||
free_program_headers:
|
||||
kfree(program_headers);
|
||||
free_section_headers:
|
||||
kfree(section_headers);
|
||||
|
||||
while (true) {}
|
||||
#if 0
|
||||
return false;
|
||||
|
||||
while (true) {}
|
||||
|
||||
//dump_elf_symbol_table(file, &header);
|
||||
if (elf_load_exec(task, file, &header, phdrs) == -1) {
|
||||
// Free up the memory.
|
||||
kfree(shdrs);
|
||||
kfree(phdrs);
|
||||
return 0;
|
||||
}
|
||||
// Set the entry.
|
||||
(*entry) = header.entry;
|
||||
(*entry) = header->entry;
|
||||
|
||||
// Free up the memory.
|
||||
kfree(shdrs);
|
||||
kfree(phdrs);
|
||||
|
||||
while (true) {}
|
||||
#endif
|
||||
return 1;
|
||||
kfree(buffer);
|
||||
return true;
|
||||
return_error_free_buffer:
|
||||
kfree(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
int elf_check_file_type(vfs_file_t *file, Elf_Type type)
|
||||
|
||||
+18
-1
@@ -1292,7 +1292,9 @@ static int ext2_find_entry(ext2_filesystem_t *fs, ino_t ino, const char *name, e
|
||||
}
|
||||
// Get the directory entry.
|
||||
entry = (ext2_dirent_t *)((uintptr_t)cache + dir_offset);
|
||||
|
||||
if (!strcmp(entry->name, ".") && !strcmp(name, "/")) {
|
||||
break;
|
||||
}
|
||||
// Check if the entry has the same name.
|
||||
if ((entry->inode != 0) && (strlen(name) == entry->name_len))
|
||||
if (!strncmp(entry->name, name, entry->name_len))
|
||||
@@ -1322,6 +1324,7 @@ free_cache_return_error:
|
||||
/// @return 0 on success, -1 on failure.
|
||||
static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *direntry)
|
||||
{
|
||||
pr_debug("ext2_resolve_path(%s, %s, %p)\n", directory->name, path, direntry);
|
||||
// Check the pointers.
|
||||
if (directory == NULL) {
|
||||
pr_err("You provided a NULL directory.\n");
|
||||
@@ -1341,6 +1344,10 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *d
|
||||
pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", directory->name);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(path, "/") == 0) {
|
||||
ext2_find_entry(fs, directory->ino, path, direntry);
|
||||
return 0;
|
||||
}
|
||||
ino_t ino = directory->ino;
|
||||
char *token = strtok(path, "/");
|
||||
while (token) {
|
||||
@@ -1535,6 +1542,16 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
|
||||
/// @param file The file structure.
|
||||
static int ext2_close(vfs_file_t *file)
|
||||
{
|
||||
// Get the filesystem.
|
||||
ext2_filesystem_t *fs = (ext2_filesystem_t *)file->device;
|
||||
if (fs == NULL) {
|
||||
pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", file->name);
|
||||
return -1;
|
||||
}
|
||||
// We cannot close the root.
|
||||
if (file == fs->root) {
|
||||
return -1;
|
||||
}
|
||||
pr_debug("ext2_close(%p) : Closing file `%s`\n", file, file->name);
|
||||
// Remove the file from the list of opened files.
|
||||
list_head_del(&file->siblings);
|
||||
|
||||
Reference in New Issue
Block a user