Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 方法和ELF OS ABI中的静态局部变量_C++ - Fatal编程技术网

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
    类型。(见下文。)
  • 生成链接映射和/或程序集输出,并将这些间接符号跟踪到代码的细节
  • 另外,检查使用
    ldd-v$(type-p gcc)
    定位glibc是否指向非标准libc

i-对于PE格式文件,这表示符号位于特定于DLL实现的部分中。对于ELF格式文件,这表示符号是间接函数。这是ELF符号类型标准集的GNU扩展。它表示一个符号>,如果被重新定位引用,它不会计算为其地址,而是必须在运行时调用。然后,运行时执行将返回要在重新定位中使用的值