80 lines
1.7 KiB
C
80 lines
1.7 KiB
C
#include "exe.h"
|
|
|
|
#include "elf.h"
|
|
|
|
static enum ec3_status get_elf_executable_info(
|
|
FILE *fp,
|
|
struct ec3_tag_executable_info *out)
|
|
{
|
|
elf_ehdr_t hdr;
|
|
fseek(fp, 0, SEEK_SET);
|
|
size_t r = fread(&hdr, sizeof hdr, 1, fp);
|
|
if (r != 1) {
|
|
return EC3_ERR_IO_FAILURE;
|
|
}
|
|
|
|
out->exe_elf.elf_entry = hdr.e_entry;
|
|
|
|
bool text_found = false, data_found = false;
|
|
|
|
for (size_t i = 0; i < hdr.e_phnum; i++) {
|
|
elf_phdr_t phdr;
|
|
size_t offset = hdr.e_phoff + (i * hdr.e_phentsize);
|
|
fseek(fp, offset, SEEK_SET);
|
|
r = fread(&phdr, sizeof phdr, 1, fp);
|
|
|
|
if (r != 1) {
|
|
return EC3_ERR_IO_FAILURE;
|
|
}
|
|
|
|
if (phdr.p_type != PT_LOAD) {
|
|
continue;
|
|
}
|
|
|
|
if ((phdr.p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) {
|
|
if (text_found) {
|
|
out->exe_format = EC3_EXEC_OTHER;
|
|
return EC3_SUCCESS;
|
|
}
|
|
|
|
out->exe_elf.elf_text_offset = phdr.p_offset;
|
|
out->exe_elf.elf_text_filesz = phdr.p_filesz;
|
|
out->exe_elf.elf_text_vaddr = phdr.p_vaddr;
|
|
out->exe_elf.elf_text_memsz = phdr.p_memsz;
|
|
out->exe_elf.elf_text_align = phdr.p_align;
|
|
text_found = true;
|
|
}
|
|
|
|
if ((phdr.p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) {
|
|
if (data_found) {
|
|
out->exe_format = EC3_EXEC_OTHER;
|
|
return EC3_SUCCESS;
|
|
}
|
|
|
|
out->exe_elf.elf_data_offset = phdr.p_offset;
|
|
out->exe_elf.elf_data_filesz = phdr.p_filesz;
|
|
out->exe_elf.elf_data_vaddr = phdr.p_vaddr;
|
|
out->exe_elf.elf_data_memsz = phdr.p_memsz;
|
|
out->exe_elf.elf_data_align = phdr.p_align;
|
|
data_found = true;
|
|
}
|
|
}
|
|
|
|
return EC3_SUCCESS;
|
|
}
|
|
|
|
enum ec3_status get_executable_info_from_file(
|
|
FILE *fp,
|
|
enum ec3_executable_format format,
|
|
struct ec3_tag_executable_info *out)
|
|
{
|
|
out->exe_format = format;
|
|
|
|
switch (format) {
|
|
case EC3_EXEC_ELF:
|
|
return get_elf_executable_info(fp, out);
|
|
default:
|
|
return EC3_SUCCESS;
|
|
}
|
|
}
|