2011-07-12 31 views
3

我正在研究分析ELF和PE格式(學校類型/研究項目)中的對象文件的程序。現在我正要處理可執行文件中的動態導入符號。我想盡可能多地找到關於符號的信息。以ELF格式導入符號的源共享庫的名稱

在PE格式中,導入存儲在.idata部分。有幾張表有不同的信息,但對我來說有趣的是,找出哪個庫是符號定義沒有問題。總是有共享庫的名稱,然後是從其中導入的符號的名稱/序號。

我想在ELF文件中找到這種信息。所有進口/出口都在.dynsym部分 - 動態符號表。那些被導入的符號被標記爲undefined,例如:

00000000  DF *UND* 00000000 GLIBC_2.0 fileno 

但是沒有信息,這個符號的源文件是什麼。所有所需的共享庫在.dynamic部分中列出,例如:

Dynamic Section: 
    NEEDED    libz.so.1 

大約在符號庫唯一信息是版本字符串= GLIBC_2.0。我想通過這個越來越現實的庫名,但是當我看到的objdump -p輸出我發現GLIBC_2.0可與多個庫連接:

Version References: 
    required from libm.so.6: 
    0x0d696910 0x00 13 GLIBC_2.0 
    required from libgcc_s.so.1: 
    0x0b792650 0x00 12 GLIBC_2.0 

如果我理解正確的ELF動態鏈接過程,在ELF可執行文件中找不到這些信息是不可能的。從哪裏輸入的符號在鏈接器將所有符號表加載到內存後確定。 但我想在我繼續之前確定這一點,所以我的問題是:有沒有什麼辦法可以從ELF可執行文件中找到符號共享庫的名稱?

謝謝你的任何建議。

回答

0

幾個月前,我正在研究相當類似的東西 - 我能夠通過將源代碼轉換爲nm和readelf來回答我所有的問題。 (見http://ftp.gnu.org/gnu/binutils/) 我發現這也很有用 - >http://www.skyfree.org/linux/references/ELF_Format.pdf

+0

那麼,我研究了objdump的來源和BFD的一點點。我讀過ELF規範。基於這一點,我認爲不可能將庫名稱分配給動態符號表中的符號,除非它實際上是動態鏈接的。但我不能說我對此絕對有把握,而且在繼續前我想和一個比我有更多經驗的人討論。 –

+0

啊 - 好的。我不認爲我理解你的原始問題。爲了澄清 - 你想根據符號找到使用的庫文件,是嗎?在Linux中,這由程序加載程序完成 - 它將符號與庫的緩存進行匹配。請參閱http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html – Josh

+0

是的,我想知道是否可以將庫的名稱分配給每個導入的符號 - 它定義的庫以及從哪個庫它將在僅基於可執行文件中的數據進行動態鏈接期間鏈接,而無需實際加載和搜索共享對象。 –

0

好的,所以它可能一般不可能分配庫名稱到每個導入的符號。但我可能通過符號版本發現瞭解決方案。當然,每個ELF文件中不必包含sybol版本部分。

struct elf_obj_tdata *pElf = bfdFile->tdata.elf_obj_data; 
for (long i = 0; i < dynNumSyms; i++) 
{ 
    asymbol *dynSym = dynSymTab[i]; 

    // If there is version information in file. 
    if (pElf->dynversym_section != 0 
     && (pElf->dynverdef_section != 0 
     || pElf->dynverref_section != 0)) 
    { 
     unsigned int vernum; 
     const char *version_string; 
     const char *fileName; 

     vernum = ((elf_symbol_type *) dynSym)->version & VERSYM_VERSION; 

     if (vernum == 0) // local sym 
      version_string = ""; 
     else if (vernum == 1) // global sym, defined in this object 
      version_string = "Base"; 
     else if (vernum <= pElf->cverdefs) 
      version_string = pElf->verdef[vernum - 1].vd_nodename; 
     else 
    { 
     Elf_Internal_Verneed *t; 

     version_string = ""; 
     fileName = ""; 

     // Iterate through all Verneed entries - all libraries 
     for (t = pElf->verref; t != NULL; t = t->vn_nextref) 
     { 
      Elf_Internal_Vernaux *a; 

      // Iterate through all Vernaux entries 
      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) 
      { 
       // Find associated entry 
       if (a->vna_other == vernum) 
       { 
        version_string = a->vna_nodename; 
        fileName = t->vn_filename; 
        break; 
       } 
      } 
     } 

     // here we have got: 
     // name of symbol = dynSym->name 
     // version string = version_string 
     // name of library = fileName 
    } 
    } 
} 

那麼你覺得什麼,這是正確的?

+0

你最終得出結論嗎?如果是,那是什麼?我在問自己完全相同的問題...... – stackoverflowwww