Skip to content

Instantly share code, notes, and snippets.

@gubatron
Last active January 18, 2023 16:21
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gubatron/36784ee38e45cb4bf4c7a82ecc87b6a8 to your computer and use it in GitHub Desktop.
Save gubatron/36784ee38e45cb4bf4c7a82ecc87b6a8 to your computer and use it in GitHub Desktop.
How to build bitcoin and debug with GDB or LLDB

Hack and Debug with gdb or LLDB, using Bitcoin's code as an example

/*
 * Copyright CC0 Angel Leon <@gubatron>
 */

Update: I believe now it's better to use lldb, at least on MacOS, here's a LLDB to GDB command map

Here's how to use gdb to debug issues you might be having hacking bitcoinclassic (or any other C++ program)

If you're in Ubuntu you might want to have the following packages installed

sudo apt install git build-essential pkg-config dh-autoreconf libtool autotools-dev automake libssl-dev libevent-dev bsdmainutils libzmq3-dev libminiupnpc-dev libboost-all-dev

We'll also need to add an apt repo to install berkley db dependencies

sudo add-apt-repository ppa:bitcoinclassic/bitcoinclassic
sudo apt-get update
sudo apt-get install libdb4.8-dev libdb4.8++-dev

Check out the main repo git clone https://github.com/bitcoinclassic/bitcoinclassic

Make sure to have it forked on github to your account, now let's add your remote clone to our local instance cd bitcoinclassic git remote add myusername https://github.com/myusername/bitcoinclassic

Now when you create a branch or have commits to push you push them to your myusername remote.

First build ever

./autogen.sh

./configure --enable-debug

make -j 8

Further builds

From Scratch

make clean; ./configure --enable debug; make -j 8

Normal builds

To compile ongoing code changes make -j 8

If everything went fine, you should see output similar to...

AR       libbitcoin_wallet.a
  CXXLD    bitcoin-cli
  CXXLD    bitcoin-tx
  CXXLD    bitcoind
  CXXLD    test/test_bitcoin
make[1]: Nothing to be done for `all-am'.

Running gdb

First make sure you're in the folder where our executable bitcoind is cd src

Running gdb

On my mac I have to run it with sudo

$ sudo gdb
Password:
GNU gdb (GDB) 8.0.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) 

Loading the symbol table of our executable

Now let's load the executable we're about to debug, with the file command.

(gdb) file bitcoind
Reading symbols from bitcoind...warning: dsym file UUID doesn't match the one in /Users/gubatron/workspace.frostwire/bitcoinclassic/src/bitcoind
warning: can't find symbol '_Z10ParseHexUVRK8UniValueRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE' in minsymtab
warning: can't find symbol '_Z21getAllNetMessageTypesv' in minsymtab
warning: can't find symbol '_ZN9Streaming10BufferPool10writeInt32Ej' in minsymtab
done.

You can alternatively start gdb and pass the executable as an argument

$ gdb bitcoind
GNU gdb (GDB) 8.0.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bitcoind...
warning: dsym file UUID doesn't match the one in /Users/gubatron/workspace.frostwire/bitcoinclassic/src/bitcoind

warning: can't find symbol '_Z10ParseHexUVRK8UniValueRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE' in minsymtab

warning: can't find symbol '_Z21getAllNetMessageTypesv' in minsymtab

warning: can't find symbol '_ZN9Streaming10BufferPool10writeInt32Ej' in minsymtab
done.

Setting breakpoints

If you know where you want your program to start before hand you can set breakpoints before you run it. Now that we have a symbol table loaded, let's set up a few breakpoints. We do that with the b <filename>:<linenumber> command

(gdb) b main.cpp:3560
Breakpoint 1 at 0x1001c8ac8: file main.cpp, line 3560.
(gdb) b bitcoind.cpp:174
Breakpoint 2 at 0x1000091a2: file bitcoind.cpp, line 174.
(gdb) b init.cpp:164
Breakpoint 3 at 0x1000b22c8: file /usr/local/include/boost/signals2/detail/slot_groups.hpp, line 164.
(gdb) b init.cpp:174
Breakpoint 4 at 0x1000b25c3: file init.cpp, line 174.

Running our executable from gdb

Since the file is loaded, we can tell gdb to "run", the run command can receive the arguments we pass to our executable. If we want to setup a break point at the start and run it, we can do a b main and then run <my program args, or we can use the shortcut start <myprogram args>


macOS caveat: If you're doing this tutorial from a Mac and you're getting an error like this:

(gdb) run -server -keypool=1 -rest -discover=0 -testnet -datadir=/Users/gubatron/tmp/bitcoind
Starting program: /Users/gubatron/workspace.frostwire/bitcoinclassic/src/bitcoind -server -keypool=1 -rest -discover=0 -testnet -datadir=/Users/gubatron/tmp/bitcoind
During startup program terminated with signal ?, Unknown signal.

create or edit your ~/.gdbinit file and add the following line and restart gdb: set startup-with-shell off


So let's start our program and set a breakpoint at the start (make sure the datadir folder exists beforehand):

(gdb) start -server -keypool=1 -rest -discover=0 -testnet -datadir=/Users/gubatron/tmp/bitcoind
Temporary breakpoint 1 at 0x1000099e4: file bitcoind.cpp, line 187.
Starting program: /Users/gubatron/workspace.frostwire/bitcoinclassic/src/bitcoind -server -keypool=1 -rest -discover=0 -testnet -datadir=/Users/gubatron/tmp/bitcoind
[New Thread 0x1903 of process 30164]
warning: unhandled dyld version (15)

Thread 2 hit Temporary breakpoint 1, main (argc=7, argv=0x7fff5fbff628) at bitcoind.cpp:187
187	    SetupEnvironment();

Since this view isn't the friendliest of all, here's a cool trick, press Ctrl-x-s

With Ctrl-x-2 you get multiple windows, so you can see the stack.

Debugging bitcoind with LLDB

MacBook-Pro:src gubatron$ sudo lldb bitcoind
Password:
(lldb) target create "bitcoind"
Current executable set to 'bitcoind' (x86_64).

(lldb) b main
Breakpoint 1: where = bitcoind`main + 36 at bitcoind.cpp:202, address = 0x00000001000097e4
(lldb) run -server -keypool=1 -rest -discover=0 -testnet -datadir=/Users/gubatron/tmp/bitcoind                                                                  There is a running process, kill it and restart?: [Y/n] Y
Process 85476 exited with status = 9 (0x00000009) 
Process 85483 launched: '/Users/gubatron/workspace.frostwire/bitcoin-abc/src/bitcoind' (x86_64)
Process 85483 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001000097e4 bitcoind`main(argc=7, argv=0x00007fff5fbff630) at bitcoind.cpp:202
   199 	}
   200 	
   201 	int main(int argc, char *argv[]) {
-> 202 	    SetupEnvironment();
   203 	
   204 	    // Connect bitcoind signal handlers
   205 	    noui_connect();
Target 0: (bitcoind) stopped.

Then type gui and enjoy the view.

LLDB to GDB command map

@talhamalik883
Copy link

how can i debug any rpc call through lldb ?

@basldjfiodsa
Copy link

Cannot add PPA: 'ppa:~bitcoinclassic/ubuntu/bitcoinclassic'.
The team named '~bitcoinclassic' has no PPA named 'ubuntu/bitcoinclassic'
Please choose from the following available PPAs:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment