2 回答

TA貢獻1828條經(jīng)驗 獲得超4個贊
不要忽略第一條評論。如果您堅持使用 Go 的內(nèi)部鏈接器,該鏈接器不以與 libc 使用兼容的方式鏈接,那么您將不能使用任何 C 代碼,包括LD_PRELOAD
ed C 代碼甚至動態(tài)鏈接器本身的功能。正如 Florian(來自 glibc)在鏈接問題中所說,它對 glibc 也無效,并且只是偶然地在那里“工作”。
即使您以某種方式“機械地”弄清楚為什么沒有調(diào)用您的ctor,您仍然在損壞的進程狀態(tài)下運行C代碼,并且任何事情都可能出錯。即使您分析了所有內(nèi)容并且看起來很好,這也可以隨著下一次動態(tài)鏈接器/libc 更新而完全改變。
如果你想這樣做,請使用 Go 中的外部鏈接器選項。

TA貢獻2051條經(jīng)驗 獲得超10個贊
從評論中可以看出,Go/Alpine 環(huán)境中的靜態(tài)構(gòu)造函數(shù)存在一個主要問題。簡而言之,從 ABI 的角度來看,調(diào)用靜態(tài)構(gòu)造函數(shù)的需求分配給了可執(zhí)行文件,而不是加載程序。Go 可執(zhí)行文件不是基于 C 運行時的,它只調(diào)用依賴共享對象的靜態(tài)構(gòu)造函數(shù),而不是LD_PRELOAD-ed 共享對象。在 glibc 的情況下, a LD_PRELOAD-ed 共享對象的構(gòu)造函數(shù)由實現(xiàn)調(diào)用,而不是由加載器設(shè)計。在 musl-libc 上它們不是。
我做了一個“hack”-ish解決方法,讓現(xiàn)有的 Go 應(yīng)用程序與LD_PRELOAD-ed 共享對象一起工作。我正在使用這樣一個事實,即LD_PRELOADmusl-libc 在此環(huán)境中正確地編輯了該庫,并且 Gopthread_create在初始化的早期階段就調(diào)用了該庫。
我正在覆蓋/掛鉤-ed 共享對象pthread_create中的符號LD_PRELOAD并使用它來調(diào)用構(gòu)造函數(shù)。
#include <pthread.h>
#include <dlfcn.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
int (*pthread_create_original)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) = dlsym(RTLD_NEXT,"pthread_create");
static int already_called = 0;
if (!already_called)
{
already_called = 1;
// call here your constructors
}
return pthread_create_original(thread,attr,start_routine,arg);
}
警告:這適用于當前的 Go 運行時,但構(gòu)建此解決方案的假設(shè)遠非未來證明。Next Go 版本很容易破壞它。
- 2 回答
- 0 關(guān)注
- 154 瀏覽
添加回答
舉報