How to make LLDB quit on success, wait on failure? - c++

This is the Clang version of:
Make gdb quit automatically on successful termination?
How to have gdb exit if program succeeds, break if program crashes?
Running my application many times, programmatically, over a large number of possible inputs, I've occasionally encountered a segmentation fault.
I'd like each test invocation to be run under lldb so that I can get a backtrace for further debugging. If an invocation exits without a crash, I'd like lldb to automatically quit so that the test harness progresses to the next iteration. This way I can set the whole thing off over lunchtime and only have the suite interrupted when something crashes.
Bonus points for having lldb auto-quit in all cases, but first print a backtrace if the program crashed.
I'm currently able to automate at least the initial run command:
lldb -o run -f $CMD -- $ARGS

I'm having difficulty finding an online command reference but it looks like the -batch command line option will get you the basic "exit on success/prompt on fail" behaviour.
For a backtrace and auto-quit on failure I think you need the --source-on-crash option...
-K <filename>
--source-on-crash <filename>
When in batch mode, tells the debugger to source this file of lldb
commands if the target crashes.
So, create the command file with something like...
echo -e 'bt\nquit' > lldb.batch
and then invoke as...
lldb --batch -K lldb.batch -o run -f $CMD -- $ARGS

Related

During startup program exited normally. gdb doesn't break at breakpoints

I'm receiving this gdb error on any code I try to debug any program with gdb. Here's the simplest process that reproduces the error
Create a main.cpp file with this content:
int main(){
return 0;
}
Run g++ -g main.cpp
Run gdb a.out
Inside gdb set a break point at line 2 with break 2
In gdb run the program with run
Output:
Starting program: /tmp/test/a.out
During startup program exited normally.
This is all done with gdb on the command line. I've tried using g++ and gcc with the same result. I'm not really sure where to go from here.
gdb version = 9.2
g++ version = 9.3.0
EDIT: I figured out what is causing the issue, but not how to fix it. The issue seems to be something related to my SHELL variable. I'm currently using xonsh as my shell but when I set my SHELL environment variable back to /bin/bash everything works as expected. Is there anything I can do to fix this while using xonsh? Should I report this to xonsh, gdb, both or neither?
I'm currently using xonsh as my shell but when I set my SHELL environment variable back to /bin/bash everything works as expected. Is there anything I can do to fix this while using xonsh? Should I report this to xonsh, gdb, both or neither?
This might be your xonsh startup problem, or it might be xonsh problem, or it could be that xonsh doesn't do what GDB expects it to do.
Normally, GDB forks / execs $SHELL -c "/path/to/your/exe $args" and expects the $SHELL to exec your program (this is done so shell redirection still works under GDB).
Only after that exec will GDB start setting breakpoints, etc.
If you have some xonsh init-file, which e.g. causes xonsh to exec something else, things could go bad. So I suggest trying to remove any such ~/.xonshrc or whatever it's called file, and seeing whether that fixes the problem.
If it doesn't, it could be that xonsh e.g. forks and execs your binary in a child (grandchild of GDB) instead of doing it directly, or it could be that xonsh doesn't understand the -c ... syntax.
If you don't care about redirection, you could also ask GDB to not use $SHELL at all: set startup-with-shell off. Documentation.

How to run program in gdb via bashscript with backtrace?

I'm trying to run my program TestApc via gdb and get useful data when my program crash with back trace command ("bt" command).
I wrote a bash script , which look like:
#!/bin/bash
gdb -ex=r --args ./TestApc
When the program crash, I can't type the "bt" command (because I get out from the gdb console)
Is there a way to stay on gdb after the crash ?

Is it possible to configure GDB so it auto quit on normal program termination?

