第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

LD_PRELOAD-ing go 可執(zhí)行文件時未調(diào)用共享對象中的構(gòu)造函數(shù)

LD_PRELOAD-ing go 可執(zhí)行文件時未調(diào)用共享對象中的構(gòu)造函數(shù)

Go
守著星空守著你 2022-06-06 14:42:48
在 Alpine 映像中構(gòu)建的 GO 可執(zhí)行文件存在一個奇怪的行為,其中標準 LD_PRELOAD 功能無法正常工作??雌饋韯討B(tài)加載器沒有調(diào)用構(gòu)造函數(shù)!我有一個例子去應(yīng)用程序(getgoogle.go):package mainimport (    "fmt"    "net/http")func main() {    resp, err := http.Get("http://google.com/")    if err == nil {        fmt.Println(resp.StatusCode)    }}以及示例共享對象代碼 ( libldptest.c)#include <stdio.h>static void __attribute__((constructor)) StaticConstructor(int argc, char **argv, char **env){    printf(">>> LD_PRELOADED!\n");}我正在使用這個 Dockerfile(gotest圖像)創(chuàng)建一個基于 debian 的 docker 圖像:FROM golangCOPY libldptest.c hello-world.go /RUN gcc -shared -o /libldptest.so /libldptest.cRUN go build -gcflags='-N -l' -o /getgoogle /getgoogle.goENV LD_PRELOAD=/libldptest.so然后運行以下命令:$docker run -it gotest /getgoogle>>> LD_PRELOADED!200這意味著構(gòu)造函數(shù)在這里工作。但是當對基于 alpine 的 docker 鏡像做同樣的事情時FROM golang:1.12-alpineRUN apk add gcc libc-devCOPY libldptest.c hello-world.go /RUN gcc -shared -o /libldptest.so /libldptest.cRUN go build -gcflags='-N -l' -o /getgoogle /getgoogle.goENV LD_PRELOAD=/libldptest.so并運行與上面相同的命令$docker run -it gotest /getgoogle200$docker run -it gotest ls>>> LD_PRELOADED!bin  src這意味著運行 go 應(yīng)用程序時未調(diào)用靜態(tài)構(gòu)造函數(shù)?。ǖ谶\行時被調(diào)用ls)請注意,我已經(jīng)檢查過動態(tài)加載程序是否將庫添加到進程空間。我很感激能理解它為什么不起作用。
查看完整描述

2 回答

?
明月笑刀無情

TA貢獻1828條經(jīng)驗 獲得超4個贊

不要忽略第一條評論。如果您堅持使用 Go 的內(nèi)部鏈接器,該鏈接器不以與 libc 使用兼容的方式鏈接,那么您將不能使用任何 C 代碼,包括LD_PRELOADed C 代碼甚至動態(tài)鏈接器本身的功能。正如 Florian(來自 glibc)在鏈接問題中所說,它對 glibc 也無效,并且只是偶然地在那里“工作”。

即使您以某種方式“機械地”弄清楚為什么沒有調(diào)用您的ctor,您仍然在損壞的進程狀態(tài)下運行C代碼,并且任何事情都可能出錯。即使您分析了所有內(nèi)容并且看起來很好,這也可以隨著下一次動態(tài)鏈接器/libc 更新而完全改變。

如果你想這樣做,請使用 Go 中的外部鏈接器選項。


查看完整回答
反對 回復(fù) 2022-06-06
?
侃侃無極

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 版本很容易破壞它。


查看完整回答
反對 回復(fù) 2022-06-06
  • 2 回答
  • 0 關(guān)注
  • 154 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號