用vim单步调试bitcoin
区块#0. 前言
参加了区块链研习社的源码研读班,准备研读下比特币核心(Bitcoin Core)的源码,为了更好的掌握其脉络,单步调试是必不可少的,那么就先来准备下环境吧~
这里通过vim+vimgdb插件,来构造一个gdb的调试环境。
区块#1. 环境搭建
1.1 vim环境
安装vim+vimgdb插件,该插件以补丁方式提供,需要重新编译安装vim,有些遗憾该插件很久没有更新了,目前仅支持vim7.4版本。
1.1.1 源码下载
- vim7.4及对应vimgdb插件下载
$ wget https://github.com/vim/vim/archive/v7.4.tar.gz
$ git clone https://github.com/cpiger/vimgdb-for-vim7.4.git
1.1.2 打上补丁
- 解压vim7.4并打上vimgdb补丁
$ tar -zxf v7.4.tar.gz
$ ln -s vim-7.4/ vim74
$ patch -p0 < vimgdb-for-vim7.4/vim74.patch
patching file vim74/src/auto/configure
patching file vim74/src/buffer.c
patching file vim74/src/clewn/gdb.h
patching file vim74/src/clewn/gdb_lvl2.c
patching file vim74/src/clewn/gdb_lvl3.c
patching file vim74/src/clewn/misc.c
patching file vim74/src/clewn/misc.h
patching file vim74/src/clewn/obstack.c
patching file vim74/src/clewn/obstack.h
patching file vim74/src/config.h.in
patching file vim74/src/config.mk.in
patching file vim74/src/configure.in
patching file vim74/src/eval.c
patching file vim74/src/ex_cmds.c
patching file vim74/src/ex_getln.c
patching file vim74/src/feature.h
patching file vim74/src/gdb.c
patching file vim74/src/globals.h
patching file vim74/src/gui.c
patching file vim74/src/gui_gtk_x11.c
patching file vim74/src/gui_x11.c
patching file vim74/src/main.c
patching file vim74/src/Makefile
patching file vim74/src/normal.c
patching file vim74/src/option.c
patching file vim74/src/option.h
patching file vim74/src/os_unix.c
patching file vim74/src/proto/gdb.pro
patching file vim74/src/proto.h
patching file vim74/src/screen.c
patching file vim74/src/structs.h
patching file vim74/src/version.c
patching file vim74/src/window.c
若没有任何错误信息,即打补丁成功。
1.1.3 编译安装
(1)执行configure命令
$ cd vim74/
$ ./configure --with-features=huge --enable-pythoninterp --with-python-config-dir=/usr/lib/python2.7/config-x86_64-linux-gnu/ --enable-perlinterp --enable-cscope --enable-multibyte --enable-xim --enable-gdb --prefix=/home/rzexin/Software/ALL/vimgdb
核心参数是:--enable-gdb,根据需要开启其他属性
参数说明:
- --enable-gdb:开启gdb支持
- --with-features=huge:支持最大特性
- --enable-pythoninterp:启用Vim对python编写的插件的支持
- --enable-multibyte和--enable-xim:需要在Vim中输入中文,开启这两个特性
- --enable-cscope:Vim对cscope支持
- --with-python-config-dir=/usr/lib/python2.7/config-x86_64-linux-gnu/ 指定 python 路径
- --prefix=/home/rzexin/Software/ALL:设定编译安装路径
(2)修改Makefile文件
设置--prefix并未修改src/Makefile中的配置,将以下三行注释掉,以便vim可以安装到我们指定的目录
# BINDIR = /opt/bin
# MANDIR = /opt/share/man
# DATADIR = /opt/share
(3)编译&安装
-j:是make命令执行线程数,可根据机器性能调大一点,缩短编译等待时间
CFLAGS="-O2 -D_FORTIFY_SOURCE=1":不加该参数,安装后启动vim会core
$ make -j2 CFLAGS="-O2 -D_FORTIFY_SOURCE=1"
$ make install
$ tree -L 2 ~/Software/ALL/vimgdb/
/home/rzexin/Software/ALL/vimgdb/
├── bin
│ ├── ex -> vim
│ ├── rview -> vim
│ ├── rvim -> vim
│ ├── view -> vim
│ ├── vim
│ ├── vimdiff -> vim
│ ├── vimtutor
│ └── xxd
└── share
├── man
└── vim
1.1.4 环境配置
(1)设置环境变量
之所以要安装到/home/rzexin/Software/ALL/vimgdb目录,还是因为vimgdb插件支持的vim版本过低,会导致不少基于高版本vim的插件使用不了,如:vim-go(v7.4.1689+)、YouCompleteMe(v7.4.1578+)等。
$ vim
vim-go requires Vim 7.4.1689 or Neovim, but you're using an older version.
Please update your Vim for the best vim-go experience.
If you really want to continue you can set this to make the error go away:
let g:go_version_warning = 0
Note that some features may error out or behave incorrectly.
Please do not report bugs unless you're using Vim 7.4.1689 or newer.
YouCompleteMe unavailable: requires Vim 7.4.1578+.
Press ENTER or type command to continue
通过别名方式,单独提供一个专门用于gdb调试的vim:
vimg
,vim
命令还是对应系统自带vim
alias vimg='/home/rzexin/Software/ALL/vimgdb/bin/vim'
(2)拷贝运行环境配置
$ cp -r vimgdb-for-vim7.4/vimgdb_runtime/* ~/.vim
(3)激活命令帮助
$ cd ~/.vim/doc/
$ vimg
执行命令:helptags .
,而后就能使用:help vimgdb
打开vimgdb的帮助文档了:
1.2 bitcoin环境
安装好vim及vimgdb插件后,我们下面来获取bitcoin-core源码了。
1.2.1 源码下载
下载当前最新版本
$ wget https://github.com/bitcoin/bitcoin/archive/v0.16.2.tar.gz
$ tar -zxvf v0.16.2.tar.gz
$ tree -L 1 bitcoin-0.16.2/
bitcoin-0.16.2/
├── autogen.sh
├── build-aux
├── configure.ac
├── contrib
├── CONTRIBUTING.md
├── COPYING
├── depends
├── doc
├── INSTALL.md
├── libbitcoinconsensus.pc.in
├── Makefile.am
├── README.md
├── share
├── src
└── test
1.2.2 编译安装
注:需开启debug参数:
--enable-debug
$ cd ~/BlockChain/Bitcoin/bitcoin-0.16.2/
$ ./autogen.sh
$ ./configure --enable-debug --prefix=/home/rzexin/Software/ALL/bitcoin
Options used to compile and link:
with wallet = yes
with gui / qt = yes
qt version = 5
with qr = auto
with zmq = no
with test = yes
with bench = yes
with upnp = auto
use asm = yes
debug enabled = yes
werror = no
target os = linux
build os =
CC = gcc
CFLAGS = -g -O2 -g3 -O0
CPPFLAGS = -DDEBUG -DDEBUG_LOCKORDER -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS
CXX = g++ -std=c++11
CXXFLAGS = -g -O2 -g3 -O0 -Wall -Wextra -Wformat -Wvla -Wformat-security -Wno-unused-parameter -Wno-implicit-fallthrough
LDFLAGS =
ARFLAGS = cr
$ make -j2 && make install
$ tree ~/Software/ALL/bitcoin/
/home/rzexin/Software/ALL/bitcoin/
├── bin
│ ├── bench_bitcoin
│ ├── bitcoin-cli
│ ├── bitcoind
│ ├── bitcoin-qt
│ ├── bitcoin-tx
│ ├── test_bitcoin
│ └── test_bitcoin-qt
├── include
│ └── bitcoinconsensus.h
├── lib
│ ├── libbitcoinconsensus.a
│ ├── libbitcoinconsensus.la
│ ├── libbitcoinconsensus.so -> libbitcoinconsensus.so.0.0.0
│ ├── libbitcoinconsensus.so.0 -> libbitcoinconsensus.so.0.0.0
│ ├── libbitcoinconsensus.so.0.0.0
│ └── pkgconfig
│ └── libbitcoinconsensus.pc
└── share
└── man
└── man1
├── bitcoin-cli.1
├── bitcoind.1
├── bitcoin-qt.1
└── bitcoin-tx.1
- 可执行文件说明
程序名 | 说明 |
---|---|
bitcoind | 比特币运行的核心程序俗称bitcoin core |
bitcoin-cli | Bitcoind的一个功能完备的RPC客户端,包括查询区块,交易信息等等 |
bitcoin-qt | 比特币钱包 |
bitcoin-tx | 比特币交易处理模块,支持交易的查询和创建 |
test_bitcoin | 运行各个模块的测试代码 |
test_bitcoin-qt | 运行钱包的模块测试代码 |
1.2.3 环境配置
(1)配置PATH和LD_IBRARY_PATH
export PATH=/home/rzexin/Software/ALL/bitcoin/bin:$PATH
export LD_LIBRARY_PATH=/home/rzexin/Software/ALL/bitcoin/lib:$LD_LIBRARY_PATH
(2)配置帮助文档
export MANPATH=/home/rzexin/Software/ALL/bitcoin/share/man:$MANPATH
# man帮助手册彩色输出
export LESS_TERMCAP_mb=$'\E[01;31m'
export LESS_TERMCAP_md=$'\E[01;31m'
export LESS_TERMCAP_me=$'\E[0m'
export LESS_TERMCAP_se=$'\E[0m'
export LESS_TERMCAP_so=$'\E[01;44;33m'
export LESS_TERMCAP_ue=$'\E[0m'
export LESS_TERMCAP_us=$'\E[01;32m'
通过上述配置,可以使用man命令查看到帮助文档,且是彩色打印便于查看:
$ man bitcoind
1.2.4 钱包启动
很好奇当前(2018.08.14)比特币账本总的大小,故启动看看:)
已经有
203GB
!好吧,我可怜的256GB本儿,就别指望同步下来了:(
区块#2. 调试实践
2.1 vim单步调试小demo
2.1.1 准备demo
一个计算阶乘小demo
// $ cat main.cpp
#include
extern int factor(int n, int *rt);
int main(int argc, char **argv)
{
int i;
int result = 1;
for (i = 1; i < 6; i++)
{
factor(i, &result);
printf("%d! = %d\n", i, result);
}
return 0;
}
//$ cat factor.cpp
int factor(int n, int *r)
{
if (n <= 1)
{
*r = n;
}
else
{
factor(n - 1, r);
*r *= n;
}
return 0;
}
编译&执行:
$ g++ -g -Wall -o demo main.cpp factor.cpp
$ ./demo
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
2.1.2 vimrc配置
""""""""""""""""""""""""""""""""""
" => vimgdb
""""""""""""""""""""""""""""""""""
let g:vimgdb_debug_file = ""
run macros/gdb_mappings.vim
map :run macros/gdb_mappings.vim
nmap g :bel 40vsplit gdb-variables
2.1.3 单步调试实践
(1)使用前面自己编译的vim打开源码
$ vimg main.cpp
(2)按F2
键,相当于执行::run macros/gdb_mappings.vim
,加载vimgdb补丁的绑定
(3)按F7
键,进行gdb keys mapped
,开启gdb调试功能
(4)点击空格
,下方出现调试交互窗口
(5)在交互窗口中,输入file demo
,绑定我们前面生成的可执行文件
执行后,将会看到如下提示信息:
(gdb) file demo
Reading symbols from demo...done.
(6)使用CTRL+B
设置断点
(7)执行R
启动程序,或在控制窗口中执行run
命令
可见demo停在断点出
(8)使用CTRL+n
单步执行,使用C
进行continue
(9)使用,g
打开变量窗口
(10)通过CTRL+v
选中变量,通过CTRL+p
添加变量到变量窗口中,便于观察执行过程中值的变化
(11)在12行通过执行S
单步进入factor函数,同样的方法,将*r
也添加进变量窗口
(12)单机空格
进入命令窗口,执行quit
,结束gdb调试
2.1.4 更多指令
执行
:help gdb-mappings
可查看
按键 | 用途 |
---|---|
launch the interactive gdb input-line window | |
CTRL-Z | send an interrupt to GDB and the program it is running |
B | info breakpoints |
L | info locals |
A | info args |
S | step |
I | stepi |
CTRL-N | next: next source line, skipping all function calls |
X | nexti |
F | finish |
R | run |
Q | quit |
C | continue |
W | where |
CTRL-U | up: go up one frame |
CTRL-D | down: go down one frame |
CTRL-B | set a breakpoint on the line where the cursor is located |
CTRL-E | clear all breakpoints on the line where the cursor is located |
CTRL-P | Normal mode: print value of word under cursor |
CTRL-X | print value of data referenced by word under cursor |
2.2 vim单步调试bitcoind
接下来就是激动人心的比特币核心源码的单步调试了
2.2.1 进入安装目录
我们可看到源码和可执行程序都在一个目录
$ cd /home/rzexin/BlockChain/Bitcoin/bitcoin-0.16.2/src
$ ls bitcoind bitcoind.cpp
bitcoind bitcoind.cpp
2.2.2 单步调试实践
(1)打开源码文件
$ vimg bitcoind.cpp
(2)执行F2
、F7
开启GDB调试功能
(3)执行CTRL+B
设置断点
(4)这次由于要指定一些参数,就不再通过执行R
启动程序,而是执行空格
进入调试终端后,执行如下命令启动
regtest:是一个本地测试环境,可以根据需要实时创建区块
datadir:不指定的话,默认创建在~/.bitcoin
start -server -keypool=1 -rest -discover=0 -regtest -datadir=/home/rzexin/BlockChain/Bitcoin/data
(5)使用CTRL+n
单步执行,使用CTRL+s
单步进入函数
(6)进一步探索
区块#3. 结语
好了,单步调试环境已经准备好了,那么接下来就开始愉快的bitcoin探索之旅吧。。。
区块链研习社源码研读班第五期-rzexin