61,15 → 61,15 |
"irrecoverable error" |
}; |
|
static unsigned int elf_load(int fd, elf_header_t *header); |
static int segment_header(int fd, elf_header_t *elf); |
static int section_header(int fd, elf_header_t *elf); |
static int load_segment(int fd, elf_segment_header_t *entry, elf_header_t *elf); |
static unsigned int elf_load(elf_ld_t *elf); |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry); |
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); |
|
typedef void (*entry_point_t)(void); |
int elf_load_file(char *file_name, elf_info_t *info) |
{ |
elf_ld_t elf; |
|
int elf_load_file(char *file_name, elf_header_t *header) |
{ |
int fd; |
int rc; |
|
81,7 → 81,10 |
return -1; |
} |
|
rc = elf_load(fd, header); |
elf.fd = fd; |
elf.info = info; |
|
rc = elf_load(&elf); |
printf("elf_load() -> %d\n", rc); |
|
close(fd); |
89,17 → 92,14 |
return rc; |
} |
|
void elf_run(elf_header_t *header) |
void elf_run(elf_info_t *info) |
{ |
entry_point_t entry_point; |
(*info->entry)(); |
|
entry_point = (entry_point_t)header->e_entry; |
(*entry_point)(); |
|
/* not reached */ |
} |
|
int elf_create_pcb(elf_header_t *header) |
int elf_create_pcb(elf_info_t *info) |
{ |
pcb_t *pcb; |
void *a; |
112,7 → 112,7 |
return EE_MEMORY; |
} |
|
pcb->entry = (entry_point_t)header->e_entry; |
pcb->entry = info->entry; |
|
return 0; |
} |
123,16 → 123,20 |
* @param header Pointer to ELF header in memory |
* @return EE_OK on success |
*/ |
static unsigned int elf_load(int fd, elf_header_t *header) |
static unsigned int elf_load(elf_ld_t *elf) |
{ |
elf_header_t header_buf; |
elf_header_t *header = &header_buf; |
int i, rc; |
|
rc = read(fd, header, sizeof(elf_header_t)); |
rc = read(elf->fd, header, sizeof(elf_header_t)); |
if (rc < 0) { |
printf("read error\n"); |
return EE_INVALID; |
} |
|
elf->header = header; |
|
printf("ELF-load:"); |
/* Identify ELF */ |
if (header->e_ident[EI_MAG0] != ELFMAG0 || |
164,18 → 168,27 |
printf("Object type %d is not supported\n", header->e_type); |
return EE_UNSUPPORTED; |
} |
if (header->e_type == ET_DYN) header->e_entry += RTLD_BIAS; |
|
/* The run-time dynamic linker is loaded with a bias */ |
if (header->e_type == ET_DYN) |
elf->bias = RTLD_BIAS; |
else |
elf->bias = 0; |
|
printf("parse segments\n"); |
|
/* Walk through all segment headers and process them. */ |
for (i = 0; i < header->e_phnum; i++) { |
elf_segment_header_t segment_hdr; |
|
/* Seek to start of segment header */ |
lseek(fd, header->e_phoff + i * sizeof(elf_segment_header_t), |
SEEK_SET); |
lseek(elf->fd, header->e_phoff |
+ i * sizeof(elf_segment_header_t), SEEK_SET); |
|
rc = segment_header(fd, header); |
rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t)); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
|
rc = segment_header(elf, &segment_hdr); |
if (rc != EE_OK) |
return rc; |
} |
184,16 → 197,23 |
|
/* Inspect all section headers and proccess them. */ |
for (i = 0; i < header->e_shnum; i++) { |
elf_section_header_t section_hdr; |
|
/* Seek to start of section header */ |
lseek(fd, header->e_shoff + i * sizeof(elf_section_header_t), |
SEEK_SET); |
lseek(elf->fd, header->e_shoff |
+ i * sizeof(elf_section_header_t), SEEK_SET); |
|
rc = section_header(fd, header); |
rc = read(elf->fd, §ion_hdr, sizeof(elf_section_header_t)); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
|
rc = section_header(elf, §ion_hdr); |
if (rc != EE_OK) |
return rc; |
} |
|
elf->info->entry = |
(entry_point_t)((uint8_t *)header->e_entry + elf->bias); |
|
printf("done\n"); |
|
return EE_OK; |
219,21 → 239,14 |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int segment_header(int fd, elf_header_t *elf) |
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
static elf_segment_header_t entry_buf; |
elf_segment_header_t *entry = &entry_buf; |
int rc; |
|
rc = read(fd, entry, sizeof(elf_segment_header_t)); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
|
switch (entry->p_type) { |
case PT_NULL: |
case PT_PHDR: |
break; |
case PT_LOAD: |
return load_segment(fd, entry, elf); |
return load_segment(elf, entry); |
break; |
case PT_DYNAMIC: |
case PT_INTERP: |
256,7 → 269,7 |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
int load_segment(int fd, elf_segment_header_t *entry, elf_header_t *elf) |
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry) |
{ |
void *a; |
int flags = 0; |
266,7 → 279,7 |
printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr, |
entry->p_memsz); |
|
bias = (elf->e_type == ET_DYN) ? RTLD_BIAS : 0; |
bias = elf->bias; |
|
if (entry->p_align > 1) { |
if ((entry->p_offset % entry->p_align) != |
318,7 → 331,7 |
* Load segment data |
*/ |
printf("seek to %d\n", entry->p_offset); |
rc = lseek(fd, entry->p_offset, SEEK_SET); |
rc = lseek(elf->fd, entry->p_offset, SEEK_SET); |
if (rc < 0) { printf("seek error\n"); return EE_INVALID; } |
|
printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias); |
334,7 → 347,7 |
now = 4096; |
if (now > left) now=left; |
printf("read %d...", now); |
rc = read(fd, dp, now); |
rc = read(elf->fd, dp, now); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
printf("->%d\n", rc); |
left -= now; |
351,15 → 364,8 |
* |
* @return EE_OK on success, error code otherwise. |
*/ |
static int section_header(int fd, elf_header_t *elf) |
static int section_header(elf_ld_t *elf, elf_section_header_t *entry) |
{ |
static elf_section_header_t entry_buf; |
elf_section_header_t *entry = &entry_buf; |
int rc; |
|
rc = read(fd, entry, sizeof(elf_section_header_t)); |
if (rc < 0) { printf("read error\n"); return EE_INVALID; } |
|
switch (entry->sh_type) { |
case SHT_PROGBITS: |
if (entry->sh_flags & SHF_TLS) { |
372,7 → 378,10 |
} |
break; |
case SHT_DYNAMIC: |
printf("dynamic section found\n"); |
elf->info->dynamic = |
(void *)((uint8_t *)entry->sh_addr + elf->bias); |
printf("dynamic section found at 0x%x\n", |
(uintptr_t)elf->info->dynamic); |
break; |
default: |
break; |