在 64 位机器上使用静态链接库编译位置无关的可执行文件

Compile position-independent executable with statically linked library on 64 bit machine

当我尝试使用以下命令行进行编译时:

g++ code.cpp /usr/lib/x86_64-linux-gnu/libcrypto.a -ldl -Fpie -pie -o executable

我收到以下错误消息:

/usr/bin/ld: /tmp/ccNHn5FA.o: Die Umlagerung von 
/tmp/ccNHn5FA.o: error adding symbols: Ungültiger Wert
collect2: error: ld returned 1 exit status

我想知道为什么这不起作用,因为完全相同的命令行在我的 32 位机器上工作正常。我做错了什么?

When I try to compile with the following command-line:

g++ code.cpp /usr/lib/x86_64-linux-gnu/libcrypto.a -ldl -Fpie -pie -o executable

I get the following error message...

编辑:我刚刚注意到 -Fpie。我不相信那是一面真正的旗帜。 -fPIC-fPIE 是编译器标志。 -pie 是程序的 linker 标志,-shared 是共享对象的等效 linker 标志。

/usr/lib/x86_64-linux-gnu/libcrypto.a 中的目标文件需要用 -fPIC-fPIE 编译。

存档只是目标文件的集合。我相信readelf -rR会告诉你里面有没有搬迁信息:

$ mkdir objects
$ cd objects/
$ cp /usr/lib/x86_64-linux-gnu/libcrypto.a .
$ ar x libcrypto.a 
$ ls
a_bitstr.o           cryptlib.o             gost_asn1.o         rsa_lib.o
...
$ readelf --relocs cryptlib.o 

Relocation section '.rela.text' at offset 0x2700 contains 133 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000008  000400000002 R_X86_64_PC32     0000000000000000 .bss + 9b
000000000010  001f00000004 R_X86_64_PLT32    0000000000000000 BUF_strdup - 4
...
Relocation section '.rela.data.rel.ro.local' at offset 0x3378 contains 41 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000000  000500000001 R_X86_64_64       0000000000000000 .rodata.str1.1 + 3e
000000000008  000500000001 R_X86_64_64       0000000000000000 .rodata.str1.1 + 48
...
Relocation section '.rela.eh_frame' at offset 0x3750 contains 36 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
000000000058  000200000002 R_X86_64_PC32     0000000000000000 .text + b0
...

对于openssl,下载最新的可能最简单,然后用shared配置得到-fPIC。另请参阅 OpenSSL wiki 上的 Compilation and Installation

相关,见。它是在 Android 的上下文中提出的,但它也适用于此处。它解释了为什么 -fPIC-fPIE 都有效。


(comment) Why does this work on my 32 bit machine? Why is the result of the hardening-check (cheks if pie or not) negative when I compile only with -fPIC or -fPIE?

32 位和 64 位有不同的要求,所以我相信 32 位 i386 机器上的东西 "just work"。但是 64 位 x86_64 机器需要 -fPIE-fPIC其他人将不得不为您提供详细信息,因为我不认识他们。这里有一个 question/answer 应该解释一下:Why does gcc not implicitly supply the -fPIC flag when compiling static libraries on x86_64

您的强化检查可能失败了,因为您编译时使用了重定位信息(-fPIC-fPIE),但您没有 link 使用重定位信息(-pie 对于程序或 -shared 用于共享对象)。因此 linker.

没有将相关部分添加到 Elf 二进制文件中

相关的,Tobias Klein 有一个名为 Checsec for auditing Elf binaries. Its similar to Microsoft's BinScope 的简洁工具。

我一直用它来验收测试二进制文件。 (我从事软件安全工作,这是我使用最佳实践确保程序符合规范的技巧之一)。