2011-07-08 56 views
7

在運行時我需要打印出一個地址,然後找到該地址屬於哪個函數。這些功能位於共享庫中,因此不在固定地址。我的地圖文件顯然只是顯示每個共享庫func的相對偏移量。是否有可能在運行時查詢庫的加載位置,以便我可以從我的地址中減去該值以獲得正確的映射文件偏移量?在Linux中查找共享庫的加載地址

目前我正在做一個稍微哈克計算策略,由此我還打印出庫中的一個函數的地址,然後找到在地圖文件功能,找出其中的加載地址必須是。我寧願有一個通用的方法,不需要你命名參考函數。

(GDB在我的設置中不可用)。 謝謝。

回答

4

在最近的Linux,你可以用dl_iterate_phdr找出共享庫的地址。

1

GNU backtrace library?

我不會依賴hacky的方法來做這樣的事情。我不認爲有任何保證庫的內容被加載到連續的內存中。

3

試着看看/ proc/[PID]/maps文件。 這應該包含進程內存地址空間中庫映射的地址。

如果你想達到的可執行部分,在圖書館使用readelf並找到.text段的偏移量。

7

dladdr做到了這一點,結束了。 :-)

更爲全面的是,dladdr會獲取一個地址並計算出它對應的庫和符號......然後它會給你庫的名稱,符號的名稱和基地每個地址。我個人認爲這很好,這也讓我目前的調試工作變得更容易。

希望這會有所幫助!

1

檢查System V ABI, chapter 5。對於懶惰的在那裏,這裏是爲支持ELF二進制格式系統做到這一點的標準方式:

#include <link.h> 

off_t load_offset; 
for (Elf64_Dyn *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) { 
    if (dyn->d_tag == DT_DEBUG) { 
     struct r_debug *r_debug = (struct r_debug *) dyn->d_un.d_ptr; 
     struct link_map *link_map = r_debug->r_map; 
     while (link_map) { 
      if (strcmp(link_map->l_name, libname) == 0) { 
       load_offset = (off_t)link_map->l_addr; 
       break; 
      } 
      link_map = link_map->l_next; 
     } 
     break; 
    } 
} 

這不依賴於任何GNU擴展。

在GNU系統中,宏ElfW(dyn)表示將返回Elf64_Dyn或Elf32_Dyn這是很方便。