Using standard C++ library debug symbols? Ubuntu / Linux / libstdc++6-8-dbg? - c++

There is a package called libstdc++6-8-dbg on Ubuntu Linux (latest version at time of writing).
It is described as:
GNU Standard C++ Library v3 (debugging files)
This package contains the shared library of libstdc++ compiled with
debugging symbols.
Among other things it contains these files:
/usr/lib/x86_64-linux-gnu/debug/libstdc++.a
/usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.25
/usr/lib/x86_64-linux-gnu/debug/libstdc++fs.a
Normally to compile a (single translation unit) C++ program with gcc you can write:
$ g++ myprogram.cc
To add generation of debug symbols of user code you pass -g:
$ g++ -g myprogram.cc
But this doesn't include the debug versions of the standard library.
What extra options do you need to pass to g++ to tell it to use the debug versions of the standard library provided by libstdc++6-8-dbg?

The OP wants to resolve C++ standard library's symbols in the backtrace correctly. John's answer correctly states that this could be achieved by linking against the debug version of the standard libraries.
However, Ubuntu also provides debug symbol packages that, once installed, allow GDB to resolve symbols in standard libraries whose debug symbols have been stripped i.e. in the release version of the standard library. We provide a how-to example below (I'm using Ubuntu 20.04):
Suppose the generated binary is named a.out. We first find the version of libstdc++ it links against:
$ ldd a.out
...
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff8dc6f7000)
...
We search for the package that provides the shared library file (/lib is a symbolic link to /usr/lib. The full path must be used here.):
$ dpkg -S /usr/lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++6:amd64: /usr/lib/x86_64-linux-gnu/libstdc++.so.6
Follow the instructions to add the repo for debug symbol packages and then update the package index. The link also describes how one may search for debug symbol packages, but I directly searched with the package name:
$ apt list libstdc++6\*
...
libstdc++6-dbgsym/focal-updates 10.2.0-5ubuntu1~20.04 amd64
...
There will be tons of results, but be sure to look out for dbgsym, rather than dbg! After installing libstdc++6-dbgsym, GDB should be able to resolve the symbols, even if your binary isn't linked against the debug library.
The texts above should answer the OP's question. Now I point out an issue with John's answer.
GDB automatically reads in the debug symbols once you've installed the package. You don't need to compile your program any differently.
This statement is 100% correct, but the figure included is irrelevant and doesn't prove the statement. There are three closely-releated concepts at play here:
Debug library package: The package libstdc++6-8-dbg provides a version of the libstdc++ library with debug symbols.
Debug symbol pagkage: The package libstdc++6-dbgsym provides the debug symbols for the libstdc++ library. That is, it doesn't include any machine instructions for functions like printf, only the debug symbols. libstdc++6-8-dbg bundles code and debug symbols together into one library.
Release library package: The packages libstdc++6-8 and libstdc++6 provide the release versions of the standard library, meaning that they don't carry debug symbols, only the code. Debug symbol packages should be used together with the release libraries.
GDB will automatically read the debug symbols in the debug symbol package, but not in the debug library. The auto-load in John's figure simply states that the Python script /usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.25-gdb.py will be run automatically when the debug library is loaded and has nothing to do with the auto-loading of debug symbols.

GDB automatically reads in the debug symbols once you've installed the package. You don't need to compile your program any differently.
If you want your program to load the debug version your best bet is to adjust the library search path. You could do that by setting LD_LIBRARY_PATH temporarily:
$ LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/debug/
$ ldd test
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007efcef670000)
...
Or permanently:
$ export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/debug/
$ ldd test
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007efcef670000)
...
Or you could make it a system-wide change. You can do that in Ubuntu by adding a config entry to /etc/ld.so.conf.d/ and running ldconfig to update the cache.
$ sudoedit /etc/ld.so.conf.d/debug.conf
$ cat /etc/ld.so.conf.d/debug.conf
/usr/lib/x86_64-linux-gnu/debug
$ sudo ldconfig
$ ldd test
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007f3aced53000)
...
The config files are searched alphabetically so just make sure the one you write (debug.conf above) comes earlier than the default one (x86_64-linux-gnu.conf on my system).

Related

libtorrent-rasterbar7: g++ linker unable to find libtorrent/session.hpp

