Debugging/tracing inside a shared library during runtime? - c++

I'm trying to understand how a certain library works. I've compiled it with my added prinfts and everything is great. Now I want to stop the example program during runtime to look at the call stack, but I can't quite figure out how to do it with gdb. The function I want to break on, is inside a shared library. I've reviewed a previous question here on SO, but the approach doesn't work for me. The language in question is C++. I've attempted to provide the filename and line number, but gdb refuses to understand that, it only lists the source files from the demo app.
Any suggestions?

You can do "break main" first. By the time you hit that, the shared library should be loaded, and you can then set a breakpoint in any of its routines.

There are two cases to consider (and your question doesn't make it clear which case you have):
- your executable is linked with the shared library directly:
this means that GDB will "see" the symbols (and sources) from shared library when you stop on main
- your executable dynamically loads the shared library (e.g. via dlopen):
in that case, GDB will not "see" your shared library until after dlopen completes.
Since you can't see the symbols when you stop at main, I am guessing you have the second case.
You can do "set stop-on-solib-events 1" at the (gdb) prompt, and GDB will stop every time a new shared library is loaded (or unloaded).
You can see which libraries GDB "knows" about via info shared command.
Just wait until you see your target library in that list, before attempting to set breakpoints in it.

Check this out:
http://linux.die.net/man/1/ltrace
it will trace your library calls - probably be useful.
And "strace" does the same thing for system calls.
And with that you should be able to find an entry point... You could set a breakpoint in GDB that way (although i can't explain the details myself)

Related

Given program counter, find the source line in a shared library

I'm trying to debug a segfault in Android's surfaceflinger daemon on a custom made ARM board. The process crashes before dumping the call stack and register content, including the program counter.
Normally I would've used objdump and searched for the program counter. The problem is that part of the call stack is in a shared library. Without using gdb, how can I correlate the program counter with a line in the source file? That is, can the addresses of shared library instructions be determined without running the program?
The simplest solution is to load core dump into gdb and use info symbol <program counter address>, see https://stackoverflow.com/a/7648883/72178.
You can also use addr2line but you will have to provide library starting address in parameters to addr2line, see How to map function address to function in *.so files.
You need your program (and all the relevant shared libraries) to be compiled with debug information (in DWARF format), e.g. by passing some -g (or -g2 or -g3) flag to the GCC compiler when they are built. Notice that with GCC such a debugging option can be mixed with optimization options like -O2
Then you might use utilities like addr2line, or perhaps libraries like libbacktrace. FWIW, the GCC compiler itself (actually its cc1plus) uses that libbacktrace library to print a useful backtrace on SIGSEGV and other terminating signals (on compiler crashes).
BTW, you could (and probably should) enable core(5) dumping and do a post mortem analysis of it with gdb
Notice that due to ASLR, a shared library is loaded (actually mmap(2)-ed) at some "random" page.
Read Drepper's How to Write Shared Libraries paper.

How to find who is calling the shared library functions?

I have some C++ code in place, which internally uses multiple third party libraries. The code compiles fine but during execution it is failing to load some shared library(libintbasic.so). Given the condition, I can not install any library into the system, the only way out is to find which function is calling that library. How could I find that out who is calling that library (my code does not call that directly).
I can not install any library into the system,
That appears to be a bogus claim: clearly you can copy your binary onto the system. Installing an additional library into the same directory is not much harder.
How could I find that out who is calling that library
There are two cases to consider:
your binary or one of the libraries it is directly linked with links to libintbasic.so. Your binary will not run at all, or
your binary, or one of the libraries it is directly linked with calls dlopen("libintbasic.so",...) and fails when that dlopen fails.
Debugging the first case is often easiest by setting LD_DEBUG=files,libs. The dynamic loader will then tell you which libraries are being loaded, and why they are required.
Debugging the second case is easy with gdb: set a breakpoint on dlopen, and execute where and info shared commands every time the breakpoint is hit.
Remove the linking option -lintbasic, you will see all the functions that needs this library in the error messages. This is not clean but it should work fine.
You may use ldd utility recursively for find all dependencies between shared libraries.
The following link also may be useful: Does ldd also show dependencies of dependencies?

Using libunwind in a shared library

I want to provide a generic call stack function as part of a library (.so) using libunwind. However, executables linked against the .so start to fail as soon as I link against libunwind. As I understand it, the problem I'm running into is that libunwind defines the same symbols as the GCC runtime, but the implementation is seemingly not compatible.
Linking statically or dynamically against libunwind doesn't change anything, I get a segfault when throwing an exception in _Unwind_Resume (if linked statically), otherwise the call-stack starts at __cxa_throw (presumably, it has been damaged before.)
Interestingly, the problems only occur when I use GCC, with Clang, everything works just fine.
Is it possible to use libunwind inside a shared library? If not, is there another library which allows me to obtained the name plus instruction pointer offset of the functions on the stack? backtrace() is nearly good enough, but backtrace_symbols() is doing too much formatting which I would have to "un-parse" first.

C++ - dynamic loading behaviour

I have shared library code in c++ . I am replacing the existing c++ shared library with newer one with changes in c++ functions. But the application is not executing the latest code path instead it goes through the previous code path i.e I have added a print with additional messages in the newer library but the print that I get is from previous one.
I have used strings command to check the changes are reflected in the newer library and it is giving positive result.
The application is using dynamic load call to open the library. I don't have the application code with me.
Make file has the following flags for creating shared library.
${CXX} -shared -Wl,--exclude-libs,ALL,-soname,${LIB} ${LDFLAGS} -o $# $(OBJECTS)
Is there any shared library flags that I am missing ?
Anyone has idea for this strange behaviour ?
PS:I am running this in a embedded environment.
I am assuming a few things here:
1. You have not linked your shared library with your executable with "-L" option. This would never unload your shared library.
2. The library is opened during run time using dlopen
Run time library swapping can work only if the mentioned 2 points hold true for you. When a shared library is opened (using dlopen) its loaded into program's memory. So, even if you delete the library from disk (after it has been loaded), the program will still continue to run whatsoever.
When you call dlclose it "decrements the reference count on the dynamic
library handle handle. If the reference count drops to zero and
no other loaded libraries use symbols in it, then the dynamic library
is unloaded."(From the man page)
So, what you should do to implement "refresh library mechanism" is to close the existing library with dlclose and reload your new library with dlopen (make sure that the symbol names are same for the new library as that of the old one) and the symbols accessed will be of new library.
So, such things must be supported within the program or end up using dirty hacks like LD_PRELOAD which will load your library upfront before the original library. But thats another thing which I think you are not looking for.

What is "system-supplied DSO" that gdb references?

I'm running gdb with set verbose on and I'm trying to understand one of the messages I am getting:
Reading symbols from system-supplied DSO at 0x7ffff7ffb000...(no debugging symbols found)...done.
What is thesystem-supplied DSO? After some search I think that DSO might stand for "dynamic shared object". But I still don't understand exactly what gdb is doing here and how I might solve the problem with the debugging symbols not being found (or if it even matters).
Also the program that I am debugging is being compiled with llvm-gcc and has an LLVM pass applied to it. I think that is effecting the behavior of gdb, but I"m not exactly sure how.
So essentially my question is what does the message that gdb prints mean, is it likely to cause a problem, and if so any suggestions on how I could help gdb find the debugging symbols.
According to this document a DSO is:
A dynamic shared object (DSO) is an object file that’s meant to be
used simultaneously— or shared—by multiple applications (a.out files)
while they’re executing.
I believe that a system supplied DSO is just a DLL provided by the OS and loaded by the main executable. Since this is an external library you don't have the debugging symbols of such object unless you download them separately. Typically the release binaries are stripped of debugging symbols but they can have a link to a separate file. A typical Linux distribution provides a package containing the debugging symbols of such binaries ( like the xxx-debuginfo-xxx.rpm for RedHat based distributions).
In this context, system-supplied-DSO means a shared library provided directly by the linux kernel such as VDSO. Debuginfo is indeed available for them, but is packaged along with the kernel rather than userspace. Use debuginfod to automatically fetch them if your distro supports that.