Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux ELF文件:静态和动态ELF程序的哪个字节不同?_Linux_Elf_Binutils - Fatal编程技术网

Linux ELF文件:静态和动态ELF程序的哪个字节不同?

Linux ELF文件:静态和动态ELF程序的哪个字节不同?,linux,elf,binutils,Linux,Elf,Binutils,我正在处理linux elf文件 我想检测给定的elf程序是静态链接(完全静态链接,ldd表示“不是动态可执行文件””)还是动态链接。ELF是用于嵌入式Linux的,所以我不能只运行它或使用ldd实用程序 我想在我的程序中完全做到这一点,通过读取和检查一些字节。我不想依赖文件实用程序或libelf、binutils等 哪些字节将不同?使用from如何?如果您愿意,去除任何不需要的依赖项/检查应该相当容易。我认为这是一种比试图通过阅读man5elf找出所有角落案例更聪明的方法,尽管FWIW看起来只

我正在处理linux elf文件

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

我想在我的程序中完全做到这一点,通过读取和检查一些字节。我不想依赖
文件
实用程序或libelf、binutils等

哪些字节将不同?

使用from如何?如果您愿意,去除任何不需要的依赖项/检查应该相当容易。我认为这是一种比试图通过阅读
man5elf
找出所有角落案例更聪明的方法,尽管FWIW看起来只是检查
PT_INTERP
程序头,正如您在评论中怀疑的那样

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

#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
常量char*fname=argv[0];
如果(argc>=2)fname=argv[1];
int-fd;
结构统计;
void*映射;
如果((fd=open(fname,orduonly))=-1){
佩罗尔(fname);
返回1;
}
if(fstat(fd和st)){
佩罗尔(“fstat”);
关闭(fd);
返回1;
}
if((映射=mmap(NULL,st.st_大小,PROT_读取,MAP_共享,fd,0))==MAP_失败){
佩罗尔(“mmap”);
关闭(fd);
返回1;
}
常量Elf32_Ehdr*eh=映射;
如果(st.st_尺寸<(关闭)尺寸为(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_版本]!=EV_当前){
printf(“不是有效的ELF文件\n”);
返回0;
}
如果(eh->e_type!=ET_EXEC&&eh->e_type!=ET_DYN){
printf(“非可执行或共享对象”);
返回0;
}
int是_dynamic=0;
//根据需要进行更改,但请记住,在某些情况下可能需要byteswapping
如果(eh->e_-ident[EI_-CLASS]==ELFCLASS32&&eh->e_-ident[EI_-DATA]==ELFDATA2LSB&&eh->e_-machine==EM_386){
uint16_t ph_cnt;
对于(ph_cnt=0;ph_cnte_phnum;ph_cnt++){
常量Elf32_Phdr*ph=(常量Elf32_Phdr*)((常量uint8_t*)映射+eh->e_phoff+ph_cnt*eh->e_phentsize);
如果(ph->p|U类型==PT|U动态| ph->p|U类型==PT|U内部){
is_dynamic=1;
}
}
}如果(eh->e_ident[EI_CLASS]==elf类64&&eh->e_ident[EI_数据]==elf数据2lsb&&eh->e_机器==EM_X86_64){
常量Elf64_Ehdr*eh=映射;
uint16_t ph_cnt;
对于(ph_cnt=0;ph_cnte_phnum;ph_cnt++){
常量Elf64_Phdr*ph=(常量Elf64_Phdr*)((常量uint8_t*)映射+eh->e_phoff+ph_cnt*eh->e_phentsize);
如果(ph->p|U类型==PT|U动态| ph->p|U类型==PT|U内部){
is_dynamic=1;
}
}
}否则{
printf(“不支持的体系结构\n”);
返回0;
}
munmap(地图,圣约翰大小);
关闭(fd);
printf(“%s:%sdynamic\n”,fname,是动态的吗?”:“不是”);
返回0;
}

我想你需要找一个动态的节目主持人这看起来不错。它几乎不依赖于外部工具。这是一个足够大的代码块,显然是从现有的东西中派生出来的,我认为您应该说明您认为将应用的许可证。@Chris Stratton:mmap部分来自,其余部分来自阅读
man 5 elf
。检查的灵感来自于阅读链接的ldd源代码,所以我可以将它保留为uClibc的GPLv2。Chris Stratton,我不会复制代码,我只想知道idea和字段的名称。代码由used发布,是他自己的,是CC-by。如果我复制这个密码,我会在密码里提到他的名字。