简体   繁体   English

“_GLOBAL__sub_I_”在nm输出中是什么意思?

[英]What does '_GLOBAL__sub_I_' mean in nm output?

While I was trying to resolve a problem in static linking, I encounter a couple of _GLOBAL__sub_I_ prefixes in front of symbol names.当我试图解决静态链接中的问题时,我在符号名称前面遇到了几个_GLOBAL__sub_I_前缀。 It appears in that form although I used nm --demangle(-C) .尽管我使用了nm --demangle(-C) ,但它以这种形式出现。

I stumbled upon this answer ( How to find global static initializations ).我偶然发现了这个答案( 如何找到全局静态初始化)。 Looking at my source code, it indeed looks like initialization of a global static variable.查看我的源代码,它确实看起来像一个全局静态变量的初始化。

What I'm wondering is, where can I more information on __sub_ and other mangled names, like __cxxabiv1 ?我想知道的是,我在哪里可以获取有关 __sub_ 和其他错误名称(例如__cxxabiv1更多信息?

To prevent link rot i will answer here, although it is Chris Britt who should be credited with finding the information in the first place (see comments to the question).为了防止链接腐烂,我将在这里回答,尽管首先应该归功于Chris Britt找到信息(请参阅对问题的评论)。

If we look at "cxxabi.h File Reference" (2013) we see that the header defines two namespaces: __gnu_cxx and abi .如果我们查看“cxxabi.h 文件参考”(2013 年),我们会看到头文件定义了两个命名空间: __gnu_cxxabi So this is the header we are looking for "cxxabi.h File Reference" (2019) states that it was generated in 2009 and is almost identical, except that there is only abi namespace that is mentioned.所以这是我们正在寻找的头文件“cxxabi.h 文件参考”(2019 年)指出它是在 2009 年生成的,几乎相同,只是提到了abi命名空间。

The difference is superficial, the header code itself defines the namespace __cxxabiv1 and then sets namespace abi = __cxxabiv1;区别是表面的, 头代码本身定义了命名空间__cxxabiv1 ,然后设置了namespace abi = __cxxabiv1; so we can be sure that this header is still what we are looking for.所以我们可以确定这个标题仍然是我们正在寻找的。

The following is declared in the header:在头文件中声明如下:

typedef __cxa_cdtor_return_type (*__cxa_cdtor_type)(void *);

int __cxxabiv1::__cxa_atexit (void(*)(void *), void *, void *) throw ();
void __cxxabiv1::__cxa_bad_cast ();
void __cxxabiv1::__cxa_bad_typeid ();
std::type_info * __cxxabiv1::__cxa_current_exception_type ();
char * __cxxabiv1::__cxa_demangle (const char *__mangled_name, char *__output_buffer, size_t *__length, int *__status);
int __cxxabiv1::__cxa_finalize (void *);
void __cxxabiv1::__cxa_guard_abort (__guard *);
int __cxxabiv1::__cxa_guard_acquire (__guard *);
void __cxxabiv1::__cxa_guard_release (__guard *);
void __cxxabiv1::__cxa_pure_virtual (void);
__cxa_vec_ctor_return_type __cxxabiv1::__cxa_vec_cctor (void *dest_array, void *src_array, size_t element_count, size_t element_size, __cxa_cdtor_return_type(*constructor)(void *, void *), __cxa_cdtor_type destructor);
void __cxxabiv1::__cxa_vec_cleanup (void *__array_address, size_t __element_count, size_t __element_size, __cxa_cdtor_type destructor);
__cxa_vec_ctor_return_type __cxxabiv1::__cxa_vec_ctor (void *__array_address, size_t __element_count, size_t __element_size, __cxa_cdtor_type constructor, __cxa_cdtor_type destructor);
void __cxxabiv1::__cxa_vec_delete (void *__array_address, size_t __element_size, size_t __padding_size, __cxa_cdtor_type destructor);
void __cxxabiv1::__cxa_vec_delete2 (void *__array_address, size_t __element_size, size_t __padding_size, __cxa_cdtor_type destructor, void(*__dealloc)(void *));
void __cxxabiv1::__cxa_vec_delete3 (void *__array_address, size_t __element_size, size_t __padding_size, __cxa_cdtor_type destructor, void(*__dealloc)(void *, size_t));
void __cxxabiv1::__cxa_vec_dtor (void *__array_address, size_t __element_count, size_t __element_size, __cxa_cdtor_type destructor);
void * __cxxabiv1::__cxa_vec_new (size_t __element_count, size_t __element_size, size_t __padding_size, __cxa_cdtor_type constructor, __cxa_cdtor_type destructor);
void * __cxxabiv1::__cxa_vec_new2 (size_t __element_count, size_t __element_size, size_t __padding_size, __cxa_cdtor_type constructor, __cxa_cdtor_type destructor, void *(*__alloc)(size_t), void(*__dealloc)(void *));
void * __cxxabiv1::__cxa_vec_new3 (size_t __element_count, size_t __element_size, size_t __padding_size, __cxa_cdtor_type constructor, __cxa_cdtor_type destructor, void *(*__alloc)(size_t), void(*__dealloc)(void *, size_t));
void * __cxxabiv1::__dynamic_cast (const void *__src_ptr, const __class_type_info *__src_type, const __class_type_info *__dst_type, ptrdiff_t __src2dst);

