gdb debug peer 程序
在开始我们从 github 上download 下来的源码包,实际上已经包含了可执行的 peer 程序,但是该程序是使用 release 方式编译的,并不支持gdb 直接debug,所以我们需要对源码从新编译peer。
在开始编译前,读者应该了解,由于“神秘的东方力量”,程序试图从golang 库中download 安装包时,需要“科学上网”。
假设 fabric 的源码被download 在 /opt/gopath/src/github.com/hyperledger/fabric,切换到该目录后,对 Makefile 进行修改,加入debug 编译(大约360行),红色部分为修改的内容。
传递参数-ldflags "-s",忽略debug的打印信息;传递-gcflags "-N -l" 参数,这样可以忽略Go内部做的一些优化,聚合变量和函数等优化,这样对于GDB调试来说非常困难,所以在编译的时候加入这两个参数避免这些优化。
release/%/bin/peer: $(PROJECT_FILES) @echo "Building $@ for $(GOOS)-$(GOARCH)" mkdir -p $(@D) $(CGO_FLAGS) GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags "-s" -gcflags "-N -l" -o $(abspath $@) -tags "$(GO_TAGS)" -ldflags "$(GO_LDFLAGS)" $(pkgmap.$(@F))
编译 peer 执行,编译成功后,peer 将在 build/bin/peer
make peer
作者在第一次编译时,还会遇到 protoc-gen-go 命令找不到的问题,错误信息如下
mkdir -p build/image/ccenv/payload cp build/docker/gotools/bin/protoc-gen-go build/bin/chaintool build/goshim.tar.bz2 build/image/ccenv/payload cp: cannot stat 'build/docker/gotools/bin/protoc-gen-go': No such file or directory Makefile:263: recipe for target 'build/image/ccenv/payload' failed make: *** [build/image/ccenv/payload] Error 1
解决方式是自己安装后拷贝到 build/docker/gotools/bin/ 目录,然后再次执行编译 peer 的命令
cd $GOPATH/src/github.com/golang/ git clone https://git.oschina.net/mellymeng/protobuf.git go get -u github.com/golang/protobuf/protoc-gen-go cd $GOPATH cp bin/protoc-gen-go /opt/gopath/src/github.com/hyperledger/fabric/build/docker/gotools/bin/
编译peer ok 后,按照 hyperledger fabric 1.0.5 分布式部署 (七)介绍的设置环境变量
export CORE_PEER_TLS_ROOTCERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" ; export CORE_PEER_LOCALMSPID="Org1MSP" ; export CORE_PEER_TLS_ENABLED=true ; export CORE_PEER_TLS_KEY_FILE="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key" ; export CORE_PEER_MSPCONFIGPATH="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" ; export CORE_PEER_ADDRESS="peer0.org1.example.com:7051" ;
使用gdb 启动 peer 程序
gdb build/bin/peer
给 gdb 加入 go 的调试信息,假设 golang 安装在 /opt/go 目录
source /opt/go/src/runtime/runtime-gdb.py
在gdb 中设置peer 的运行参数
set args chaincode query -C mychannel -n mycc --logging-level CRITICAL -c '{"Args":["cert"]}'
在 gdb 中设置断点,例如
b /opt/gopath/src/github.com/hyperledger/fabric/peer/chaincode/common.go:99
然后在gdb 执行 run 命令
run
此时gdb 将进入 common.go 程序的99 行,该函数是啥内容呢?peer 处理 chaincodeInvokeOrQuery 的函数。
Breakpoint 3 at 0xb2cd20: file /opt/gopath/src/github.com/hyperledger/fabric/peer/chaincode/common.go, line 99. (gdb) run Starting program: /opt/gopath/src/github.com/hyperledger/fabric/build/bin/peer chaincode query -C mychannel -n mycc --logging-level CRITICAL -c '{"Args":["cert"]}' [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New Thread 0x7ffff73e1700 (LWP 14311)] [New Thread 0x7ffff6be0700 (LWP 14312)] [New Thread 0x7ffff63df700 (LWP 14313)] [New Thread 0x7ffff5a7e700 (LWP 14314)] [New Thread 0x7ffff527d700 (LWP 14318)] [Switching to Thread 0x7ffff6be0700 (LWP 14312)] Thread 3 "peer" hit Breakpoint 3, github.com/hyperledger/fabric/peer/chaincode.chaincodeInvokeOrQuery (cmd=0xc420253200, args= []string, invoke=false, cf=0xc4201833b0, err=...) at /opt/gopath/src/github.com/hyperledger/fabric/peer/chaincode/common.go:99 99 func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *ChaincodeCmdFactory) (err error) {
参考博客:
https://stackoverflow.com/questions/41040156/cp-cannot-stat-build-docker-gotools-bin-protoc-gen-go-no-such-file-or-direct
http://blog.csdn.net/iflow/article/details/77951610
http://blog.studygolang.com/2012/12/gdb%E8%B0%83%E8%AF%95go%E7%A8%8B%E5%BA%8F/