【问题标题】:What does '_GLOBAL__sub_I_' mean in nm output?'_GLOBAL__sub_I_' 在 nm 输出中是什么意思?
【发布时间】:2015-10-19 21:25:36
【问题描述】:

当我试图解决静态链接中的问题时,我在符号名称前遇到了几个_GLOBAL__sub_I_ 前缀。尽管我使用了nm --demangle(-C),但它以那种形式出现。

我偶然发现了这个答案 (How to find global static initializations)。查看我的源代码,它确实看起来像是全局静态变量的初始化。

我想知道的是,我在哪里可以获取有关 __sub_ 和其他错误名称(例如 __cxxabiv1)的更多信息?

【问题讨论】:

  • @Chris 看起来是一个很棒的资源,谢谢
  • 不客气,如果在这件事上还有什么我可以帮助你的,请告诉我。
  • @ChrisBritt 该链接看起来不再相关,我认为 URL 已更改。您能否提供一个新的,或在在线文档中查找的标题?
  • @TheVee 我很抱歉。老实说,我什至不记得我在两年前发表的评论中指出该文档的意思。我很可能只是打算提供指向相关头文件的链接(其中确实有文档),但如果它发生了变化,我真的不知道我还有什么意思。)

标签: c++ name-mangling nm


【解决方案1】:

为了防止链接失效,我会在这里回答,尽管首先应该归功于 Chris Britt 找到信息(请参阅问题的 cmets)。

如果我们查看"cxxabi.h File Reference" (2013),我们会看到标头定义了两个命名空间:__gnu_cxxabi。所以这是我们正在寻找的标头 "cxxabi.h File Reference" (2019) 声明它是在 2009 年生成的并且几乎相同,除了只提到了 abi 命名空间。

区别是表面的,header code itself 定义了命名空间__cxxabiv1,然后设置了namespace abi = __cxxabiv1;,所以我们可以确定这个标题仍然是我们正在寻找的。​​p>

在头部声明如下:

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;

标题还包括:

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

所以看看它们可能会很有用。

【讨论】:

    【解决方案2】:

    我的符号中有一个 _GLOBAL__sub_I_ 前缀,我需要删除它。

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

    当我#include &lt;iostream&gt; 时,llvm.global_ctors_GLOBAL__I_a... 发生了什么?

    如果您将&lt;iostream&gt; 标头#include 到C++ 翻译单元中,该文件可能会使用std::cin/std::cout/… 全局对象。但是,C++ 不保证不同翻译单元中的静态对象之间的初始化顺序,因此,例如,如果 .cpp 文件中的静态 ctor/dtor 使用了 std::cout,则该对象不一定会在您使用之前自动初始化.

    为了使 std::cout 和朋友在这些场景中正常工作,我们使用的 STL 声明了一个静态对象,该对象在包含 &lt;iostream&gt; 的每个翻译单元中创建。该对象有一个静态构造函数和析构函数,用于在全局 iostream 对象可能在文件中使用之前对其进行初始化和销毁​​。 .ll 文件中看到的代码对应构造函数和析构函数的注册码。

    我将我的函数移动到没有&lt;fstream&gt; 的翻译单元中,现在导出的符号没有_GLOBAL__sub_I_

    【讨论】:

      猜你喜欢
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      相关资源
      最近更新 更多