proc: do not check return args when loading return vals of call injection
When the function we are calling is an autogenerated stub (because, for example, we are calling it through a function pointer) the declaration line of variables is meaningless and could cause us to discard valid return arguments.
This commit is contained in:
parent
de322cd113
commit
4a004e4bc1
@ -23,6 +23,7 @@ const (
|
||||
VariablesOnlyVisible VariablesFlags = 1 << iota
|
||||
VariablesSkipInlinedSubroutines
|
||||
VariablesTrustDeclLine
|
||||
VariablesNoDeclLineCheck
|
||||
)
|
||||
|
||||
// Variables returns a list of variables contained inside 'root'.
|
||||
@ -60,7 +61,7 @@ func variablesInternal(v []Variable, root *godwarf.Tree, depth int, pc uint64, l
|
||||
// are defined.
|
||||
o = 1
|
||||
}
|
||||
if declLine, ok := root.Val(dwarf.AttrDeclLine).(int64); !ok || line >= int(declLine)+o {
|
||||
if declLine, ok := root.Val(dwarf.AttrDeclLine).(int64); (flags&VariablesNoDeclLineCheck != 0) || !ok || line >= int(declLine)+o {
|
||||
return append(v, Variable{root, depth})
|
||||
}
|
||||
return v
|
||||
|
||||
@ -899,7 +899,7 @@ func (rbpi *returnBreakpointInfo) Collect(t *Target, thread Thread) []*Variable
|
||||
return returnInfoError("could not read function entry", err, thread.ProcessMemory())
|
||||
}
|
||||
|
||||
vars, err := scope.Locals()
|
||||
vars, err := scope.Locals(0)
|
||||
if err != nil {
|
||||
return returnInfoError("could not evaluate return variables", err, thread.ProcessMemory())
|
||||
}
|
||||
|
||||
@ -49,13 +49,21 @@ type EvalScope struct {
|
||||
// The goroutine executing the expression evaluation shall signal that the
|
||||
// evaluation is complete by closing the continueRequest channel.
|
||||
callCtx *callContext
|
||||
|
||||
// If trustArgOrder is true function arguments that don't have an address
|
||||
// will have one assigned by looking at their position in the argument
|
||||
// list.
|
||||
trustArgOrder bool
|
||||
}
|
||||
|
||||
type localsFlags uint8
|
||||
|
||||
const (
|
||||
// If localsTrustArgOrder is set function arguments that don't have an
|
||||
// address will have one assigned by looking at their position in the argument
|
||||
// list.
|
||||
localsTrustArgOrder localsFlags = 1 << iota
|
||||
|
||||
// If localsNoDeclLineCheck the declaration line isn't checked at
|
||||
// all to determine if the variable is in scope.
|
||||
localsNoDeclLineCheck
|
||||
)
|
||||
|
||||
// ConvertEvalScope returns a new EvalScope in the context of the
|
||||
// specified goroutine ID and stack frame.
|
||||
// If deferCall is > 0 the eval scope will be relative to the specified deferred call.
|
||||
@ -201,12 +209,12 @@ func isAssignment(err error) (int, bool) {
|
||||
}
|
||||
|
||||
// Locals returns all variables in 'scope'.
|
||||
func (scope *EvalScope) Locals() ([]*Variable, error) {
|
||||
func (scope *EvalScope) Locals(flags localsFlags) ([]*Variable, error) {
|
||||
if scope.Fn == nil {
|
||||
return nil, errors.New("unable to find function context")
|
||||
}
|
||||
|
||||
trustArgOrder := scope.trustArgOrder && scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 12) && scope.Fn != nil && (scope.PC == scope.Fn.Entry)
|
||||
trustArgOrder := (flags&localsTrustArgOrder != 0) && scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 12) && scope.Fn != nil && (scope.PC == scope.Fn.Entry)
|
||||
|
||||
dwarfTree, err := scope.image().getDwarfTree(scope.Fn.offset)
|
||||
if err != nil {
|
||||
@ -214,6 +222,9 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
|
||||
}
|
||||
|
||||
variablesFlags := reader.VariablesOnlyVisible
|
||||
if flags&localsNoDeclLineCheck != 0 {
|
||||
variablesFlags = reader.VariablesNoDeclLineCheck
|
||||
}
|
||||
if scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 15) {
|
||||
variablesFlags |= reader.VariablesTrustDeclLine
|
||||
}
|
||||
@ -417,7 +428,7 @@ func (scope *EvalScope) SetVariable(name, value string) error {
|
||||
|
||||
// LocalVariables returns all local variables from the current function scope.
|
||||
func (scope *EvalScope) LocalVariables(cfg LoadConfig) ([]*Variable, error) {
|
||||
vars, err := scope.Locals()
|
||||
vars, err := scope.Locals(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -431,7 +442,7 @@ func (scope *EvalScope) LocalVariables(cfg LoadConfig) ([]*Variable, error) {
|
||||
|
||||
// FunctionArguments returns the name, value, and type of all current function arguments.
|
||||
func (scope *EvalScope) FunctionArguments(cfg LoadConfig) ([]*Variable, error) {
|
||||
vars, err := scope.Locals()
|
||||
vars, err := scope.Locals(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1134,7 +1145,7 @@ func (scope *EvalScope) evalIdent(node *ast.Ident) (*Variable, error) {
|
||||
return nilVariable, nil
|
||||
}
|
||||
|
||||
vars, err := scope.Locals()
|
||||
vars, err := scope.Locals(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -883,9 +883,13 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
||||
|
||||
// pretend we are still inside the function we called
|
||||
fakeFunctionEntryScope(retScope, fncall.fn, int64(regs.SP()), regs.SP()-uint64(bi.Arch.PtrSize()))
|
||||
retScope.trustArgOrder = !bi.regabi
|
||||
var flags localsFlags
|
||||
flags |= localsNoDeclLineCheck // if the function we are calling is an autogenerated stub then declaration lines have no meaning
|
||||
if !bi.regabi {
|
||||
flags |= localsTrustArgOrder
|
||||
}
|
||||
|
||||
fncall.retvars, err = retScope.Locals()
|
||||
fncall.retvars, err = retScope.Locals(flags)
|
||||
if err != nil {
|
||||
fncall.err = fmt.Errorf("could not get return values: %v", err)
|
||||
break
|
||||
|
||||
@ -3544,7 +3544,7 @@ func testDeclLineCount(t *testing.T, p *proc.Target, lineno int, tgtvars []strin
|
||||
assertLineNumber(p, t, lineno, "Program did not continue to correct next location")
|
||||
scope, err := proc.GoroutineScope(p, p.CurrentThread())
|
||||
assertNoError(err, t, fmt.Sprintf("GoroutineScope (:%d)", lineno))
|
||||
vars, err := scope.Locals()
|
||||
vars, err := scope.Locals(0)
|
||||
assertNoError(err, t, fmt.Sprintf("Locals (:%d)", lineno))
|
||||
if len(vars) != len(tgtvars) {
|
||||
t.Fatalf("wrong number of variables %d (:%d)", len(vars), lineno)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user