Parse go symbol table and print on step
This commit is contained in:
parent
0d134e8733
commit
4df7b998ee
Binary file not shown.
@ -7,10 +7,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println(os.Getpid())
|
pid := os.Getpid()
|
||||||
|
fmt.Println(pid)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
for {
|
for {
|
||||||
fmt.Println("Hello, world!")
|
fmt.Println(pid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -3,6 +3,8 @@
|
|||||||
package proctl
|
package proctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"debug/gosym"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -15,16 +17,19 @@ type DebuggedProcess struct {
|
|||||||
Regs *syscall.PtraceRegs
|
Regs *syscall.PtraceRegs
|
||||||
Process *os.Process
|
Process *os.Process
|
||||||
ProcessState *os.ProcessState
|
ProcessState *os.ProcessState
|
||||||
|
Executable *elf.File
|
||||||
|
Symbols []elf.Symbol
|
||||||
|
GoSymTable *gosym.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new DebuggedProcess struct with sensible defaults.
|
// Returns a new DebuggedProcess struct with sensible defaults.
|
||||||
func NewDebugProcess(pid int) (*DebuggedProcess, error) {
|
func NewDebugProcess(pid int) (*DebuggedProcess, error) {
|
||||||
err := syscall.PtraceAttach(pid)
|
proc, err := os.FindProcess(pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
proc, err := os.FindProcess(pid)
|
err = syscall.PtraceAttach(pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -41,9 +46,28 @@ func NewDebugProcess(pid int) (*DebuggedProcess, error) {
|
|||||||
ProcessState: ps,
|
ProcessState: ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = debuggedProc.LoadInformation()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &debuggedProc, nil
|
return &debuggedProc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dbp *DebuggedProcess) LoadInformation() error {
|
||||||
|
err := dbp.findExecutable()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dbp.obtainGoSymbols()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Obtains register values from the debugged process.
|
// Obtains register values from the debugged process.
|
||||||
func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
|
func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
|
||||||
err := syscall.PtraceGetRegs(dbp.Pid, dbp.Regs)
|
err := syscall.PtraceGetRegs(dbp.Pid, dbp.Regs)
|
||||||
@ -56,7 +80,21 @@ func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
|
|||||||
|
|
||||||
// Steps through process.
|
// Steps through process.
|
||||||
func (dbp *DebuggedProcess) Step() error {
|
func (dbp *DebuggedProcess) Step() error {
|
||||||
return dbp.handleResult(syscall.PtraceSingleStep(dbp.Pid))
|
err := dbp.handleResult(syscall.PtraceSingleStep(dbp.Pid))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("step failed: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
regs, err := dbp.Registers()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f := dbp.GoSymTable.PCToFunc(regs.PC())
|
||||||
|
l := f.LineTable.PCToLine(regs.PC())
|
||||||
|
fmt.Printf("Stopped at: %s:%d\n", f.Name, l)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue process until next breakpoint.
|
// Continue process until next breakpoint.
|
||||||
@ -78,3 +116,43 @@ func (dbp *DebuggedProcess) handleResult(err error) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dbp *DebuggedProcess) findExecutable() error {
|
||||||
|
procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)
|
||||||
|
|
||||||
|
f, err := os.Open(procpath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
elffile, err := elf.NewFile(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dbp.Executable = elffile
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbp *DebuggedProcess) obtainGoSymbols() error {
|
||||||
|
symdat, err := dbp.Executable.Section(".gosymtab").Data()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pclndat, err := dbp.Executable.Section(".gopclntab").Data()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pcln := gosym.NewLineTable(pclndat, dbp.Executable.Section(".text").Addr)
|
||||||
|
tab, err := gosym.NewTable(symdat, pcln)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dbp.GoSymTable = tab
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user