Struggling with using gdb to debug C++ code w/ Ada library - c++

I can't get into the specifics, for a variety of reasons, but here's the essential architecture of what I'm working with
I have a C++ framework, which uses C++ object files built by me to execute a dynamic simulation.
The C++ libraries call, among other things, a shared (.so) library, written in Ada.
As best as I can tell, the Ada library (which is a large collection of nontrivial code) is generating exceptions on fringe cases, but I'm having trouble isolating the function that is generating the exception.
Here's what I'm using:
CentOS 4.8 (Final)
gcc 3.4.6 (w/ gnat)
gdb 6.3.0.0-1.162.el4rh
This is the error I get under normal execution:
terminate called without an active exception
raised PROGRAM_ERROR : unhandled signal
I can get gdb to catch the exception as soon as it returns to the C++, but I can't get it to catch inside the Ada code. I've made sure to compile everything with -g, but that doesn't seem to help the problem.
When I try to catch/break on the signal/exception in gdb (which politely tells me Catch of signal not yet implemented), I get this:
[Thread debugging using libthread_db enabled]
[New thread -1208371520 (LWP 14568)]
terminate called without an active exception
Program received signal SIGABRT, Aborted.
[Switching to thread -1208371520 (LWP 14568)]
0x001327a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
I believe the terminate called [...] line is from the framework. When I try to capture that break, then run a backtrace (bt), I get something like this:
#0 0x001327a2 in gdb makes me want to flip tables.
#1 0x00661825 in raise () from /lib/tls/libc.so.6
#2 0x00663289 in abort () from /lib/tls/libc.so.6
#3 0x0061123e in __gnu_cxx: __verbose_terminate_handler () from /usr/lib/libstdc++.so.6
#4 0x0060eed1 in __xac_call_unexpected () from /usr/lib/libstdc++.so.6
#5 0x0060ef06 in std::terminate () from /usr/lib/libstdc++.so.6
#6 0x0060f0a3 in __xax_rethrow () from /usr/lib/libstdc++.so.6
#7 0x001fe526 in cpputil::ExceptionBase::Rethrow (scope=#0xbfe67470) at ExceptionBase.cpp:140
At that point, it's into the framework code.
I've read several guides and tutorials and man pages online, but I'm at a bit of a loss. I'm hoping that someone here can help get me pointed in the right direction.

It sounds like you're able to compile the Ada source code. Assuming that's the case, in the subprogram(s) that are being called through whose execution the exceptions are being raised, add an exception handler at the end that dumps the exception information:
when E : others =>
Ada.Text_IO.Put_Line(Ada.Exceptions.Exception_Information(E));
raise;
You'll also need to add a 'with' of Ada.Exceptions to the package. And Ada.Text_IO if that isn't already present.
I'm not sure exactly what you'll get out from that version of GNAT, but it's probably the invocation addresses which you can then decode using addr2line.

Could you start the C++ framework from an Ada main? If so, and you can propagate the exceptions through the C++ framework to the Ada main, its last chance handler ought to give you a pretty good report with exception, source file and line where it occurred, and a stack dump for addr2line. My experience with these is that the debugger usually isn't needed after that.
I could be off beam here because I haven't used a Gnat anywhere near as old as yours...

Related

How do I find out why gdb has stopped

While using GDB to debug a program I have been having issues with the program stopping while in debug mode. When I do a backtrace, I find that it's deep within a proprietary third party library call stack and I am looking to find out why exactly the program has stopped. I am still just a GDB beginner so I still unsure of how to do this. Looking at the backtrace I noticed that "__cxa_throw () from /usr/lib64/libstdc++.so.6" so I am presuming that an exception of some sort was thrown but I would like to know how to get more information about it, if possible.
Try using the backtrace command which will show how your program got in the state it is. Here you can find more details.
How do I find out why gdb has stopped
GDB usually tells you right away, e.g.
Program received signal SIGABRT, Aborted.
0x00007ffff7750425 in __GI_raise (sig=<optimized out>)
The program stopped because it received a signal.
I find that it's deep within a proprietary third party library call stack and I am looking to find out why exactly the program has stopped.
It has stopped exactly for the reason GDB told you about.
Looking at the backtrace I noticed that __cxa_throw() from /usr/lib64/libstdc++.so.6 so I am presuming that an exception of some sort was thrown but I would like to know how to get more information about it.
Presence of __cxa_throw does indicate that an exception has been thrown (and presence of std::terminate() indicates that it was an uncaught exception).
Without debug info for the third-party library, your choices of finding the cause are limited:
You can read the documentation for this library and double-check that you have not violated any preconditions that it requires
You can disassemble the routine that called __cxa_throw and figure out exactly why that routine was called.