When compiling the libtorrent tutorial 'hello world' with:
g++ main.cpp -o run -ltorrent-rasterbar -lboost_filesystem-mt -L /usr/lib/
=> fatal error: libtorrent/session.hpp: No such file or directory
Despite having libtorrent-rasterbar7 installed (both libtorrent-rasterbar.so.7 and libtorrent-rasterbar.so.7.0.0 exist in /usr/lib/). Also I'm able to run a simple python script that imports and uses libtorrent without issues.
The g++ command I'm using is identical to the solution for a similar issue with version 6 yet still having the error.
You haven't installed the libtorrent-rasterbar header files. The
package you are missing is the libtorrent-rasterbar development
package. What it is called depends on your distro. (On Debian or Ubuntu
it is libtorrent-rasterbar-dev. On Fedora it is libtorrent-rasterbar-devel).
Whenever you want to write an application that links with a packaged library
you need to install not simply the runtime library but the associated development
package, which provides both the runtime library and its header files.
BTW, there is no need to pass -L /usr/lib to the linker as /usr/lib is one of the default linker search directories.

g++ ld shared library error with code::blocks

There are similar topics, but I haven't managed to find my answer in them.
I am building a test console application using the code::blocks IDE. It needs to load a DVB shared library called libhdhomerun.so (from Silicon Dust) for the HD Homerun DVB tuners. The HDHR tuner library has being installed using ./configure, ..., sudo make install, ldconfig etc and it all works with their utilities (built at the same time). So - the library is there and OK.
The library installed itself into /usr/local/lib. There is actually no symlink to it as there is with other shared libraries, but then it doesn't have any version information on the end either.
When I build the code (having explicitly included /usr/local/lib/libhdhomerun.so), the ld stage fails with
"cannot find -lhdhomerun.so"
I have tried every combination of including (/usr/local/lib/) libhdhomerun.so, hdhomerun.so, libhdhomerun, hdhomerun, creating a symlink to it etc. Nothing makes any difference.
The bizarre thing is that I have udev, mysql and libdvbv5 shared libraries included in exactly the same way, and they are fine. The only one that will not link is hdhomerun.
If I run a manual verbose link step from the command line "ld -lhdhomerun.so --verbose", it does fail - because it is trying to find libhdhomerun.so.so.
Any suggestions gratefully received - but I do need to keep using code::blocks.
To link the library properly, you need to have library path defined in your environment, and use proper library name with -l flag. Library path is defined in LD_LIBRARY_PATH environment variable. For -l flag to g++, library extension should not be provided - as you already observed, so in your case it should be like this:
-lhdhomerun

Error building gcc 4.8.3 from source: libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)

