如何在运行时检测符号是否被剥离?

时间:2011-02-28 16:22:19

标签: c++ symbols introspection strip dlsym

在我的C ++程序中,如何在运行时以编程方式检测符号是否已通过Linux上的“strip”gnu开发工具剥离?

我想要一个函数定义,如果被剥离则返回true,否则返回false。

在“main()”上使用dlsym()是否能够可靠地检测到它?

5 个答案:

答案 0 :(得分:8)

我知道file命令可以区分,所以你可以查看它的来源,看看它使用了什么机制。

答案 1 :(得分:8)

another answer留下的评论:

被剥离的ELF将缺少.symtab条目。 file命令遍历所有ELF节标题,直到找到符号表节。如果找不到,则认为二进制被剥离。


libelf 库允许程序操作ELF目标文件,存档文件和存档成员。 elf(3E)手册页提供了与使用库相关的文档。以下代码提供了一个示例,通过查找是否存在符号表部分(.symtab)来确定是否剥离了可执行文件。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

/* Include for ELF processing */
#include <libelf.h>
#include <gelf.h>

int main(int argc, char ** argv)
{
    int fd;
    const char *file = argv[0];

    Elf *elf;       /* ELF pointer for libelf */
    Elf_Scn *scn;   /* section descriptor pointer */
    GElf_Shdr shdr; /* section header */

    /* Open ELF file to obtain file descriptor */
    if((fd = open(file, O_RDONLY)) < 0)
    {
        fprintf(stderr, "Error opening file %s\n", file);
        exit(EXIT_FAILURE);
    }

    /* Protect program from using an older library */
    if(elf_version(EV_CURRENT) == EV_NONE)
    {
        fprintf(stderr, "WARNING - ELF Library is out of date!\n");
        exit(EXIT_FAILURE);
    }

    /* Initialize elf pointer for examining contents of file */
    elf = elf_begin(fd, ELF_C_READ, NULL);

    /* Initialize section descriptor pointer so that elf_nextscn()
     * returns a pointer to the section descriptor at index 1. */
    scn = NULL;

    /* Iterate through ELF sections */
    while((scn = elf_nextscn(elf, scn)) != NULL)
    {
        /* Retrieve section header */
        gelf_getshdr(scn, &shdr);

        /* If a section header holding a symbol table (.symtab)
         * is found, this ELF file has not been stripped. */
        if(shdr.sh_type == SHT_SYMTAB)
        {
            printf("NOT STRIPPED\n");
            break;
        }
    }

    elf_end(elf);
    close(fd);
    exit(EXIT_SUCCESS);
}

答案 2 :(得分:2)

dlsym查看 strip 未触及的动态符号。静态符号表包含在未在运行时加载的部分中,因此不会出现在段表中。

一个非常好的启发式方法是观察ELF头中是否存在一个段表,它通常映射到你的进程内存,尽管动态链接器接口使得故意很难找到它。在具有dl_iterate_phdrs功能(这是标准的扩展)的典型系统上,您可以走PHDRS并在vaddr检查每个是否有ELF幻数,但那是决不会,形状或形式便携。

答案 3 :(得分:1)

你可以使用 popen()在目标应用程序上执行nm,然后parse the output来确定它是否被剥离。

nm: /bin/ls: no symbols

答案 4 :(得分:1)

readelf --sections binary_path | grep debug_info

一般来说,是否剥离二进制文件并不是一件容易的事,因为剥离文件有不同的方法。基本上剥离删除了一些与符号和调试相关的部分。但是,如果将“debug_info”替换为“debug”,则可以看到在Ubuntu发行版的标准二进制文件中仍然存在一些与调试相关的部分。