I'm debugging a shell script on OSX with mysterious segfault in the middle. The command in question does not segfault if executed outside of script.
So i need to somehow run all programs in script with GDB attached so i can debug this segfault. Is it possible to configure GDB so it will run the program and quit if program terminated correctly? I have tried the following code:
echo file ifconfig > gdbcfg
echo run >> gdbcfg
echo quit >> gdbcfg
gdb -x gdbcfg
But this is not working since GDB tries to execute quit command before application terminates normally :(. Is it possible to somehow instruct GDB to wait for application normal termination and quit after that?
Maybe my approach is too comples and it's just some GDB flag like "load and run this application, quit if all is ok"?
Why not just make the process to dump a core file and analyze it later with gdb? I mean ulimit -c unlimited and then (after the core is dumped) gdb ./process core?
But this is not working since GDB tries to execute quit command before application terminates
No: it's not working because (assuming you pasted your actual code) the gdbcfg contains a single quit after your commands are executed (and no run). What you want is:
echo file ifconfig > gdbcfg
echo run >> gdbcfg
echo quit >> gdbcfg
gdb -x gdbcfg
A more UNIXy way to spell that is:
echo >gdbcfg <<EOF
file ifconfig
run
quit
EOF
gdb -x gdbcfg
Update:
If the file contents of gdbcfg contains all three commands, then your understanding of the problem is incorrect: GDB will wait for each command to finish before executing the next one.

How to have gdb exit if program succeeds, break if program crashes?

I seem to have some kind of multithreading bug in my code that makes it crash once every 30 runs of its test suite. The test suite is non-interactive. I want to run my test suite in gdb, and have gdb exit normally if the program exits normally, or break (and show a debugging prompt) if it crashes. This way I can let the test suite run repeatedly, go grab a cup of coffee, come back, and be presented with a nice debugging prompt. How can I do this with gdb?
This is a little hacky but you could do:
gdb -ex='set confirm on' -ex=run -ex=quit --args ./a.out
If a.out terminates normally, it will just drop you out of GDB. But if you crash, the program will still be active, so GDB will typically prompt if you really want to quit with an active inferior:
Program received signal SIGABRT, Aborted.
0x00007ffff72dad05 in raise (sig=...) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
in ../nptl/sysdeps/unix/sysv/linux/raise.c
A debugging session is active.
Inferior 1 [process 15126] will be killed.
Quit anyway? (y or n)
Like I said, not pretty, but it works, as long as you haven't toggled off the prompt to quit with an active process. There is probably a way to use gdb's quit command too: it takes a numeric argument which is the exit code for the debugging session. So maybe you can use --eval-command="quit stuff", where stuff is some GDB expression that reflects whether the inferior is running or not.
This program can be used to test it out:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
if (time(NULL) % 2) {
raise(SIGINT);
}
puts("no crash");
return EXIT_SUCCESS;
}
You can also trigger a backtrace when the program crashes and let gdb exit with the return code of the child process:
gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg
The easiest way is to use the Python API offered by gdb:
def exit_handler(event):
gdb.execute("quit")
gdb.events.exited.connect(exit_handler)
You can even do it with one line:
(gdb) python gdb.events.exited.connect(lambda x : gdb.execute("quit"))
You can also examine the return code to ensure it's the "normal" code you expected with event.exit_code.
You can use it in conjuction with --eval-command or --command as mentioned by #acm to register the event handler from the command line, or with a .gdbinit file.
Create a file named .gdbinit and it will be used when gdb is launched.
run
quit
Run with no options:
gdb --args prog arg1...
You are telling gdb to run and quit, but it should stop processing the file if an error occurs.
Make it dump core when it crashes. If you're on linux, read the man core man page and also the ulimit builtin if you're running bash.
This way when it crashes you'll find a nice corefile that you can feed to gdb:
$ ulimit -c unlimited
$ ... run program ..., gopher coffee (or reddit ;)
$ gdb progname corefile
If you put the following lines in your ~/.gdbinit file, gdb will exit when your program exits with a status code of 0.
python
def exit_handler ( event ):
if event .exit_code == 0:
gdb .execute ( "quit" )
gdb .events .exited .connect ( exit_handler )
end
The above is a refinement of Kevin's answer.
Are you not getting a core file when it crashes? Start gdb like this 'gdb -c core' and do a stack traceback.
More likely you will want to be using Valgrind.

How to run gdb with LD_PRELOAD?

I have a program using LD_PRELOAD. The program should be run like
this, "LD_PRELOAD=/path/to/libfoo.so qemu -U LD_PRELOAD a.out", if
without gdb.
Here are what I did while running gdb.
(gdb) set environment LD_PRELOAD=/nfs_home/chenwj/tools/lib/libdbo.so
(gdb) file /nfs_home/chenwj/tools/bin/qemu-i386
(gdb) r -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1
But gdb gave me the error below
Starting program: /nfs_home/chenwj/tools/bin/qemu-i386 -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1
bash: open "/bin/bash" failed: Permission denied
During startup program exited with code 66.
Any sugguestion appreciated.
Regards, chenwj
GDB does not invoke your executable directly. Instead, it does
bash -c '/nfs_home/chenwj/tools/bin/qemu-i386 -U LD_PRELOAD bzip2_base.i386-m32-gcc44-annotated input.source 1'
This is done so that bash takes care of I/O redirection (which you are not using).
My guess is that /bin/bash doesn't work when LD_PRELOAD=libdbo.so is in effect, though I don't understand the exact nature of failure.
One way to work around this problem is to create a wrapper executable, implementing C equivalent of this:
export LD_PRELOAD=/nfs_home/chenwj/tools/lib/libdbo.so
exec /nfs_home/chenwj/tools/bin/qemu-i386 "$#"
and debug that executable (without setting LD_PRELOAD). You'll see an extra SIGTRAP when the wrapper execve()s the wrapped qemu-i386, which you should ignore and continue.