class __cxxabiv1::__fundamental_type_info : public std::type_info;
class __enum_type_info : public std::type_info;
class __pointer_type_info : public __pbase_type_info;
class __class_type_info : public std::type_info;
class __pointer_to_member_type_info : public __pbase_type_info;
class __base_class_type_info;
class __si_class_type_info : public __class_type_info;
class __vmi_class_type_info : public __class_type_info;

The header also includes:标题还包括:

#include <bits/cxxabi_tweaks.h>
#include <cxxabi-forced.h>

So it may be useful to take a look at them.因此,查看它们可能会有所帮助。

I was getting a _GLOBAL__sub_I_ prefix in my symbols that I needed to get rid of.我在我需要删除的符号中得到了一个_GLOBAL__sub_I_前缀。

Then found this: https://llvm.org/docs/FAQ.html :然后发现这个: https : //llvm.org/docs/FAQ.html

What is this llvm.global_ctors and _GLOBAL__I_a... stuff that happens when I #include <iostream> ?这是什么llvm.global_ctors_GLOBAL__I_a...当我#include <iostream>时发生的事情?

If you #include the <iostream> header into a C++ translation unit, the file will probably use the std::cin/std::cout/… global objects.如果将<iostream>标头 #include 到 C++ 翻译单元中,该文件可能会使用std::cin/std::cout/…全局对象。 However, C++ does not guarantee an order of initialization between static objects in different translation units, so if a static ctor/dtor in your .cpp file used std::cout, for example, the object would not necessarily be automatically initialized before your use.但是,C++ 不保证不同翻译单元中静态对象之间的初始化顺序,因此,例如,如果 .cpp 文件中的静态 ctor/dtor 使用 std::cout,则该对象不一定会在使用前自动初始化.

To make std::cout and friends work correctly in these scenarios, the STL that we use declares a static object that gets created in every translation unit that includes <iostream> .为了使 std::cout 和朋友在这些场景中正常工作,我们使用的 STL 声明了一个静态对象,该对象在每个包含<iostream>翻译单元中创建。 This object has a static constructor and destructor that initializes and destroys the global iostream objects before they could possibly be used in the file.该对象有一个静态构造函数和析构函数,用于在全局 iostream 对象可能在文件中使用之前初始化和销毁​​它们。 The code that you see in the .ll file corresponds to the constructor and destructor registration code.您在 .ll 文件中看到的代码对应于构造函数和析构函数注册代码。

I moved my function into a translation unit without <fstream> , and the symbol is now exported without _GLOBAL__sub_I_ .我将我的函数移到一个没有<fstream>的翻译单元中,并且现在在没有_GLOBAL__sub_I_情况下导出了符号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM