方法和ELF OS ABI中的静态局部变量
Static locals in methods and ELF OS ABI
给定程序
$ 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_LINUX
,而在另一种情况中得到ELFOSABI_NONE
吗?编译器是gcc 4.7.2
背景是,在我的环境中,加载程序拒绝非ELFOSABI_NONE
的可执行文件。
GNU/Linux格式取代了System V对象文件格式,您的gcc认为可以运行可执行文件的最低OS/ABI是GNU/Linu克斯。
当程序中的符号类型为STT_GNU_IFUNC
(表示间接函数的GNU扩展)时,通常会发生这种情况,而这些符号通常来自glibc。当您引入本地静态变量gcc时,它向翻译单元添加了(更多)代码,以处理其初始化和销毁(按照_ZZZ__static_initialization_and_destruction_iii
的行),这可能是glibc的相关部分发挥作用的地方。
首先,你最好遵循这个问题中的建议:如何避免二进制文件中的STT_GNU_IFUNC符号?
第二,我不得不说,在我的盒子上,旧的gcc 4.4和新的clang 3.4都将全局和本地二进制文件生成为SYSV标准ELF,所以要么您的测试用例缺少更多相关的部分,要么您可能使用了自定义配置和构建的gcc、自定义链接器或非标准glibc。
你可以寻求更多的途径来调查你是如何在二进制文件中使用这些GNU间接函数的:
- 在二进制文件上运行
nm
并识别间接符号,它们应该具有i
类型。(见下文。) - 生成链接映射和/或程序集输出,并将这些间接符号跟踪到代码的细节
- 此外,请检查使用
ldd -v $(type -p gcc)
定位glibc是否指向非标准libc
i-对于PE格式文件,这表示符号位于特定于DLL实现的部分中。对于ELF格式的文件,这表示符号是一个间接函数。这是对ELF符号类型标准集的GNU扩展。它指示一个符号>,如果重定位引用了该符号,则该符号不会计算为其地址,而是必须在运行时调用。然后,运行时执行将返回要在重新定位中使用的值
https://sourceware.org/binutils/docs/binutils/nm.html
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- C++:用IIFE线程初始化静态局部变量安全吗
- 静态局部变量会被错误地优化吗?
- 为什么静态局部变量的 MSVC 线程安全初始化使用 TLS
- CppUnit:为什么静态局部变量保持其值
- 静态局部变量没有物理内存
- 使用函数模板中静态局部变量的地址作为类型标识符是否安全
- 通过静态局部变量的参考/指针返回
- 递归计算在不使用静态局部变量,全局变量或静态函数的情况下,在递归函数中发生的环数
- 关于静态局部变量的澄清
- 如果在静态局部变量之前出现异常,会发生什么
- 其中定义函数的静态局部变量对象
- C++ 中静态局部变量的范围和生存期
- 返回静态局部变量作为引用
- DLL 中的 C++ 静态局部变量初始化会导致_CrtIsValidHeapPointer异常
- 在C++中如何在类方法之间访问静态局部变量的值
- 静态方法中的正常局部变量和静态局部变量之间有什么区别吗?
- C++11 中的静态局部变量
- 静态局部变量的线程安全增量
- G++ 4.6 -std=gnu++0x:静态局部变量构造函数调用计时和线程安全