Can gdb be used to backtrace when exceptions are caught?

I have just started using c++ exceptions and want to get it right. What I have in mind is to generate some sort of backtrace information when exceptions are caught. Initially I had ideas similar to Call-stack for exceptions in C++ but eventually figured out that's not quite good.
I have also read How to generate a stacktrace when my gcc C++ app crashes but do not want to add more complexity to my current project. Since, I only need the backtracing when in debug mode, I was hoping I could be using gdb for that purpose.
My strategy has been to insert breakpoint in the catch block and then go up through the call stack to exactly pinpoint why the exception was thrown in the first place (or what caused it)? Unfortunatly, I cannot seem to be able to do this since when gdb reaches the breakpoint, it clears the call stack and I can only see main (that's where I catch). Is this supposed to happen or am I doing something wrong here?
Edit:
I just like to summarize the methods here for other folks:
1st Method (by paulsm4). Set a catchpoint via catch throw for catching on throw or catch catch for catching on catch! Then call backtrace
2nd Method (by aschepler) Set a breakpoint on __cxa_throw and then backtrace
3rd Method (in Qt Creator -- if you happen to use) You can easily set a breakpoint on throw or catch!
Edit_2: Using Qt Creator debugger, it seems that setting a breakpoint on __cxa_begin_catch is also an equivalent to catch catch :)
This this:
http://sourceware.org/gdb/onlinedocs/gdb/Set-Catchpoints.html
You can use catchpoints to cause the debugger to stop for certain
kinds of program events, such as C++ exceptions or the loading of a
shared library. Use the catch command to set a catchpoint.
So the answer should be "yes", and it should avoid the problems with the two links you cited.
Please post back if it helped! Personally, I've never tried this GDB feature myself :)
Summary of answers from the comments:
1st Method (by paulsm4). Set a catchpoint via catch throw for catching on throw or catch catch for catching on catch! Then call backtrace
2nd Method (by aschepler) Set a breakpoint on __cxa_throw and then backtrace
3rd Method (in Qt Creator -- if you happen to use) You can easily set a breakpoint on throw or catch!
Using Qt Creator debugger, it seems that setting a breakpoint on __cxa_begin_catch is also an equivalent to catch catch

Any likely causes of a double-free in ncurses?

I have an ncurses app that does the following, sometimes instantly after launch, sometimes after some fiddling.
malloc: *** error for object 0x100300400: double free
Program received signal SIGABRT, Aborted
(gdb) where
#0 0x00007fff846a7426 in read ()
#1 0x00007fff83f3d775 in _nc_wgetch ()
#2 0x00007fff83f3de3f in wgetch ()
(and so on into my code)
Does anyone have suggestions for likely things to pursue?
It looks like you are using glibc, likely on an x86_64 Linux system.
The tool to use for any kind of heap corruption on Linux/x86_64 is Valgrind. It will just immediately give you the answer, so there is no point in guessing where the problem might be (and it could be anywhere).

Run an Application in GDB Until an Exception Occurs

