gpt4 book ai didi

LD_PRELOAD-ing go 可执行文件时未调用共享对象中的构造函数

转载 作者:行者123 更新时间:2023-12-01 20:22:57 27 4
gpt4 key购买 nike

在 Alpine 镜像中构建的 GO 可执行文件存在一个奇怪的行为,其中标准 LD_PRELOAD 功能无法正常工作。

看起来像 构造函数未被调用 由动态加载器!

我有一个示例 go 应用程序(getgoogle.go):

package main

import (
"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 图像)创建一个基于 debian 的 docker 图像:
FROM golang
COPY libldptest.c hello-world.go /
RUN gcc -shared -o /libldptest.so /libldptest.c
RUN go build -gcflags='-N -l' -o /getgoogle /getgoogle.go
ENV LD_PRELOAD=/libldptest.so

然后运行以下命令:
$docker run -it gotest /getgoogle
>>> LD_PRELOADED!
200

这意味着构造函数在这里工作。

但是当对基于 alpine 的 docker 镜像做同样的事情时
FROM golang:1.12-alpine
RUN apk add gcc libc-dev
COPY libldptest.c hello-world.go /
RUN gcc -shared -o /libldptest.so /libldptest.c
RUN go build -gcflags='-N -l' -o /getgoogle /getgoogle.go
ENV LD_PRELOAD=/libldptest.so

并运行与上面相同的命令
$docker run -it gotest /getgoogle
200
$docker run -it gotest ls
>>> LD_PRELOADED!
bin src

这意味着运行 go 应用程序时未调用静态构造函数! (但在运行 ls 时被调用)

请注意,我已经检查过动态加载程序是否将库添加到进程空间。

我很感激能理解它为什么不起作用。

最佳答案

不要忽略第一条评论。如果你坚持使用 Go 的内部链接器,它不以与 libc 兼容的方式链接,那么你不能使用任何 C 代码,包括 LD_PRELOAD ed C 代码甚至是动态链接器本身的特性。正如 Florian(来自 glibc)在链接问题中所说,它对 glibc 也无效,并且只是偶然地在那里“工作”。

即使您以某种方式“机械地”弄清楚为什么没有调用您的ctor,您仍然在损坏的进程状态下运行C代码并且任何事情都可能出错。即使您分析了所有内容并且看起来很好,这也可以随着下一次动态链接器/libc 更新而完全改变。

如果你想这样做,请使用 Go 中的外部链接器选项。

关于LD_PRELOAD-ing go 可执行文件时未调用共享对象中的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61885554/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com