When I try to see definition of cout, I land to iostream file where it is declared as,
extern _CRTDATA2 ostream cout;
So where it is defined? Because extern is just declaration and not definition.
Global symbols are defined in a run-time library that you link with your applications. For example, in gcc you pass the compiler option -lstdc++ that will link your application with the libstdc++.a library. That is where all such symbols reside.
Though, this is specific to your compiler/run-time library version and will vary. Microsoft Visual C++ may behave differently but the idea is the same: the symbols are inside the precompiled libraries that are delivered with your C++ compiler.
With GNU you can type:
nm -g libstdc++.a
to see the symbols inside the library. The output may look like this (among lots of other lines):
ios_init.o:
U _ZSt3cin
globals_io.o:
0000000000000000 D _ZSt3cin
0000000000000000 D _ZSt4cerr
0000000000000000 D _ZSt4clog
0000000000000000 D _ZSt4cout
0000000000000000 D _ZSt4wcin
0000000000000000 D _ZSt5wcerr
0000000000000000 D _ZSt5wclog
0000000000000000 D _ZSt5wcout
Related
I have built SpiderMonkey on Windows. They provide MSVC++ toolchain and I couldn't build it for mingw. I've built it for 64bit.
It is a DLL, I need to convert its lib to gnu C++ format (.lib to .a).
After looking on the web, I've found here how to do this, roughly:
gendef mozjs-45.dll
dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib mozjs-45.a --input-def mozjs-45.def
I use TDM-GCC-64 under Code::Blocks. At link time it throws errors like:
undefined reference to `__imp__Z13JS_GetPrivateP8JSObject'
I have checked the lib content using:
nm libmozjs-45.a > libmozjs-45.nm
I see there are the same entries as in the def file exported, but that looks different than linker expects (I presume):
?JS_GetPrivate##YAPEAXPEAVJSObject###Z
Edit 1
I have managed to build SpiderMonkey with mingw-w64. Now, at linking time I get the following error:
undefined reference to `__imp__ZN17JSAutoCompartmentC1EP9JSContextP8JSObject'
Looking with nm at the lib, I have:
d000536.o:
0000000000000000 i .idata$4
0000000000000000 i .idata$5
0000000000000000 i .idata$6
0000000000000000 i .idata$7
0000000000000000 t .text
0000000000000000 I __imp__ZN17JSAutoCompartmentC1EP9JSContextP8JSObjectON7mozilla6detail19GuardObjectNotifierE
U _head_mozjs_45_dll
0000000000000000 T _ZN17JSAutoCompartmentC1EP9JSContextP8JSObjectON7mozilla6detail19GuardObjectNotifierE
Indeed, the definition of the class is:
class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
{
JSContext* cx_;
JSCompartment* oldCompartment_;
public:
JSAutoCompartment(JSContext* cx, JSObject* target
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
JSAutoCompartment(JSContext* cx, JSScript* target
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~JSAutoCompartment();
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
Why the same compiler exports this as __imp__ZN17JSAutoCompartmentC1EP9JSContextP8JSObjectON7mozilla6detail19GuardObjectNotifierE, but, when referencing it, expects it as __imp__ZN17JSAutoCompartmentC1EP9JSContextP8JSObject?
Answer: missed a symbol definition that exclude MOZ_GUARD_OBJECT_NOTIFIER_PARAM from build.
$ nm --demangle /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/libsupc++.a | grep "__cxxabiv1::__class_type_info::~__class_type_info"
gives following output:
0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
U __cxxabiv1::__class_type_info::~__class_type_info()
U __cxxabiv1::__class_type_info::~__class_type_info()
So, how to interpret this output?
Here is multiple definitions of the symbol (three T's) - how it could be? Why linker produced such library with violated ODR? What is the purpose? And why all of them have the same (and strange) address (0000000000000000)?
How the same symbol could be both defined (T) and undefined (U) simultaneously?
A static library (archive file, .a) is essentially a collection of individual .o files (plus some indexing information so the linker can find the .o files it needs). Some of those undefined symbols are in a different object than the one that defines them. If you look at the full output of nm this becomes clear. (Or use the -o flag to nm.)
The reason you have multiple defined symbols is that demangle isn't a 1-to-1 operation. In my copy of libsupc++, those three definitions are:
0000000000000000 T _ZN10__cxxabiv117__class_type_infoD0Ev
0000000000000000 T _ZN10__cxxabiv117__class_type_infoD1Ev
0000000000000000 T _ZN10__cxxabiv117__class_type_infoD2Ev
Why are there several symbols which all demangle to the destructor? They're destructors for different situations. gcc uses the Itanium ABI for C++, whose name mangling rules are described here.
Trying to make the ta-lib library (ta-lib-0.4.0-src.tar.gz) I get the following error:
/home/me/ta-lib/src/.libs/libta_lib.so: undefined reference to `sinh'
/home/me/ta-lib/src/.libs/libta_lib.so: undefined reference to `sincos'
/home/me/ta-lib/src/.libs/libta_lib.so: undefined reference to `ceil'
...
for a large number of maths functions.
The failing command looks like this:
gcc -g -O2 -o .libs/ta_regtest (... .o files) -L/home/me/ta-lib/src \
/home/me/ta-lib/src/.libs/libta_lib.so -lm -lpthread -ldl
The offending library (ta_lib) looks like this:
objdump -TC libta_lib.so | grep " D \*UND\*"
0000000000000000 D *UND* 0000000000000000 sinh
0000000000000000 D *UND* 0000000000000000 sincos
0000000000000000 D *UND* 0000000000000000 ceil
...
For the same maths functions (the grep excludes defined functions and those that have a "w" (presumably weak) flag)
A map lists the libraries included, among them:
LOAD /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.so
and a list of the symbols (objdump -TC) defined in libm.so includes:
000000000001a320 w iD .text 0000000000000020 GLIBC_2.2.5 ceil
which was one of the undefined references (they are all there). I cannot determine the meaning of GLIBC_2.2.5.
Why is the loader not finding these functions?
My system looks like this:
$ uname -a
Linux mynode 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
When I try to see definition of cout, I land to iostream file where it is declared as,
extern _CRTDATA2 ostream cout;
So where it is defined? Because extern is just declaration and not definition.
Global symbols are defined in a run-time library that you link with your applications. For example, in gcc you pass the compiler option -lstdc++ that will link your application with the libstdc++.a library. That is where all such symbols reside.
Though, this is specific to your compiler/run-time library version and will vary. Microsoft Visual C++ may behave differently but the idea is the same: the symbols are inside the precompiled libraries that are delivered with your C++ compiler.
With GNU you can type:
nm -g libstdc++.a
to see the symbols inside the library. The output may look like this (among lots of other lines):
ios_init.o:
U _ZSt3cin
globals_io.o:
0000000000000000 D _ZSt3cin
0000000000000000 D _ZSt4cerr
0000000000000000 D _ZSt4clog
0000000000000000 D _ZSt4cout
0000000000000000 D _ZSt4wcin
0000000000000000 D _ZSt5wcerr
0000000000000000 D _ZSt5wclog
0000000000000000 D _ZSt5wcout
I have a static library I'm building in debug mode, but when I step into it I still get disassembly. I want to know how to use nm or another tool to ensure that the debug symbols are not being stripped.
You might use nm's option --debug-syms, to let nm also list debugger symbols (if any) for the object packed into a library.
For debugger symbols the second column indicates N.
Example (assumes the object example.o to be in the library)
nm --debug-syms libexample.a
Output (excerpt):
example.o:
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_loc
0000000000000000 N .debug_pubnames
0000000000000000 N .debug_str
0000000000000000 r .eh_frame
0000000000000000 n .note.GNU-stack
0000000000000000 r .rodata
0000000000000000 t .text
...
For more on this please see man nm.
You can use the file command, available for many OSes, including Windows via Cygwin.
If it says 'not stripped' it means it has the debug info present.
As a side note, for static libs use ar to extract the .o files & use file on them directly.
You can use strip -S libXX.a to check if your static library size has been reduce. The static library size will not change if it's not include debugging symbols.
It is works on Mac OS to check static library generated by Xcode.
Linux and Unix strip command
Download Dependencywalker for your OS
It will detect if your dll has debug symbols. If you see "Invalid" under "Symbols", it means debug symbols have been stripped off. Valid values are : PDB, CV, DBG, etc.