I 'm using gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 for the compile but I have also tried gcc 4.1.2 and I get the same error.
for gcc 5.2.1
strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6|grep CXXABI gives
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_1.3.8
CXXABI_1.3.9
CXXABI_TM_1
CXXABI_FLOAT128
For the compiler being compiled gcc 4.8.3
strings gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6|grep CXXABI
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_TM_1
CXXABI_1.3
CXXABI_1.3.2
CXXABI_1.3.6
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.4
CXXABI_TM_1
CXXABI_1.3.7
CXXABI_1.3.3
i.e no 1.3.8
prior to running configure and make I also tried:
export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
../gcc-4.8.3/configure --build=x86_64-linux-gnu
make
Error message:
msgfmt -o fr.mo ../../../../gcc-4.8.3/libstdc++-v3/po/fr.po
msgfmt: gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
msgfmt: Makefile:460: recipe for target 'de.mo' failed
When compiling with gcc 4.1.2 I get the same error:
msgfmt -o fr.mo ../../../../libstdc++-v3/po/fr.po
gcc-build/gcc-4.8.3/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
Makefile:460: recipe for target 'de.mo' failed
When compiling with gcc 4.1.2 i did the following prior to configure and make
#where libraries i have compiled with gcc 4.1.2 are located i.e
export LD_LIBRARY_PATH=/opt/devtools/gcc-4.1.2/lib
#where libstdc++.so.6 is
export LIBRARY_PATH=/opt/gcc-4.1.2/lib64
strings /opt/gcc-4.1.2/lib64/libstdc++.so.6|grep CXXABI
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.1
CXXABI_1.3
which makes me wonder where CXXABI_1.3.8 is coming from. I also did a 'make distclean' between changing compiler
I stumbled upon the same problem with a bit newer compiler combination, i.e. using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 while building GCC 4.8.5. The solution worked out so far apparently did the job and gives valuable general explanation of the problem. I offer further details and an alternative solution below.
The error message in question comes from the msgfmt program - part of gettext, an internationalization and localization system:
$ which msgfmt
/usr/bin/msgfmt
$ dpkg -S /usr/bin/msgfmt
gettext: /usr/bin/msgfmt
msgfmt gets called by the GCC build system to compile messages emited by the C++ standard library (libstdc++) that is currently being built. msgfmt is a dynamically linked executable, linked (among others) against libicuuc.so.55 - a cross-platform Unicode based globalization library:
$ ldd /usr/bin/msgfmt
libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007ff133f47000)
(other dependencies not shown for clarity)
The icuuc library is a dynamically linked shared object itself that depends on the stdc++ library:
$ ldd /usr/lib/x86_64-linux-gnu/libicuuc.so.55
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff688a16000)
(other dependencies not shown for clarity)
The above listing was generated using my interactive shell environment, which resolves the dependency on libstdc++.so.6 to the system-wide version of the C++ library located in /usr/lib/x86_64-linux-gnu. However, the GCC build environment apparently resolves this dependency to the C++ library generated on the earlier stage of the current build process, i.e. to the one located in $TOP_BUILD_DIR/x86_64-linux-gnu/libstdc++-v3/src/.libs - recall the originally posted error message:
msgfmt: gcc-build/build/x86_64-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
I get a fairly similar output:
msgfmt: /opt/build/gcc/gcc-4.8.4/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)
Now, answering the original question, the string 'CXXABI_1.3.8' comes from the libicuuc.so.55 library, which requires that the libstdc++.so.6 library it depends upon, provides a particular ABI version:
$ strings /usr/lib/x86_64-linux-gnu/libicuuc.so.55 | grep CXXABI
CXXABI_1.3.8
CXXABI_1.3
To summarize, the GCC build system creates a circular dependency, which mixes system-wide binaries with local libraries:
libstdc++ (currenlty built) > msgfmt > libicuuc.so.55 > libstdc++.so.6
by resolving libstdc++.so.6 to it's own library structure instead of the system-wide version.
The solution proposed by Mats Petersson, which involves rebuilding the libicuuc.so.55 library such that it depends on an older version of libstdc++.so.6, which is (hopefully) compatible with the GCC build system, is certainly valid. However, it seems a bit unnatural for my taste, as it requires playing around with dependencies of a system-wide binary, which is out of control of any non-root user.
My alternative solution involves building the custom version of the gettext package instead, such that the msgfmt binary is self-contained and its dependencies do not interfere with the GCC build system. It can be achieved by installing the custom version of gettext in /opt and adjusting the relevant paths using environment modules.
I had the same problem when I tried to build GCC 4.8.5 from source on Ubuntu 16.04.3 LTS with GCC 5.4.0.
As a workaround I just dropped LD_LIBRARY_PATH only for msgfmt command in makefiles. To be precise I give the exact commands I executed to get the build successful:
1 - extract the sources
tar zxfv gcc-4.8.5.tar.gz
cd gcc-4.8.5
2 - modify call of msgfmt (add LD_LIBRARY_PATH= ) and make sure it is correct
vi ./libstdc++-v3/po/Makefile.in
vi ./libstdc++-v3/po/Makefile.am
grep "MSGFMT =" ./libstdc++-v3/po/Makefile.in ./libstdc++-v3/po/Makefile.am
./libstdc++-v3/po/Makefile.in:MSGFMT = LD_LIBRARY_PATH= msgfmt
./libstdc++-v3/po/Makefile.am:MSGFMT = LD_LIBRARY_PATH= msgfmt
3 - configure (I restriced multilib to 64bit only, because I don't have libc6-dev-i386 installed on my 64bit host and don't want to do it only for this build), build and install
./configure --prefix=$HOME/gcc-4.8.5 --with-multilib-list=m64
make
make install
So, this problem occurs when a library that has been built with a newer compiler is linked with an older version of C++ library - or sometimes when a newer headerfile is used to compile something that then links to an older C++ library.
It is also possible come up with a similar problem when moving binary files from one system to another, if the shared libraries installed on the "new system" are older than the ones on which the code was built.
There are typically three plausible solutions:
1. Recompile the offending library with an older compiler.
2. Install a newever version of the C++ library.
3. Rebuild the C++ library from sources (with a new enough compiler).
just copy libstdc++.so in system installed directory to your gcc source appropriate directory, remember to rename it properly.
attention: you may need to copy several times as during compiling, gcc will replace that library several times.

Linker library path in makefile confusion

