我有一个简单的C++代码,看起来像这样:
#include <boost/timer/timer.hpp>
int main(void) {
boost::timer::auto_cpu_timer t;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我尝试编译并链接它(使用gcc 4.8.1和GNU ld 2.23.52.20130828),如下所示:
$ g++ -o test test.cc -lboost_timer
/usr/bin/ld: /tmp/cc2jP1jv.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv'
/usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
一种解决方案是-lboost_system在命令行上明确提及,这是有效的.但是,我也可以这样做:
$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer
Run Code Online (Sandbox Code Playgroud)
根据ld文档"with --copy-dt-needed-entries命令行中提到的动态库将被递归搜索,跟随其DT_NEEDED标记到其他库,以便解析输出二进制文件所需的符号",所以这一切都有意义:ld正在从boost_timer中找出它还需要链接boost_system以解析所有符号.
但是,我意识到这也有效:
$ g++ -fPIC -shared -o test test.cc -lboost_timer
Run Code Online (Sandbox Code Playgroud)
显然,我现在已经生成了一个共享对象而不是一个可执行文件.显然,ld能够弄清楚它需要将该共享对象与boost_system链接:
$ ldd test | grep boost_system
libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000)
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:为什么在构建共享对象与可执行文件时,符号解析会有所不同?如何在没有指定的情况下ld能够确定我的共享对象应该与boost_system链接--copy-dt-needed-entries?
请参阅标签部分.
这个决定背后的理由是什么?合并是否会影响构建最新binutils和GDB的建议方式?(事实上当我检查binutils-2_25_1并跑步时make all && make install,我也得到了gdb.)
我正在尝试构建 Gnu binutils,通过定义宏SYSV386_COMPAT 0来改变它生成一些 FPU 操作码的方式,从而解锁行为。
我可以轻松地进入头文件并手动设置值,但是如何调用配置脚本才能#define SYSV386_COMPAT 0在命令行上指定等效项?如果可能的话,我更愿意在命令行上指定一些内容(只是因为该功能是可传递的,而且我认为我不应该破解源代码)。话虽如此,我已经尝试阅读至少一些 FM,但未能在或AC_DEFINE(SYSV386_COMPAT, 0)中插入。binutils/configure.ingas/configure.in
由于错误,ld我需要将 ELF 部分从一个目标文件复制到另一个目标文件。我可以将所需的部分转储到文件中,但问题是该objcopy选项--add-section需要二进制文件,因此部分类型信息会丢失。据我所知,我无法使用 binutils 设置部分的类型,但我希望我错了:)
我可以手动编辑二进制文件以设置节类型并解决根本问题,但我很好奇是否有基于标准工具的解决方案。
对于好奇的人来说,潜在的问题是,当 GNUld链接没有该部分的 ARM 目标文件.ARM.attributes(例如在其自己的部分中只有一个二进制 blob 的文件)时,它会选择一些默认值,导致它甚至为 RAM 函数生成无效的胶合板当包含调用的文件有好的.ARM.attributes
部分时。我能想到的唯一解决方案(待定
https://sourceware.org/bugzilla/show_bug.cgi?id=11897.ARM.attributes )是向二进制 blob 对象文件添加一个部分。.ARM.attributes但是,只有当该部分的类型为时,这才有效ARM_ATTRIBUTES。
我刚刚阅读了这篇出色的文章:http : //neugierig.org/software/chromium/notes/2011/08/static-initializers.html 然后我尝试了:https : //gcc.gnu.org/onlinedocs/gccint/Initialization .html
不过,它关于查找初始化程序的内容对我不起作用。该.ctors部分不可用,但我可以找到.init_array(另请参阅Can't find .dtors and .ctors in binary)。但是我如何解释输出?我的意思是,总结页面的大小也可以由size命令及其.bss列处理 - 或者我错过了什么?
此外,nm不报告任何*_GLOBAL__I_*符号,仅报告*_GLOBAL__N_*函数和 - 更有趣的 -_GLOBAL__sub_I_somefile.cpp条目。后者可能表示具有全局初始化的文件。但是我能以某种方式获得正在运行的构造函数列表吗?理想情况下,一个工具会给我一个列表
Foo::Foo in file1.cpp:12
Bar::Bar in file2.cpp:45
...
Run Code Online (Sandbox Code Playgroud)
(假设我有可用的调试符号)。有这样的工具吗?如果不是,那怎么写呢?该.init_array部分是否包含指向可以通过一些 DWARF 魔法转换为上述代码的指针?
我有一个来自 Tiny C 编译器的 64 位 ELF 目标代码。我无法让 gobjdump 显示反汇编代码。我使用的是 OS X 10.10.5。
$ file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ gobjdump -d hello.o
gobjdump: hello.o: File format not recognized
$ greadelf -h hello.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL …Run Code Online (Sandbox Code Playgroud) 我有一个由某人编译的 binutils 版本。我需要使用相同的选项重新编译一个新的 binutils。
我知道这会gcc -v打印出配置选项。那么也许有什么方法可以读取binutils?
在对此问题的评论中, Unexpected Behaviour in simple Pointer Algoriths in kernel space C code 中,Michael Petch 写道,“64 位 ELF 格式支持 32 位代码段。”
我有一个工作程序,其中包含 32 位和 64 位代码以及它们之间的切换。我一直无法弄清楚如何将编译器生成的 32 位和 64 位代码链接在一起而不出现链接器错误,因此所有 32 位代码都是用汇编语言编写的。随着项目变得越来越复杂,32位汇编代码的维护也变得更加繁重。
这是我所拥有的:
test32.cc 是用-m32.
所有其他源文件都是在没有该标志的情况下使用-mcmodel=kernel.
在链接描述文件中:
OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
Run Code Online (Sandbox Code Playgroud)
在生成文件中:
LD := ld
LDFLAGS := -Map $(TARGET).map -n --script $(LDSCRIPT)
$(LD) $(LDFLAGS) -b elf32-x86-64 $(OBJS64) -b elf32-i386 $(OBJS32) -o $@
Run Code Online (Sandbox Code Playgroud)
我收到错误:
ld: i386 architecture of input file 'test32.o' is incompatible with i386:x86-64 output
Run Code Online (Sandbox Code Playgroud)
将 OUTPUT_ARCH 更改为 …
musl C 库只有符号版本控制的近似实现。这可能导致具有不同符号版本的符号绑定在一起,这在完整实现中不会发生。因此,希望使用 musl 构建的项目最好完全避免符号版本控制。(不支持符号版本控制本身对于工具链来说不一定是一个糟糕的选择;这完全取决于目标受众。)
但是,Alpine Linux 工具链编译 binutils 时具有完整的符号版本支持:GAS 支持该.symver指令,链接编辑器处理版本脚本并分配符号版本(就像在 GNU/Linux 上一样)。一个简单的编译器/汇编器或链接检查显示符号版本的支持。因此,Alpine Linux 在发行版中包含的一些共享对象实际上使用了符号版本控制,尽管 musl 动态加载器会忽略这些数据。(数据只会使二进制文件膨胀。)
在某些情况下,软件无法运行(在构建正常之后),因为它以 musl 动态链接器不支持的方式使用兼容性符号(没有默认版本的符号)。这是一个不起作用的小例子:
cat > symver.c <<EOF
void
compat_function (void)
{
}
__asm__ (".symver compat_function,compat_function@SYMVER");
void
call_compat_function (void)
{
return compat_function ();
}
EOF
echo "SYMVER { };" > symver.map
cat > main.c <<EOF
extern void call_compat_function (void);
int
main (void)
{
call_compat_function ();
}
EOF
gcc -fpic -shared -o symver.so -Wl,--version-script=symver.map symver.c
gcc -Wl,--rpath=. -o main …Run Code Online (Sandbox Code Playgroud)