我在 ELF 执行 [已修复] 时遇到问题

问题描述 投票:0回答:1

看到这个问题的大家好。我有个问题。首先,我目前正在内核中编写 ELF 阅读器,现在遇到一个问题。这个问题出在字符串上。我的意思是,如果我们有两个如下所示的代码片段:

printf("HELLO\n");

还有

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

只有第二个可以在可执行程序中工作。这不是printf的问题,我已经充分测试了这个功能。区别在于行:在第一个示例中,“HELLO “将位于 ELF 文件的末尾,在第二个中 - 更接近开头。但我还检查了第一种情况下将哪些数据加载到 ELF_exe_buffer 中 - 并且加载了行。我不知道为什么我得到这个错误,请帮忙。我在下面附上了ELF阅读器代码(该功能基于来自业余操作系统的elf阅读器代码)

ELF 阅读器(业余操作系统)- 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));
}

通过添加到 CCFLAGS“-fpic”标志来修复

elf osdev
1个回答
0
投票

这个问题出在弦上。

代码显然是错误的。

如果在链接地址(第一个

EX_EXEC
段的.p_vaddr中的地址)加载,则
LOAD
二进制文件将
正确运行,但是您的代码将其加载到任意内存位置(从
calloc
)。

对于

ET_DYN
,代码更加错误(除非二进制文件是完全静态的
ET_DYN
)。一般来说,
ET_DYN
(以及
ET_EXEC
)二进制文件要求您注意其中的
PT_INTERP

通过添加到 CCFLAGS“-fpic”标志来修复

如果您的意思是使用

ET_EXEC
构建
-fpic
允许您的代码成功运行此类二进制文件,则可能会解决在与其链接的地址不同的地址运行
ET_EXEC
的一些问题,但我怀疑这一点解决所有此类问题。

© www.soinside.com 2019 - 2024. All rights reserved.