C++ 方法和ELF OS ABI中的静态局部变量
给定程序C++ 方法和ELF OS ABI中的静态局部变量,c++,C++,给定程序 $ cat main.cpp #ifndef WITH_LOCAL_STATIC static int y = 0; #endif class X { public: void foo() { #ifdef WITH_LOCAL_STATIC static int y = 0; #endif ++y; } }; int main() { X().foo(); return 0; } 以两种不同的方式编译: $
$ cat main.cpp
#ifndef WITH_LOCAL_STATIC
static int y = 0;
#endif
class X {
public:
void foo() {
#ifdef WITH_LOCAL_STATIC
static int y = 0;
#endif
++y;
}
};
int main() {
X().foo();
return 0;
}
以两种不同的方式编译:
$ g++ main.cpp -o global
$ g++ main.cpp -DWITH_LOCAL_STATIC -o local
我得到两种不同的二进制格式:
$ file local
local: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x8d8e998601e44115b5fa6c0e71f3ed97cb13a0bd, not stripped
$ file global
global: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x3481ba7c6969ed9d1bd1c8ce0f052d574023d488, not stripped
有人能解释一下为什么我在一种情况下使用ELFOSABI\u LINUX
,而在另一种情况下使用ELFOSABI\u NONE
?编译器是GCC4.7.2
背景是,在我的环境中,加载程序拒绝不是GNU/Linux格式取代System V对象文件格式的可执行文件,并且您的gcc认为可以运行可执行文件的最低OS/ABI是GNU/Linux 当您的程序具有类型为STT\u GNU\u IFUNC的符号(表示间接函数的GNU扩展)并且这些符号通常来自glibc时,通常会发生这种情况。当您引入局部静态变量gcc时,向翻译单元添加了(更多)代码来处理其初始化和销毁(按照
\uzzz\uuuu static\u initialization\u和\u destruction\u iii
的思路),这就是glibc的相关部分可能发挥作用的地方
首先,您的最佳选择是遵循此问题中的建议:
其次,我必须指出,在我的框中,旧的gcc 4.4和新的clang 3.4都以标准ELF的形式生成全局和本地二进制文件,因此要么您的测试用例缺少更多相关的位和块,要么您可能正在使用自定义配置和构建的gcc、自定义链接器或非标准的glibc
您可以通过更多途径调查二进制文件中的GNU间接函数是如何结束的:
- 在二进制文件上运行
并识别间接符号,它们应该具有nm
类型。(见下文。)i
- 生成链接映射和/或程序集输出,并将这些间接符号跟踪到代码的细节
- 另外,检查使用
定位glibc是否指向非标准libcldd-v$(type-p gcc)
i-对于PE格式文件,这表示符号位于特定于DLL实现的部分中。对于ELF格式文件,这表示符号是间接函数。这是ELF符号类型标准集的GNU扩展。它表示一个符号>,如果被重新定位引用,它不会计算为其地址,而是必须在运行时调用。然后,运行时执行将返回要在重新定位中使用的值