Adding support for reading function pointers and mapping them to function names

This commit is contained in:
epipho 2015-01-19 23:15:40 -05:00
parent 056df44318
commit 99b614a028
3 changed files with 41 additions and 4 deletions

@ -41,10 +41,11 @@ func foobar(baz string, bar FooBar) {
up = uintptr(5) up = uintptr(5)
f32 = float32(1.2) f32 = float32(1.2)
i32 = [2]int32{1, 2} i32 = [2]int32{1, 2}
f = barfoo
) )
barfoo() barfoo()
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, b1, b2, baz, neg, i8, u8, u16, u32, u64, up, f32, i32, bar) fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, b1, b2, baz, neg, i8, u8, u16, u32, u64, up, f32, i32, bar, f)
} }
func main() { func main() {

@ -622,6 +622,10 @@ func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ i
return thread.readFloat(ptraddress, t.ByteSize) return thread.readFloat(ptraddress, t.ByteSize)
case *dwarf.BoolType: case *dwarf.BoolType:
return thread.readBool(ptraddress) return thread.readBool(ptraddress)
case *dwarf.FuncType:
return thread.readFunctionPtr(ptraddress)
default:
fmt.Printf("Unknown type: %T\n", t)
} }
return "", fmt.Errorf("could not find value for type %s", typ) return "", fmt.Errorf("could not find value for type %s", typ)
@ -774,6 +778,36 @@ func (thread *ThreadContext) readBool(addr uintptr) (string, error) {
return "true", nil return "true", nil
} }
func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) {
val, err := thread.readMemory(addr, ptrsize)
if err != nil {
return "", err
}
// dereference pointer to find function pc
addr = uintptr(binary.LittleEndian.Uint64(val))
val, err = thread.readMemory(addr, ptrsize)
if err != nil {
return "", err
}
funcAddr := binary.LittleEndian.Uint64(val)
reader := thread.Process.DwarfReader()
entry, err := reader.SeekToFunction(funcAddr)
if err != nil {
return "", err
}
n, ok := entry.Val(dwarf.AttrName).(string)
if !ok {
return "", fmt.Errorf("Unable to retrieve function name")
}
return n, nil
}
func (thread *ThreadContext) readMemory(addr uintptr, size uintptr) ([]byte, error) { func (thread *ThreadContext) readMemory(addr uintptr, size uintptr) ([]byte, error) {
buf := make([]byte, size) buf := make([]byte, size)

@ -64,11 +64,12 @@ func TestVariableEvaluation(t *testing.T) {
{"u64", "18446744073709551615", "uint64", nil}, {"u64", "18446744073709551615", "uint64", nil},
{"u8", "255", "uint8", nil}, {"u8", "255", "uint8", nil},
{"up", "5", "uintptr", nil}, {"up", "5", "uintptr", nil},
{"f", "main.barfoo", "func()", nil},
{"NonExistent", "", "", errors.New("could not find symbol value for NonExistent")}, {"NonExistent", "", "", errors.New("could not find symbol value for NonExistent")},
} }
withTestProcess(executablePath, t, func(p *DebuggedProcess) { withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 46) pc, _, _ := p.GoSymTable.LineToPC(fp, 47)
_, err := p.Break(pc) _, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error") assertNoError(err, t, "Break() returned an error")
@ -99,7 +100,7 @@ func TestVariableFunctionScoping(t *testing.T) {
} }
withTestProcess(executablePath, t, func(p *DebuggedProcess) { withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 46) pc, _, _ := p.GoSymTable.LineToPC(fp, 47)
_, err := p.Break(pc) _, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error") assertNoError(err, t, "Break() returned an error")
@ -175,6 +176,7 @@ func TestLocalVariables(t *testing.T) {
{"a9", "*main.FooBar nil", "*main.FooBar", nil}, {"a9", "*main.FooBar nil", "*main.FooBar", nil},
{"b1", "true", "bool", nil}, {"b1", "true", "bool", nil},
{"b2", "false", "bool", nil}, {"b2", "false", "bool", nil},
{"f", "main.barfoo", "func()", nil},
{"f32", "1.2", "float32", nil}, {"f32", "1.2", "float32", nil},
{"i32", "[2]int32 [1 2]", "[2]int32", nil}, {"i32", "[2]int32 [1 2]", "[2]int32", nil},
{"i8", "1", "int8", nil}, {"i8", "1", "int8", nil},
@ -191,7 +193,7 @@ func TestLocalVariables(t *testing.T) {
} }
withTestProcess(executablePath, t, func(p *DebuggedProcess) { withTestProcess(executablePath, t, func(p *DebuggedProcess) {
pc, _, _ := p.GoSymTable.LineToPC(fp, 46) pc, _, _ := p.GoSymTable.LineToPC(fp, 47)
_, err := p.Break(pc) _, err := p.Break(pc)
assertNoError(err, t, "Break() returned an error") assertNoError(err, t, "Break() returned an error")