github.com/go-delve/delve的源码学习
delve是golang专用的debug工具,原理类似于gdb,关于gdb的原理可以参考这篇文章。关于delve的源码学习,先写一个基础的demo如下:
package main
import (
"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/native"
)
func main() {
targetGroup, err := native.Launch([]string{"./hello"}, "", 0, nil, "", [3]string{})
fn, _ := targetGroup.Selected.BinInfo().FindFunction("main.main")
_, err = targetGroup.Selected.SetBreakpoint(0, fn[0].Entry, proc.UserBreakpoint, nil)
err = targetGroup.Continue()
println(err)
_ = targetGroup.Detach(true)
}
分析demo的调用栈如下:
targetGroup, err := native.Launch()
|-dbp := newProcess(0)
|-newPtraceThread()
|-go pt.handlePtraceFuncs()
|-dbp.execPtraceFunc(fn)
|-dbp.ptraceThread.ptraceChan <- fn
|-execute fn
|-<-dbp.ptraceThread.ptraceDoneChan
|-tgt, err := dbp.initialize()
|-procgrp.add(dbp, ...)
|-procgrp.addTarget()
|-t := grp.newTarget()
|-grp.Selected = t
targetGroup.Selected.SetBreakpoint() // 设置断点
|-target.proc.WriteBreakpoint()
|-nativeProcess.WriteBreakpoint()
|-nativeProcess.memthread.ReadMemory(bp.OriginalData, bp.Addr)
|-read and save the original data // 读取断点位置1字节的代码
|-dbp.writeSoftwareBreakpoint()
|-write int3(0XCC) command // 修改断点位置1字节的代码为int3
|-setLogicalBreakpoint(newBreakpoint)
|-target.proc.BreakpointMap.Logical[bid] = lbp
|-target.proc.BreakpointMap.[addr] = bp
go pt.handlePtraceFuncs()
|-native.newPtraceThread.func1
|-native.(*ptraceThread).handlePtraceFuncs
|-fn := <-dbp.ptraceThread.ptraceChan
|-native.Launch.func1
|-dbp.ptraceThread.ptraceDoneChan <- nil
本作品采用《CC 协议》,转载必须注明作者和本文链接