Short link: http://bit.ly/2H2rKjp
- Learn to use GDB/LLDB when you need it
- Practice basic commands
- Drills / Wax on, wax off.
- We stay high level
- What is a debugger?
- App to debug other apps
- Breakpoints
- Stepping
- Expression/Variable evaluation
- Backtrace inspection
- App to debug other apps
- Growing up with
pryandpdb - My primary use cases
- Getting confused from reading the code
- Getting different results than expected
- I like CLI
- Portability
- I did not find "the" great alternative
- You can explore
guimode
./configure --enable-debugwhich is the same as-O0 -ggdb3
| Command | LLDB | GDB |
|---|---|---|
| Loading a program | $ lldb /path/to/foo.app |
$ gdb /path/to/foo.app |
| Listing breakpoints | breakpoint list |
info break |
| Setting a breakpoint with file/line | breakpoint set -f foo.c -l 12 |
break test.c:12 |
| Setting a breakpoint on a name | breakpoint set -n foo |
break main |
| Delete breakpoints | breakpoint delete 1 |
delete 1 |
| Setting watchpoints | watch set var global |
watch global_var |
| Running the program (with arg) | run -txindex |
run -txindex |
| Attach to program by pid | process attach --pid 123 |
attach 123 |
| Attach to program by name (wait for it) | process attach --name bitcoind --waitfor |
attach -waitfor bitcoind |
| Continue from breakpoint | thread continue |
continue |
| Step into function | thread step-in or step |
step |
| Step over function | thread step-over or next |
next |
| Step out of function | thread step-out or finish |
finish |
| List all threads | thread list |
info threads |
| List stack frame variables | frame variable |
info args and info locals |
| Print stack frame variable | frame variable foo or p foo |
p foo |
| Print global variable | target variable baz |
p foo |
| Set environment variables | settings set target.env-vars DEBUG=1 or env DEBUG=1 |
set env DEBUG 1 |
| Evaluate an expression | expr foo() |
call foo() |
| Lookup symbol information | image lookup -v -s gFoo |
info symbol 0x1ec4 |
- Shortest unique string match on command names works too, i.e.
br s -n foo - Setting a
/.gdbinitor/.lldbinit - How to get out of a long loop
- Usually "standard way" of starting your debugger
- Load
bitcoindintolldb - Set your breakpoints
runwith arguments- Use
bitcoin-cliif you need to, to hit the breakpoint
- Load
Where does the RPC getblockchaininfo get values for bestblockhash, difficulty and mediantime from? Find their sources.
Set a breakpoint in init.cpp that only gets hit when -txindex is set.
- Similar to "standard way" with some adjustments:
- Load
src/test/test_bitcoininstead ofbitcoind - Probably
runwith args--log_level=all --run_test=*/lthash_tests
- Load
Change one of the (or more) scripts in the test src/test/multisig_tests.cpp during text execution to make the test fail!
- Change funtional test timeout in
test/functional/test_framework/test_framework.pyL99self.rpc_timeout = 60to avoid timeouts while debugging. - Insert
import pdb; pdb.set_trace()at any point in the (python) functional test before the breakpoint you would like to set is going to be hit. - Run the functional test
./test/functional/example_test.py, it should be stopped at the inserted line. - Get the pid of the node you wnat to set the breakpoint in
self.nodes[0].process.pid. - Start
lldb, attaching to the pidlldb -p 12345(which causes it to be stopped bylldb) - Set your breakpoints and let the process
continuefrom withinlldb - Let the process
continuefrom withinpdb - The node should now run into the breakpoint in
lldb
Watch the removal of tx from the mempool in TrimToSize using test/functional/mempool_limit.py.
Use test/functional/wallet_avoidreuse.py to see where the avoid reuse setting is making a difference when getting your balance.
Watch messages as they come in to a syncing node in test/functional/p2p_node_network_limited.py (hint: ProcessMessage).
Explore TxIndex and BaseIndex inheritance relationship.