Adding support for reading function pointers and mapping them to function names
This commit is contained in:
parent
056df44318
commit
99b614a028
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user