I've been programming a while but I still don't fully understand how the linker behaves.
For example, today I downloaded and installed a library that I want to use in my application in Linux. (It was Xerces - for parsing XML files).
I created a makefile and gave it the path to the .so and .a files in my command : -L/usr/local/lib and also told it the name of the library to include : -lxerces-c-3.1.
My application compiled fine but failed during runtime with "cannot open shared object file libxerces-c-3.1.so". Why would this be the case, when I properly give it the path and name in the makefile?
I then added the library path to the LD_LIBRARY_PATH variable in my .bashrc file and then it worked. That's fine , but if I now remove the path to the library in my makefile and don't even include the name of the library , it still works.
I'm confused as to what is going on here. How can it still find the correct library just by assigning the path to the LD_LIBRARY_PATH variable and will only work if I do so? I have read elsewhere to not even use LD_LIBRARY_PATH.
I appreciate any answer for this. The question is a bit long and hopefully not off-topic but I hope others can learn from it too. Thanks
compilation and running are different things. :)
1) A make file contains rules on how to build your application. So when you write a rule like:
-L/usr/local/lib -lxerces-c-3.1
You are passing options to the linker. The -L option tells the linker to add additional libraries (in this case '/usr/local/lib') to the linker's search path. The -l option names the library that should be linked in.
2) When you go to run an executable, the loader needs to find all the required libraries. For example, on a Linux system you can use the ldd command to see what shared libraries are used. For example on my system:
ldd FEParser
linux-vdso.so.1 => (0x00007ffcdc7c9000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f835b143000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f835ae3d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f835ac27000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f835a862000)
/lib64/ld-linux-x86-64.so.2 (0x00007f835b447000)
From this, you can see the name of the library that is linked to the left of the '=>' token, and the path to the library to the right. If a library is not found it will show up as missing.
Now in your case, you were able to successfully compile and link your program due to giving the path and library name to use. You were not able to run the program due to the loader not being able to find the library at run time.
You have several options here:
1) you can move the library in a directory that is in the loaders search path.
2) you can modify LD_LIBRARY_PATH which adds additional directories to the loaders search path. Additionally, the directories specified in LD_LIBRARY_PATH will be passed to the linker (it will be appended after all -L flags). You do need to be careful with this, as if you set it globally (say in .bashrc), then it will effect all compilations that you do. You may or may not want this behavior.
3) As others have specified you can use -Wl,rpath=...., but it is deprecated, and I rarely use it.
4) If you need the library installed in an unusual location, you can add a create a file under /etc/ld.so.conf.d that contains, for example (file is yaml.conf):
# yaml default configuration
/opt/yaml/lib
At system boot, the loader reads all the files in this directory and appends the paths to the loader path. If you make a modification to this directory you can use the ldconfig command to cause the loader to reprocess /etc/ld.so.con.d. N.B. I know this works on centOS and Ubuntu flavors of GNU/Linux - can't speak authoritatively on other flavors.
Compile your program with -Wl,-rpath=/usr/local/lib. This way you'll add /usr/local/lib to runtime library search patch of your program and you won't need the LD_LIBRARY_PATH
Warning: since modern dynamic linkers consider rpath as deprecated you can set also runpath (which supersedes it) by specifying -Wl,-rpath=/usr/local/lib,--enable-new-dtags
There is no mystery here. Default library paths for linker (one you call to make your executable file, for example, ld) and runtime linker (one which is responsible for loading shared libraries when you execute your program, for example, ld.so) are different. Runtime linker uses LD_LIBRARY_PATH, while linker uses whatever was configured when ld was build.
In your case, looks like /usr/local/lib is part of one, but not another.
If you're using static linking, all you have to do is tell the linker where your library is at compile/link time. The library (or as much of it as is necessary) gets copied into your executable, and your executable is standalone.
But for various reasons, these days we generally use dynamic linking, not static linking. With dynamic linking, you have to tell the linker where to find the library at compile/link time, and the dynamic linker (ld.so) has to be able to find the library at run time.
If the library was in one of the standard places (/lib, /usr/lib, etc.) there's no problem. But if you linked against a library in a nonstandard place, in general, you have to add that nonstandard place to your LD_LIBRARY_PATH, so that the runtime linker will always be able to find it.

GDB - step in to statically linked libstdc++

For reasons beyond the scope of this question I have to statically link the libstdc++ to my executables. The practical downside is that now GDB can't step in to the stdlib symbols. When I was using the shared linked variants of my executable GDB had no issues to show me the accompanying source files (after I had installed the source package through apt-get under ubuntu which installed it under /build)
How can I step into libstdc++ functions when it is statically linked to an executable in GDB, under Ubuntu (14.04)?
Ubuntu package libstdc++6-4.8-dbg provides the static library with debug symbols at /usr/lib/x86_64-linux-gnu/debug/libstdc++.a; try building your executable against it and then run gdb.