I have troubles with ELF executing [FIXED]

50 Views Asked by At

Hello everyone who sees this question. I have a problem. First of all, I'm currently writing an ELF reader in my kernel and now I have one problem. This problem is in the strings. What I mean is that if we have two code snippets like the below one:

printf("HELLO\n");

And

char msg[10] = "HELLO\n";
printf(msg);

Only the second one will work in the executable program. This is not a problem with printf, I have fully tested this function. The difference is in the line: in the first example, "HELLO\n" will be located at the end of the ELF file, in the second - closer to the beginning. But I also checked what data is loaded into ELF_exe_buffer in first case - and the rows are loaded. I don't know why I am getting this error, please help. I attach the ELF reader code below (this function is based on elf reader code from amateur OS)

ELF reader (amateur OS) - https://github.com/queso-fuego/amateuros/blob/master/include/elf/elf.h

void* ELF_exe_buffer;

void* ELF_read(const char* path) {
    struct FATContent* content = FAT_get_content(path);
    if (content->file == NULL) {
        kprintf("File not found\n");
        return NULL;
    }

    char* file_content = FAT_read_content(content);
    char* header_content = file_content;

    Elf32_Ehdr *ehdr = (Elf32_Ehdr*)header_content;
    if (ehdr->e_ident[0] != '\x7f' || ehdr->e_ident[1] != 'E') {
        kprintf("\r\nError: Not ELF.\r\n");
        free(file_content);
        return NULL;
    }

    if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
        kprintf("\r\nError: Program is not an executable or dynamic executable.\r\n");
        free(file_content);
        return NULL;
    }

    Elf32_Phdr* phdr = (Elf32_Phdr*)(header_content + ehdr->e_phoff);

    uint32_t mem_min   = 0xFFFFFFFF, mem_max = 0;
    uint32_t alignment = PAGE_SIZE;
    uint32_t align     = alignment;

    for (uint32_t i = 0; i < ehdr->e_phnum; i++) {
        if (phdr[i].p_type != PT_LOAD) continue;
        if (align < phdr[i].p_align) align = phdr[i].p_align;

        uint32_t mem_begin = phdr[i].p_vaddr;
        uint32_t mem_end = phdr[i].p_vaddr + phdr[i].p_memsz + align - 1;

        mem_begin &= ~(align - 1);
        mem_end &= ~(align - 1);

        if (mem_begin < mem_min) mem_min = mem_begin;
        if (mem_end > mem_max) mem_max = mem_end;
    }

    uint32_t buffer_size = mem_max - mem_min;
    uint32_t buffer_alignment = align - 1;
    ELF_exe_buffer = calloc(1, buffer_size);
    if (ELF_exe_buffer == NULL) {
        kprintf("\r\nError: Could not malloc() enough memory for program\r\n");
        free(file_content);
        return NULL;
    }

    memset(ELF_exe_buffer, 0, buffer_size);
    for (uint32_t i = 0; i < ehdr->e_phnum; i++) {
        if (phdr[i].p_type != PT_LOAD) continue;

        uint32_t relative_offset = phdr[i].p_vaddr - mem_min;

        uint8_t* dst = (uint8_t*)ELF_exe_buffer + relative_offset; 
        uint8_t* src = file_content + phdr[i].p_offset;
        uint32_t len = phdr[i].p_memsz;

        memcpy(dst, src, len);
    }

    free(file_content);
    FAT_unload_content_system(content);
    return (void*)((uint8_t*)ELF_exe_buffer + (ehdr->e_entry - mem_min));
}

Fixed by adding to CCFLAGS "-fpic" flag

1

There are 1 best solutions below

0
Employed Russian On

This problem is in the strings.

The code is obviously wrong.

An EX_EXEC binary will only run correctly if loaded at the linked-at address (the address in the .p_vaddr of the first LOAD segment), but your code loads it into an arbitrary memory location (returned from calloc).

For ET_DYN, the code is even more wrong (unless the binary is a fully-static ET_DYN). In general ET_DYN (as well as ET_EXEC) binaries require that you pay attention to PT_INTERP in them.

Fixed by adding to CCFLAGS "-fpic" flag

If by that you mean that building ET_EXEC with -fpic allows your code to run such binary successfully, that probably fixes some of the issues of running ET_EXEC at a different address from where it was linked, but I doubt that fixes all such issues.