Scripting LLDB to obtain a stack trace after a crash - crash
I'm trying to add the capability of generating a stack trace from a core dump on mac automatically when one of our tests crashes.
I was able to do it pretty easily on linux with
gdb --batch --quiet -ex "thread apply all bt" -ex "quit" <binary> <core file> 2> /dev/null
But I'm having some trouble doing the same on mac (OSX 10.8) with lldb. To start off, the version of lldb I'm using is lldb-310.2.37.
My initial approach was to use the -s option and pass in a script file like so:
target create -c <core file> <binary>
thread backtrace all
quit
Initially I had some trouble which I think was caused by missing a newline at the end of the script file which caused lldb to not exit, but after that was fixed, I'm getting the following:
Executing commands in 'lldbSource'.
(lldb) target create -c <core file> <binary>
Core file '<core file>' (x86_64) was loaded.
(lldb) thread backtrace all
error: Aborting reading of commands after command #1: 'thread backtrace all' failed with error: invalid thread
Aborting after_file command execution, command file: 'lldbSource' failed.
The funny thing is, after that happens, we're still running lldb, and issuing 'thread backtrace all' manually works just fine.
So, approach #2 was to create a python script and use their python API (I tried this before figuring out the initial blocker I described was due to a missing newline).
My script:
import lldb
debugger = lldb.SBDebugger.Create()
target = debugger.CreateTarget('<binary>')
if target:
process = target.LoadCore('<core file>')
if process:
print process.exit_description
for thread in process:
print 'Thread %s:' % str(thread.GetThreadID())
print '\n'.join(str(frame) for frame in thread)
The problem I'm having with this approach is that process.exit_description is returning None (and so is every other thing I've tried; LLDB's python API documentation is almost completely useless).
The output I'm looking for from that call is something similar to the following:
Process 0 stopped
* thread #1: tid = 0x0000, 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16, stop reason = signal SIGSTOP
frame #0: 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16
libsystem_c.dylib`strlen + 16:
-> 0x7fff8aca4670: pcmpeqb (%rdi), %xmm0
0x7fff8aca4674: andl $0xf, %ecx
0x7fff8aca4677: shll %cl, %eax
0x7fff8aca4679: pmovmskb %xmm0, %ecx
This is output automatically by LLDB proper when loading a core file. I don't necessarily need the assembly dump, but I want at least the thread, frame and reason.
I think the first approach I used, if it could be made to work, would be ideal, but either way is OK for me. I don't have control over the LLDB version that's going to be used unfortunately, so I can't just update to latest and see if it's a bug that was fixed.
Other approaches to get the desired output are also welcome. For context, this is going to be called from a perl script.
The --batch command line argument is supported in the version of lldb that ships with Xcode 7.2 (lldb-340.4.119), and possibly earlier.
It's not documented in the man page, but it is documented in lldb --help:
-b
--batch
Tells the debugger to running the commands from -s, -S, -o & -O,
and then quit. However if any run command stopped due to a signal
or crash, the debugger will return to the interactive prompt at the
place of the crash.
These other command line options are useful for lldb automation:
-o
--one-line
Tells the debugger to execute this one-line lldb command after any
file provided on the command line has been loaded.
-k
--one-line-on-crash
When in batch mode, tells the debugger to execute this one-line
lldb command if the target crashes.
Using these facilities, I pieced together the following command:
ulimit -c unlimited && (<binary> || (lldb -c `ls -t /cores/* | head -n1` \
--batch -o 'thread backtrace all' -o 'quit' && exit 1))
This command:
Enables core dumps
Runs the executable <binary>
If it fails, runs lldb on the most recently created core dump in /cores (hopefully the right one)
Prints the backtraces of all threads
Exits with a non-zero status, so that this command can be embedded in other workflows (CI scripts, Makefiles, etc.)
I would have preferred to run lldb on <binary> directly, so that the command does not rely on guessing at the correct core file. But lldb still appears to lack a way to cause it to exit with a non-zero exit status -- an equivalent of GDB's -return-child-result option or quit 1 command -- so I would have no way of knowing if the debugged program was successful or not. I filed an issue requesting such a feature.
TOT lldb from lldb.llvm.org has a new "--batch" mode to work pretty much like the gdb batch mode, and fixes some bugs that made command-line source commands behave better. If you can build your own lldb, you can get these fixes now, otherwise you'll have to wait till the next Xcode update.
The exit_description is None because your process didn't exit, it crashed. Note that at least on OS X several threads can have had simultaneous exceptions by the time the process gets around to crashing, it isn't really useful to say the process crashed. You have to ask the threads. The stop status that lldb prints out when a thread stops is available with the GetStatus method.
stream = lldb.SBStream()
process.threads[0].GetStatus(stream)
print stream.GetData()
That doesn't seem to have a very useful help string.
Related
Sending the Valgrind to the background
I'v started a process with valgrind to find the leaks with the option --leak-check=full and redirecting the stdout and stderr outputs to a file. But the program seems to be running too long and now I want to send the process to the background so that I can close the terminal and check on the results at later time. Here I've found that by using ctrl +z it will suspend the process and with bg and disown commands its possible to remove the process from the terminal and run on the background But when I try that with valgrind the process doesnot respond to the ctrl + z command Is there an alternative way to send the valgrind process to background? Or am I doing the whole thing wrong?
callgrind with spawn-fcgi not creating profiling data
I need to profile my c++ application which starts with spawn-fcgi. I tried to use callgrind but callgrind output in KCachegrind is not showing any information of my applications. valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes --demangle=no --trace-children=yes --callgrind-out-file=%p spawn-fcgi -s /tmp/sock.tmp ./myApp arg1 arg2 This command creates two files 10012 and 10013, but second file is empty. First file have function informations for location spawn-fcgi, ld-2.*.so amd libc. Please suggest correct option to get profiling information for my application.
I experienced similar behaviour when profiled fastcgi process crashed on exit (so statistics isn't dumped on termination with SIGSEGV). I used callgrind_control tool to dump statistics at arbitrary point of time: callgrind_control --dump Also you can stop gathering statistics with callgrind_control -i off, reenable with callgrind_control -i on, reset with callgrind_control -z. See callgrind_control manual for details http://valgrind.org/docs/manual/cl-manual.html .
Merge multiple stdout/stderr into one stdout
I have a development stack with multiple processes running: web server, auto-testing, compilation in background etc. All of these are basic command line commands such as node app.js or lein midje :autotest. Is it possible with one script to run all these processes in "background" and merge their outputs into one stdout (that is: to show it on the screen in terminal)? One of the problem with easy bash solution that I found (using &) is that on Ctrl+C the background processes are obviously kept alive, which is not possible desirable. I have tried adding trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT but this doesn't seem to work reliably on OS X - surprisingly the node processes get killed, but the java ones are still living after the script exits (via Ctrl+C). I can use any scripting language. I would prefer pure bash or JS, but Python or Ruby are OK too. I would also like the ANSI escape colouring to be preserved in the merged output.
You might use multitail utility. It not only allows you to tail log files, but also output of arbitrary CLI programs (lein run, lein midje :autotest, ...). Example: $ multitail --mergeall -cT ANSI -l "lein midje :autotest" -cT ANSI -l "lein ring server-headless" Ctrl-C than kills all processes which are being tailed. If you are OSX user you can install multitail using brew install multitail (assuming that you already have homebrew installed - if not, see http://mxcl.github.io/homebrew/) In order to get more info about multitail configuration you might read man multitail. There are also usage examples at http://www.vanheusden.com/multitail/index.php
valgrind on server process
hi i am new to valgrind. I know how to run valgrind on executable files from command line. But how do you run valgrind on server processes like apache/myqld/traffic server etc .. I want to run valgrind on traffic server (http://incubator.apache.org/projects/trafficserver.html) to detect some memory leaks taking place in the plugin I have written. Any suggestions ? thanks, pigol
You have to start the server under Valgrind's control. Simply take the server's normal start command, and prepend it with valgrind. Valgrind will attach to every process your main "server" process spawns. When each thread or process ends, Valgrind will output its analysis, so I'd recommend piping that to a file (not sure if it comes out on stderr or stdout.) If your usual start command is /usr/local/mysql/bin/mysqld, start the server instead with valgrind /usr/local/mysql/bin/mysqld. If you usually start the service with a script (like /etc/init.d/mysql start) you'll probably need to look inside the script for the actual command the script executes, and run that instead of the script. Don't forget to pass the --leak-check=full option to valgrind to get the memory leak report.
How do you start running the program over again in gdb with 'target remote'?
When you're doing a usual gdb session on an executable file on the same computer, you can give the run command and it will start the program over again. When you're running gdb on an embedded system, as with the command target localhost:3210, how do you start the program over again without quitting and restarting your gdb session?
You are looking for Multi-Process Mode for gdbserver and set remote exec-file filename
Unfortunately, I don't know of a way to restart the application and still maintain your session. A workaround is to set the PC back to the entry point of your program. You can do this by either calling: jump function or set $pc=address. If you munged the arguments to main you may need set them up again. Edit: There are a couple of caveats with the above method that could cause problems. If you are in a multi-threaded program jumping to main will jump the current thread to main, all other threads remain. If the current thread held a lock...then you have some problems. Memory leaks, if you program flow allocates some stuff during initialization then you just leaked a bunch of memory with the jump. Open files will still remain open. If you mmap some files or an address, the call will most likely fail. So, using jump isn't the same thing as restarting the program.
"jump _start" is the usual way.
Presumably you are running gdbserver on the embedded system. You can ask it to restart your program instead of exiting with target extended-remote
Step-by-step procedure Remote: # pwd contains cross-compiled ./myexec gdbserver --multi :1234 Local: # pwd also contains the same cross-compiled ./myexec gdb -ex 'target extended-remote 192.168.0.1:1234' \ -ex 'set remote exec-file ./myexec' \ --args ./myexec arg1 arg2 (gdb) r [Inferior 1 (process 1234) exited normally] (gdb) r [Inferior 1 (process 1235) exited normally] (gdb) monitor exit Tested in Ubuntu 14.04. It is also possible to pass CLI arguments to the program as: gdbserver --multi :1234 ./myexec arg1 arg2 and the ./myexec part removes the need for set remote exec-file ./myexec, but this has the following annoyances: undocumented: https://sourceware.org/bugzilla/show_bug.cgi?id=21981 does not show on show args and does not persist across restarts: https://sourceware.org/bugzilla/show_bug.cgi?id=21980 Pass environment variables and change working directory without restart: How to modify the environment variables and working directory of gdbserver --multi without restarting it?
If you are running regular gdb you can type 'run' shortcut 'r' and gdb asks you if you wish to restart the program
For me the method described in 21.2 Sample GDB session startup works great. When I enter monitor reset halt later at the “(gdb)” prompt the target hardware is reset and I can re-start the application with c (= continue). The load command can be omitted between the runs because there is no need to flash the program again and again.
You can use jump gdb command. For that, you can check your startup script. My startup script has a symbol. .section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: ldr r0, =_estack mov sp, r0 /* set stack pointer */ I wanted to jump to start. That's why I used: jump Reset_Handler
On EFM32 Happy Gecko none of the suggestions would work for me, so here is what I have learned from the documentation on integrating GDB into the Eclipse environment. (gdb) mon reset 0 (gdb) continue (gdb) continue This puts me in the state that I would have expected when hitting reset from the IDE.