delve/dwarf/frame_table_test.go
Derek Parker 38bfdaf47c Implement initial support for stack unwinding.
Implement basic api for figuring out, given a current PC value, where
the function will return. Currently the API provides only a way to
determine the offset from SP (the Canonical Frame Address). It is left
up to the caller to grab the actual address from the traced program.
2014-06-25 14:14:29 -05:00

106 lines
1.8 KiB
Go

package frame
import (
"debug/elf"
"debug/gosym"
"encoding/binary"
"os"
"path/filepath"
"syscall"
"testing"
"github.com/derekparker/dbg/_helper"
"github.com/derekparker/dbg/proctl"
)
var testfile string
func init() {
testfile, _ = filepath.Abs("../_fixtures/testprog")
}
func parseGoSym(t *testing.T, exe *elf.File) *gosym.Table {
symdat, err := exe.Section(".gosymtab").Data()
if err != nil {
t.Fatal(err)
}
pclndat, err := exe.Section(".gopclntab").Data()
if err != nil {
t.Fatal(err)
}
pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr)
tab, err := gosym.NewTable(symdat, pcln)
if err != nil {
t.Fatal(err)
}
return tab
}
func gosymData(t *testing.T) *gosym.Table {
f, err := os.Open(testfile)
if err != nil {
t.Fatal(err)
}
e, err := elf.NewFile(f)
if err != nil {
t.Fatal(err)
}
return parseGoSym(t, e)
}
func TestFindReturnAddress(t *testing.T) {
var (
dbframe = grabDebugFrameSection(testfile, t)
fdes = Parse(dbframe)
gsd = gosymData(t)
)
helper.WithTestProcess("testprog", t, func(p *proctl.DebuggedProcess) {
testsourcefile := testfile + ".go"
start, _, err := gsd.LineToPC(testsourcefile, 9)
if err != nil {
t.Fatal(err)
}
_, err = p.Break(uintptr(start))
if err != nil {
t.Fatal(err)
}
err = p.Continue()
if err != nil {
t.Fatal(err)
}
regs, err := p.Registers()
if err != nil {
t.Fatal(err)
}
end, _, err := gsd.LineToPC(testsourcefile, 19)
if err != nil {
t.Fatal(err)
}
ret, err := fdes.FindReturnAddressOffset(start)
if err != nil {
t.Fatal(err)
}
addr := regs.Rsp + ret
data := make([]byte, 8)
syscall.PtracePeekText(p.Pid, uintptr(addr), data)
addr = binary.LittleEndian.Uint64(data)
if addr != end {
t.Fatalf("return address not found correctly, expected %#v got %#v", end, ret)
}
})
}