静态链接libc的正确方法是什么?

时间:2019-12-24 01:18:57

标签: gcc linker

我在这里和其他论坛上看到了很多问题,建议使用-static或有时甚至使用-static -static-libgcc以及编译参数。这在Alpine上永远无法使用,但是在Ubuntu和Fedora上可以正常使用。

我用C语言编写了一个简单的hello-world程序,然后将其编译为gcc -static test.c。并且生成的二进制文件仍然点亮ldd。看到

$ gcc -s test.c -static
$ ldd ./a.out
    /lib/ld-musl-x86_64.so.1 (0x7f043eae8000)

$ file ./a.out
./a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped

在Ubuntu上运行相同的内容显示:

$ gcc -s test.c -static                   
$ file ./a.out 
./a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=bf6bfa1c78c541ae4e81586bcd050923bca9e34a, stripped

在任何平台上静态链接libc本身的正确且一致的方法是什么?这与GCC本身的编译方式有关吗?

3 个答案:

答案 0 :(得分:0)

您的Ubuntu二进制文件未启用PIE。如果您将-no-pie传递给Alpine上的GCC,则其二进制文件同样不会启用PIE,但随后会根据需要进行静态链接。

答案 1 :(得分:0)

对于那些天真的来到这里搜索static之类的关键字的人,我在这里回答自己的问题。

如果这是用于MSVC,则唯一的选择是#include <stdio.h> #include <stdlib.h> #define ll long long int main() { ll int N; scanf("%lld", &N); /// The plain "%d" format expects an "int" argument - use "%lld" for "long long int" ll int i, j, a, b; ll int TOTAL = 0; /// If you don't INITIALIZE "TOTAL" it could start off with ANY value whatsoever! typedef struct { ll int flag; ll int count; // int fc[N]; // farmer cost OR cost for farmer i ll int* fc; } land; // check whether all of them have been // initialised to 0 // printf("%d ", arr[2][2].count); // yes static land arr[1000][1000]; /// Without "static" this array (~ 24 Megabytes) will overflow the stack! for (i = 0; i < 1000; i++) { for (j = 0; j < 1000; j++) { arr[i][j].fc = (ll int*)calloc(N, sizeof(ll int)); } } ll int x1, y1, x2, y2, c; ll int ta, tb; // temp a // temp b for (i = 0; i < N; i++) { scanf("%lld %lld %lld %lld %lld", &x1, &y1, &x2, &y2, &c); // the array index starts from 0 // so to match the inputs to the correct indices // the inputs must be reduced by one for (a = x1; a <= x2; a++) { for (b = y1; b <= y2; b++) { ta = a - 1; tb = b - 1; arr[ta][tb].count++; if (arr[ta][tb].count >= 2) arr[ta][tb].flag = 1; arr[ta][tb].fc[i] = c; } } } ll int k; for (i = 0; i < 1000; i++) { for (j = 0; j < 1000; j++) { if (arr[i][j].flag == 1) { for (k = 0; k < N; k++) TOTAL += arr[i][j].fc[k]; } } } printf("%lld", TOTAL); return 0; } static link libc。但是,如果您是来这里寻找GCC的,欢迎来到位置独立的代码兔子洞。

有一些GCC浮动版本,它们针对特定目标进行了修补,或者只是因为可以被修补。因此,如果您拥有GCC 6.0版,并且希望您的命令行参数生成相同的行为,那么您可能会成为某些不良补丁程序的受害者。

此问题中的某些版本的GCC强制执行位置无关的可执行文件(/MT),并且无声地忽略了/MTd选项,如本示例所示。我想知道是否应该向Alpine维护人员报告此错误。要强制其忽略PIE,请将-fPIE -pie传递到您的GCC。

-static

如果可以的话

-no-pie

有关$ gcc -no-pie -static test.c $ file ./a.out /lib/ld-musl-x86_64.so.1: ./a.out: Not a valid dynamic program 如何从OpenBSD读取这些slides的详细信息。

答案 2 :(得分:0)

您可能构建得很好,它看起来更像是 file 中的错误。请参阅此错误报告: https://bugs.astron.com/view.php?id=93

<块引用>

摘要:0000093:文件错误地识别了 -static-pie 二进制文件

我在构建 QEMU 时遇到了同样的问题,但我被告知上述内容: https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/21214#note_156907