I'm working on a multithreaded application, and I want to debug it using GDB.
Problem is, one of my threads keeps dying with the message:
pure virtual method called
terminate called without an active exception
Abort
I know the cause of that message, but I have no idea where in my thread it occurs. A backtrace would really be helpful.
When I run my app in GDB, it pauses every time a thread is suspended or resumed. I want my app to continue running normally until one of the threads dies with that exception, at which point everything should halt so that I can get a backtrace.
You can try using a "catchpoint" (catch throw) to stop the debugger at the point where the exception is generated.
The following excerpt From the gdb manual describes the catchpoint feature.
5.1.3 Setting catchpoints
You can use catchpoints to cause the debugger to stop for certain kinds of program events, such as C++ exceptions or the loading of a shared library. Use the catch command to set a catchpoint.
catch event
Stop when event occurs. event can be any of the following:
throw
The throwing of a C++ exception.
catch
The catching of a C++ exception.
exec
A call to exec. This is currently only available for HP-UX.
fork
A call to fork. This is currently only available for HP-UX.
vfork
A call to vfork. This is currently only available for HP-UX.
load or load libname
The dynamic loading of any shared library, or the loading of the library libname. This is currently only available for HP-UX.
unload or unload libname
The unloading of any dynamically loaded shared library, or the unloading of the library libname. This is currently only available for HP-UX.
tcatch event
Set a catchpoint that is enabled only for one stop. The catchpoint is automatically deleted after the first time the event is caught.
Use the info break command to list the current catchpoints.
There are currently some limitations to C++ exception handling (catch throw and catch catch) in GDB:
If you call a function interactively, GDB normally returns control to you when the function has finished executing. If the call raises an exception, however, the call may bypass the mechanism that returns control to you and cause your program either to abort or to simply continue running until it hits a breakpoint, catches a signal that GDB is listening for, or exits. This is the case even if you set a catchpoint for the exception; catchpoints on exceptions are disabled within interactive calls.
You cannot raise an exception interactively.
You cannot install an exception handler interactively.
Sometimes catch is not the best way to debug exception handling: if you need to know exactly where an exception is raised, it is better to stop before the exception handler is called, since that way you can see the stack before any unwinding takes place. If you set a breakpoint in an exception handler instead, it may not be easy to find out where the exception was raised.
To stop just before an exception handler is called, you need some knowledge of the implementation. In the case of GNU C++, exceptions are raised by calling a library function named __raise_exception which has the following ANSI C interface:
/* addr is where the exception identifier is stored.
id is the exception identifier. */
void __raise_exception (void **addr, void *id);
To make the debugger catch all exceptions before any stack unwinding takes place, set a breakpoint on __raise_exception (see section Breakpoints; watchpoints; and exceptions).
With a conditional breakpoint (see section Break conditions) that depends on the value of id, you can stop your program when a specific exception is raised. You can use multiple conditional breakpoints to stop your program when any of a number of exceptions are raised.
FWIW, apparently, in gcc 4.1, the appropriate function name has changed and one must set a breakpoint in this function.
__cxa_pure_virtual
Only below one worked for me with gdb 8.3:
break _Unwind_RaiseException
"catch throw" or "break __cxx_throw" didn't work for me.
Set a breakpoint on __pure_virtual

What is __kernel_vsyscall?

I got a core that looks very different from the ones I usually get - most of the threads are in __kernel_vsyscall() :
9 process 11334 0xffffe410 in __kernel_vsyscall ()
8 process 11453 0xffffe410 in __kernel_vsyscall ()
7 process 11454 0xffffe410 in __kernel_vsyscall ()
6 process 11455 0xffffe410 in __kernel_vsyscall ()
5 process 11474 0xffffe410 in __kernel_vsyscall ()
4 process 11475 0xffffe410 in __kernel_vsyscall ()
3 process 11476 0xffffe410 in __kernel_vsyscall ()
2 process 11477 0xffffe410 in __kernel_vsyscall ()
1 process 11323 0x08220782 in MyClass::myfunc ()
What does that mean?
EDIT:
In particular, I usually see a lot of threads in "pthread_cond_wait" and "___newselect_nocancel" and now those are on the second frame in each thread - why is this core different?
__kernel_vsyscal is the method used by linux-gate.so (a part of the Linux kernel) to make a system call using the fastest available method, preferably the sysenter instruction. The thing is properly explained by Johan Petersson.
When you make a system call (like reading from a file, talking to hardware, writing to sockets) you're actually creating an interrupt. The system then handles the interrupt in kernel mode and your call returns with the result. Most of the time it's unusual for you to have a lot of threads in syscall unless you're making blocking calls, in which case it's expected.
More specifically, it means the thread is waiting on a kernel level system call. But that's (unfortunately for my points) already in the name :)
In addition to the already given good link to explanation of what linux-gate.so is, I'd like to answer "why is this core different?". Most recent (newer than 2.5.68) 32-bit Linux systems use VDSO page (aka linux-gate.so.1), and 64-bit systems will soon start as well (64-bit VDSO was introduced in kernel 2.6.24).
If you develop on an older system, or with an old glibc, then you would never see __kernel_vsyscall(), either because the kernel didn't create VDSO at all, or because (old) glibc doesn't use it even when VDSO is present.
As Adam said, the main reason is performance. See this link for some old numbers http://lkml.org/lkml/2002/12/9/13.
If you have a vDSO enabled kernel, you're not using interrupts to run syscalls, as Stefan said, actually was because interrupts was getting slower that the whole vDSO thing was added to the kernel.