[英]Linux Iterate over ELF "section" headers during runtime
簡短版本:可以在運行時檢查所有 ELF“節”標頭,並為每個加載的共享庫獲取每個“節”標頭的重定位地址。
長版:我試圖在用戶空間中實現與內核中存在的動態調試相同的機制(dyn_debug)。 每個 LOG 宏實例在程序__attribute__((section("__verbose")))
中的特定“部分”中創建靜態變量的工作方式這迫使編譯器將變量放在“.data”部分而不是“__verbose”中部分。 以后可以通過變量__start___verbose、__stop___verbose訪問該段的起始和停止地址。 通過這種方式,一些中央例程可以查看所有已注冊的“日志”條目並按需更改屬性。 這適用於靜態鏈接的可執行文件,但是當使用共享庫時,有幾個“__verbose”部分(每個共享庫一個),一個在可執行文件本身中。 (當然,我使用 -fPIC 標志是為了包含在庫中)還與“-export-dynamic”鏈接的所有內容以確保導出所有符號。
每個共享庫和主可執行文件都有用於 init 的屬性(構造函數)方法。
我在 2 個案例中觀察到了兩種不同的行為。
case1:對於第一種情況,庫不是用 ldopen 加載的,而是由“libc 加載器”加載的
引用 __start___verbose 總是返回相同的地址(主可執行文件的地址),其中只存在“主”可執行日志條目。
dlsym(RTLD_NEXT, __start___verbose),返回“下一個”可解析庫的符號地址,所以實際上我得到了所有地址。
案例 2:使用 ldopen 加載庫
問題:除了 4 之外,用 ldopen 打開的庫有什么方法可以獲取那個符號,因為 4 需要從“加載程序”中顯式調用
代碼:
/* Main" */
void func1()
{
static int attribute__((section("__verbose"))) var = 1;
}
/* Shared library */
void func2()
{
static int attribute__((section("__verbose"))) var = 2;
}
/* Both in main and shared library
* Prints same address !!! BAD !! */
void __attribute__((constructor)) initializer()
{
struct int *iter;
for (iter = __start___verbose; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Works for libraries opened by libc runtime.
* Does not work for libraries opened with LDOPEN*/
void __attribute__((constructor)) initializer()
{
struct int *iter = ;
for (iter = dlsym(RTLD_NEXT, "__start___verbose"); iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Snippet for main doing dynamic loading */
handle = ldopen('path', RTLD_NOW)
iter = dlsym(handle, "__start___verbose")
for (; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
您不應該在運行時訪問節信息。 部分不應在運行時使用,並且可能會從可執行文件中刪除(剝離)。
我可能會使用自定義鏈接器腳本:
.__verbose:
{
PROVIDE_HIDDEN (__verbose_start = .);
*(.__verbose)
PROVIDE_HIDDEN (__verbose_end = .);
}
這為該部分定義了 HIDDEN 符號,因此每個 ELF 文件都將具有自己的這些符號版本。
然后 ELF 文件中的構造函數(或其他一些代碼)可以使用它們:
struct foo*;
extern struct foo* __verbose_start __attribute__((visibility("hidden")));
extern struct foo* __verbose_stop __attribute__((visibility("hidden")));
void __attribute__((constructor)) initializer()
{
initialize_logging(__verbose_start,__verbose_stop);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.