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

时间:2015-06-01 12:14:57

标签: c++ compilation openssl static-libraries 32bit-64bit

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

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位机器上完全相同的命令行工作正常。我做错了什么?

1 个答案:

答案 0 :(得分:1)

  

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

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

我收到以下错误消息...

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

/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

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

  

(评论)为什么这可以在我的32位机器上运行?当我只使用-fPIC或-fPIE进行编译时,为什么硬化检查的结果(如果不是,可能是否为cheks)为负?

32位和64位有不同的要求,所以我相信事情"只是工作"在32位i386机器上。但是64位x86_64计算机需要-fPIE-fPIC其他人必须向您提供详细信息,因为我不了解它们。这是一个应该解释的问题/答案:Why does gcc not implicitly supply the -fPIC flag when compiling static libraries on x86_64

您的强化检查可能因为您使用重定位信息(-fPIC-fPIE)编译而失败,但您没有链接重定位信息(-pie用于程序或-shared对于共享对象)。因此链接器没有将相关部分添加到Elf二进制文件中。

相关的,Tobias Klein有一个名为Checsec的简洁工具,用于审核Elf二进制文件。它类似于微软的BinScope

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