Linux ELF 文件 : Which byte will differ for static and dynamic ELF programs?

标签 linux elf binutils

我正在使用 linux elf 文件。

我想检测给定的 elf 程序是静态链接的(完全静态链接,ldd 表示“不是动态可执行文件”)还是动态链接的。 ELF 适用于嵌入式 Linux,所以我不能直接运行它或使用 ldd 实用程序。

我想通过读取和检查一些字节完全在我的程序中完成此操作。我不想依赖 file 实用程序或 libelf、binutils 等。

哪些字节会不同?

最佳答案

如何使用 ldd.c来自 μClibc ?如果你愿意,应该很容易去掉任何不需要的依赖项/检查。我认为这是一种比试图通过阅读 man 5 elf 找出所有极端情况更聪明的方法,尽管 FWIW 它看起来只是检查 PT_INTERP 程序头作为你在评论中怀疑。

更新:还有一些检查。我试图提取相关部分,但我不确定是否遗漏了任何内容,因此请自行检查。该代码检查 32 位和 64 位 x86 ELF 文件。它采用小端架构。

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <inttypes.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#include <elf.h>

int main(int argc, char* argv[])
{
    const char* fname = argv[0];
    if (argc >= 2) fname = argv[1];

    int fd;
    struct stat st;
    void *mapping;

    if ((fd = open(fname, O_RDONLY)) == -1) {
        perror(fname);
        return 1;
    }

    if (fstat(fd, &st)) {
        perror("fstat");
        close(fd);
        return 1;
    }

    if ((mapping = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return 1;
    }
    const Elf32_Ehdr* eh = mapping;

    if (st.st_size < (off_t)sizeof(Elf32_Ehdr) ||
        eh->e_ident[EI_MAG0] != ELFMAG0 || 
        eh->e_ident[EI_MAG1] != ELFMAG1 || 
        eh->e_ident[EI_MAG2] != ELFMAG2 || 
        eh->e_ident[EI_MAG3] != ELFMAG3 ||
        eh->e_ident[EI_VERSION] != EV_CURRENT) {
        printf("Not a valid ELF file\n");
        return 0;
    }

    if (eh->e_type != ET_EXEC && eh->e_type != ET_DYN) {
        printf("Not executable or shared object\n");
        return 0;
    }

    int is_dynamic = 0;

    // change as appropriate, but remember that byteswapping might be needed in some cases
    if (eh->e_ident[EI_CLASS] == ELFCLASS32 && eh->e_ident[EI_DATA] == ELFDATA2LSB && eh->e_machine == EM_386) {
        uint16_t ph_cnt;
        for (ph_cnt = 0; ph_cnt < eh->e_phnum; ph_cnt++) {
            const Elf32_Phdr* ph = (const Elf32_Phdr*)((const uint8_t*)mapping + eh->e_phoff + ph_cnt * eh->e_phentsize);
            if (ph->p_type == PT_DYNAMIC || ph->p_type == PT_INTERP) {
                is_dynamic = 1;
            }
        }
    } else if (eh->e_ident[EI_CLASS] == ELFCLASS64 && eh->e_ident[EI_DATA] == ELFDATA2LSB && eh->e_machine == EM_X86_64) {
        const Elf64_Ehdr* eh = mapping;
        uint16_t ph_cnt;
        for (ph_cnt = 0; ph_cnt < eh->e_phnum; ph_cnt++) {
            const Elf64_Phdr* ph = (const Elf64_Phdr*)((const uint8_t*)mapping + eh->e_phoff + ph_cnt * eh->e_phentsize);
            if (ph->p_type == PT_DYNAMIC || ph->p_type == PT_INTERP) {
                is_dynamic = 1;
            }
        }
    } else {
        printf("Unsupported architecture\n");
        return 0;
    }

    munmap(mapping, st.st_size);
    close(fd);
    printf("%s: %sdynamic\n", fname, is_dynamic?"":"not ");
    return 0;
}

关于Linux ELF 文件 : Which byte will differ for static and dynamic ELF programs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7298365/

相关文章:

linux - 在 Raspberry Pi Qt 中自动播放视频

linux - 为什么堆栈程序段具有可执行属性

c - 如何基本上加密 ELF 二进制文件中的文本?

linker - 添加到 gnu ld 库搜索路径的 *end*

python - 如果在某些程序正在从该文件读取数据时删除输入文件,会发生什么情况?

c - 结构与 union : structure has no member named

linux - OpenJDK 与甲骨文

linux - 如何覆盖 Linux 下 elf 可执行文件的 .interp header 中指定的链接器?

gcc - 确定 GNU binutils 的目标和架构的 "correct"方法是什么?

c - 使用 Debug模式构建 binutils