2011-09-04 52 views
4

我正在使用linux精靈文件。Linux ELF文件:對於靜態和動態ELF程序,哪個字節會有所不同?

我想檢測,如果給定的精靈程序是靜態鏈接的(全靜態鏈接,ldd說「not a dynamic executable」)或動態鏈接。 ELF適用於嵌入式Linux,因此我不能運行它或使用ldd實用程序。

我想完全在我的程序中,通過閱讀和檢查一些字節。我不想依靠file實用程序或libelf,binutils等。

哪些字節會不同?

+0

我想你需要尋找一個DYNAMIC程序標題 –

+0

或INTERP PH? – osgx

回答

4

如何使用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; 
} 
+0

這看起來不錯。它幾乎不依賴於外部工具。 – osgx

+0

這是一個足夠大的代碼塊,顯然來源於現有的東西,我認爲你應該說明你認爲適用的許可證。 –

+0

@Chris Stratton:mmap部分來自[我的評論8月27日8:59](http://stackoverflow.com/questions/7193880/assembly-of-pic/7207824#7207824),其餘從閱讀'人5精靈'。檢查的靈感來自閱讀鏈接的LDD源代碼,所以我很好,保持GPLv2爲uClibc。 – user786653