34,7 → 34,13 |
|
/** |
* @file |
* @brief Kernel ELF loader. |
* @brief Userspace ELF loader. |
* |
* This module allows loading ELF binaries (both executables and |
* shared objects) from VFS. The current implementation allocates |
* anonymous memory, fills it with segment data and then adjusts |
* the memory areas' flags to the final value. In the future, |
* the segments will be mapped directly from the file. |
*/ |
|
#include <stdio.h> |
63,6 → 69,21 |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry); |
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); |
|
/** Load ELF binary from a file. |
* |
* Load an ELF binary from the specified file. If the file is |
* an executable program, it is loaded unbiased. If it is a shared |
* object, it is loaded with the bias @a so_bias. Some information |
* extracted from the binary is stored in a elf_info_t structure |
* pointed to by @a info. |
* |
* @param file_name Path to the ELF file. |
* @param so_bias Bias to use if the file is a shared object. |
* @param info Pointer to a structure for storing information |
* extracted from the binary. |
* |
* @return EOK on success or negative error code. |
*/ |
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info) |
{ |
elf_ld_t elf; |
72,7 → 93,7 |
|
printf("open and read '%s'...\n", file_name); |
|
fd = open(file_name, 0); |
fd = open(file_name, O_RDONLY); |
if (fd < 0) { |
printf("failed opening file\n"); |
return -1; |
89,6 → 110,13 |
return rc; |
} |
|
/** Run an ELF executable. |
* |
* Transfers control to the entry point of an ELF executable loaded |
* earlier with elf_load_file(). This function does not return. |
* |
* @param info Info structure filled earlier by elf_load_file() |
*/ |
void elf_run(elf_info_t *info) |
{ |
(*info->entry)(); |
96,6 → 124,14 |
/* not reached */ |
} |
|
/** Create the program control block (PCB). |
* |
* Create and install the program control block, initialising it |
* with program information from @a info. |
* |
* @param info Program info structure |
* @return EOK on success or negative error code |
*/ |
int elf_create_pcb(elf_info_t *info) |
{ |
pcb_t *pcb; |
116,10 → 152,15 |
} |
|
|
/** ELF loader |
/** Load an ELF binary. |
* |
* @param header Pointer to ELF header in memory |
* @return EE_OK on success |
* The @a elf structure contains the loader state, including |
* an open file, from which the binary will be loaded, |
* a pointer to the @c info structure etc. |
* |
* @param elf Pointer to loader state buffer. |
* @param so_bias Bias to use if the file is a shared object. |
* @return EE_OK on success or EE_xx error code. |
*/ |
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias) |
{ |
243,8 → 284,7 |
|
/** Process segment header. |
* |
* @param entry Segment header. |
* @param elf ELF header. |
* @param entry Segment header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
276,8 → 316,8 |
|
/** Load segment described by program header entry. |
* |
* @param elf Loader state. |
* @param entry Program header entry describing segment to be loaded. |
* @param elf ELF header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
346,6 → 386,9 |
printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias); |
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/ |
|
/* Long reads are not possible yet. Load segment picewise */ |
|
unsigned left, now; |
uint8_t *dp; |
|
354,11 → 397,14 |
|
while (left > 0) { |
now = 16384; |
if (now > left) now=left; |
if (now > left) now = left; |
|
printf("read %d...", now); |
rc = read(elf->fd, dp, now); |
printf("->%d\n", rc); |
|
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
printf("->%d\n", rc); |
|
left -= now; |
dp += now; |
} |
375,8 → 421,8 |
|
/** Process section header. |
* |
* @param elf Loader state. |
* @param entry Segment header. |
* @param elf ELF header. |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
394,6 → 440,7 |
} |
break; |
case SHT_DYNAMIC: |
/* Record pointer to dynamic section into info structure */ |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
printf("dynamic section found at 0x%x\n", |