What does '_GLOBAL__sub_I_' mean in nm output?
Asked Answered
O

2

18

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. It appears in that form although I used 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?

Ouzel answered 29/7, 2015 at 4:33 Comment(5)
For __cxxabiv1 it is explained at: gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.6/a00851.htmlKalynkam
@Chris Looks like a great resource, thanksOuzel
You are welcome, let me know if there is anything else I can assist you with in this matter.Kalynkam
@ChrisBritt The link does not look very relevant anymore, I think the URLs changed. Could you please provide a new one, or the title to look for in the online documentation?Bugle
@TheVee I do apologize. I honestly don't even remember what I would have meant other than pointing to that documentation in a comment I made over two years ago. I quite possibly could have just intended to give the link to the relevant header file (which does have documentation inside of it) but if it has changed, I honestly don't know what else I would have meant.)Kalynkam
B
3

I was getting a _GLOBAL__sub_I_ prefix in my symbols that I needed to get rid of.

Then found this: https://llvm.org/docs/FAQ.html:

What is this llvm.global_ctors and _GLOBAL__I_a... stuff that happens when I #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. 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.

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>. 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. The code that you see in the .ll file corresponds to the constructor and destructor registration code.

I moved my function into a translation unit without <fstream>, and the symbol is now exported without _GLOBAL__sub_I_.

Barolet answered 18/2, 2021 at 6:8 Comment(0)
Z
0

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).

If we look at "cxxabi.h File Reference" (2013) we see that the header defines two namespaces: __gnu_cxx and abi. 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.

The difference is superficial, the header code itself defines the namespace __cxxabiv1 and then sets 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.

Zoe answered 5/5, 2019 at 5:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.