提交 731829c3 编写于 作者: A aarzilli 提交者: Derek Parker

proc: auto-dereference local variables that escape to the heap

The compiler a variable 'v' that escapes to the heap with a '&v' entry.
Auto dereference those local variables.

Fixe #871
上级 04adb46c
......@@ -24,12 +24,14 @@ All changes mention the author, unless contributed by me (@derekparker).
- Parsing of maps with zero sized values (@aarzilli)
- Typo in the documentation of `types` command (@custa)
- Data races in tests (@aarzilli)
- Fixed SetBreakpoint in native and gdbserial to return the breakpoint if it already exists (@dlsniper)
### Changed
- Switched from godeps to glide (@derekparker)
- Better performance of linux native backend (@aarzilli)
- Collect breakpoints information if necessary after a next, step or stepout command (@aarzilli)
- Autodereference escaped variables (@aarzilli)
## [1.0.0-rc.1] 2017-05-05
......
package main
import (
"fmt"
"runtime"
)
func main() {
a := [3]int{1, 2, 3}
b := &a
runtime.Breakpoint()
fmt.Println(b, *b) // set breakpoint here
}
......@@ -2984,3 +2984,49 @@ func TestStepInstructionNoGoroutine(t *testing.T) {
assertNoError(p.StepInstruction(), t, "StepInstruction")
})
}
func TestIssue871(t *testing.T) {
protest.AllowRecording(t)
withTestProcess("issue871", t, func(p proc.Process, fixture protest.Fixture) {
assertNoError(proc.Continue(p), t, "Continue")
var scope *proc.EvalScope
var err error
if testBackend == "rr" {
var frame proc.Stackframe
frame, err = findFirstNonRuntimeFrame(p)
if err == nil {
scope = proc.FrameToScope(p, frame)
}
} else {
scope, err = proc.GoroutineScope(p.CurrentThread())
}
assertNoError(err, t, "scope")
locals, err := scope.LocalVariables(normalLoadConfig)
assertNoError(err, t, "LocalVariables")
foundA, foundB := false, false
for _, v := range locals {
t.Logf("local %v", v)
switch v.Name {
case "a":
foundA = true
if v.Flags&proc.VariableEscaped == 0 {
t.Errorf("variable a not flagged as escaped")
}
case "b":
foundB = true
}
}
if !foundA {
t.Errorf("variable a not found")
}
if !foundB {
t.Errorf("variable b not found")
}
})
}
......@@ -39,6 +39,13 @@ const (
FloatIsNegInf
)
type VariableFlags uint16
const (
// VariableEscaped is set for local variables that escaped to the heap
VariableEscaped VariableFlags = (1 << iota)
)
// Variable represents a variable. It contains the address, name,
// type and other information parsed from both the Dwarf information
// and the memory of the debugged process.
......@@ -59,6 +66,8 @@ type Variable struct {
Len int64
Cap int64
Flags VariableFlags
// Base address of arrays, Base address of the backing array for slices (0 for nil slices)
// Base address of the backing byte array for strings
// address of the struct backing chan and map variables
......@@ -1717,7 +1726,13 @@ func (scope *EvalScope) variablesByTag(tag dwarf.Tag, cfg LoadConfig) ([]*Variab
}
}
for _, v := range vars {
for i, v := range vars {
if name := v.Name; len(name) > 1 && name[0] == '&' {
v = v.maybeDereference()
v.Name = name[1:]
v.Flags |= VariableEscaped
vars[i] = v
}
v.loadValue(cfg)
}
......
......@@ -121,6 +121,7 @@ func ConvertVar(v *proc.Variable) *Variable {
Kind: v.Kind,
Len: v.Len,
Cap: v.Cap,
Flags: VariableFlags(v.Flags),
}
r.Type = prettyTypeName(v.DwarfType)
......
......@@ -147,6 +147,12 @@ type Function struct {
GoType uint64 `json:"goType"`
}
type VariableFlags uint16
const (
VariableEscaped = VariableFlags(proc.VariableEscaped)
)
// Variable describes a variable.
type Variable struct {
// Name of the variable or struct member
......@@ -160,6 +166,8 @@ type Variable struct {
// Type of the variable after resolving any typedefs
RealType string `json:"realType"`
Flags VariableFlags `json:"flags"`
Kind reflect.Kind `json:"kind"`
//Strings have their length capped at proc.maxArrayValues, use Len for the real length of a string
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册