pky/proc: enable function call injection in Delve for linux/ppc64le (#3449)
* enable func call injection on delve for ppc64le * Function call injection on Delve/ppc64le, modified DWARF encoding and decoding for floating point registers to make floatsum test work * Function call injection on Delve/ppc64le cleanup * skip PIE tests for function call injection on other packages * Address review comments * accounted for additional skipped PIE tests for function call injection * Code cleanup and undoing revert of previous commit * Enable function call injection only on 1.22 and above and some cleanup * additional cleanup, go fmt run * Debug function call tests fail on ppc64le/PIE mode adjusted the backup_test_health.md file accordingly
This commit is contained in:
parent
4d30cd461b
commit
ebc3e61367
@ -20,6 +20,8 @@ Tests skipped by each supported backend:
|
|||||||
* 1 broken - cgo stacktraces
|
* 1 broken - cgo stacktraces
|
||||||
* linux/ppc64le/native skipped = 1
|
* linux/ppc64le/native skipped = 1
|
||||||
* 1 broken in linux ppc64le
|
* 1 broken in linux ppc64le
|
||||||
|
* linux/ppc64le/native/pie skipped = 3
|
||||||
|
* 3 broken - pie mode
|
||||||
* pie skipped = 2
|
* pie skipped = 2
|
||||||
* 2 upstream issue - https://github.com/golang/go/issues/29322
|
* 2 upstream issue - https://github.com/golang/go/issues/29322
|
||||||
* ppc64le skipped = 11
|
* ppc64le skipped = 11
|
||||||
|
|||||||
@ -17,13 +17,14 @@ const (
|
|||||||
PPC64LE_F0 = PPC64LE_FIRST_FPR
|
PPC64LE_F0 = PPC64LE_FIRST_FPR
|
||||||
PPC64LE_LAST_FPR = 63
|
PPC64LE_LAST_FPR = 63
|
||||||
// Vector (Altivec/VMX) registers: from V0 to V31
|
// Vector (Altivec/VMX) registers: from V0 to V31
|
||||||
PPC64LE_FIRST_VMX = 64
|
PPC64LE_FIRST_VMX = 77
|
||||||
PPC64LE_V0 = PPC64LE_FIRST_VMX
|
PPC64LE_V0 = PPC64LE_FIRST_VMX
|
||||||
PPC64LE_LAST_VMX = 95
|
PPC64LE_LAST_VMX = 108
|
||||||
// Vector Scalar (VSX) registers: from VS0 to VS63
|
// Vector Scalar (VSX) registers: from VS32 to VS63
|
||||||
PPC64LE_FIRST_VSX = 96
|
// On ppc64le these are mapped to F0 to F31
|
||||||
|
PPC64LE_FIRST_VSX = 32
|
||||||
PPC64LE_VS0 = PPC64LE_FIRST_VSX
|
PPC64LE_VS0 = PPC64LE_FIRST_VSX
|
||||||
PPC64LE_LAST_VSX = 160
|
PPC64LE_LAST_VSX = 63
|
||||||
// Condition Registers: from CR0 to CR7
|
// Condition Registers: from CR0 to CR7
|
||||||
PPC64LE_CR0 = 0
|
PPC64LE_CR0 = 0
|
||||||
// Special registers
|
// Special registers
|
||||||
|
|||||||
@ -336,10 +336,16 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
|||||||
if err := writePointer(bi, scope.Mem, regs.SP()-3*uint64(bi.Arch.PtrSize()), uint64(fncall.argFrameSize)); err != nil {
|
if err := writePointer(bi, scope.Mem, regs.SP()-3*uint64(bi.Arch.PtrSize()), uint64(fncall.argFrameSize)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case "arm64":
|
case "arm64", "ppc64le":
|
||||||
// debugCallV2 on arm64 needs a special call sequence, callOP can not be used
|
// debugCallV2 on arm64 needs a special call sequence, callOP can not be used
|
||||||
sp := regs.SP()
|
sp := regs.SP()
|
||||||
sp -= 2 * uint64(bi.Arch.PtrSize())
|
var spOffset uint64
|
||||||
|
if bi.Arch.Name == "arm64" {
|
||||||
|
spOffset = 2 * uint64(bi.Arch.PtrSize())
|
||||||
|
} else {
|
||||||
|
spOffset = 4 * uint64(bi.Arch.PtrSize())
|
||||||
|
}
|
||||||
|
sp -= spOffset
|
||||||
if err := setSP(thread, sp); err != nil {
|
if err := setSP(thread, sp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -349,7 +355,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
|||||||
if err := setLR(thread, regs.PC()); err != nil {
|
if err := setLR(thread, regs.PC()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := writePointer(bi, scope.Mem, sp-uint64(2*bi.Arch.PtrSize()), uint64(fncall.argFrameSize)); err != nil {
|
if err := writePointer(bi, scope.Mem, sp-spOffset, uint64(fncall.argFrameSize)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
regs, err = thread.Registers()
|
regs, err = thread.Registers()
|
||||||
@ -365,6 +371,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fncallLog("function call initiated %v frame size %d goroutine %d (thread %d)", fncall.fn, fncall.argFrameSize, scope.g.ID, thread.ThreadID())
|
fncallLog("function call initiated %v frame size %d goroutine %d (thread %d)", fncall.fn, fncall.argFrameSize, scope.g.ID, thread.ThreadID())
|
||||||
@ -483,11 +490,12 @@ func callOP(bi *BinaryInfo, thread Thread, regs Registers, callAddr uint64) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setPC(thread, callAddr)
|
return setPC(thread, callAddr)
|
||||||
case "arm64":
|
case "arm64", "ppc64le":
|
||||||
if err := setLR(thread, regs.PC()); err != nil {
|
if err := setLR(thread, regs.PC()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return setPC(thread, callAddr)
|
return setPC(thread, callAddr)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
@ -864,6 +872,8 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
|||||||
archoff := uint64(0)
|
archoff := uint64(0)
|
||||||
if bi.Arch.Name == "arm64" {
|
if bi.Arch.Name == "arm64" {
|
||||||
archoff = 8
|
archoff = 8
|
||||||
|
} else if bi.Arch.Name == "ppc64le" {
|
||||||
|
archoff = 40
|
||||||
}
|
}
|
||||||
// get error from top of the stack and return it to user
|
// get error from top of the stack and return it to user
|
||||||
errvar, err := readStackVariable(p, thread, regs, archoff, "string", loadFullValue)
|
errvar, err := readStackVariable(p, thread, regs, archoff, "string", loadFullValue)
|
||||||
@ -912,7 +922,7 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
|||||||
cfa := regs.SP()
|
cfa := regs.SP()
|
||||||
oldpc := regs.PC()
|
oldpc := regs.PC()
|
||||||
var oldlr uint64
|
var oldlr uint64
|
||||||
if bi.Arch.Name == "arm64" {
|
if bi.Arch.Name == "arm64" || bi.Arch.Name == "ppc64le" {
|
||||||
oldlr = regs.LR()
|
oldlr = regs.LR()
|
||||||
}
|
}
|
||||||
callOP(bi, thread, regs, fncall.fn.Entry)
|
callOP(bi, thread, regs, fncall.fn.Entry)
|
||||||
@ -925,7 +935,7 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
|||||||
case "amd64":
|
case "amd64":
|
||||||
setSP(thread, cfa)
|
setSP(thread, cfa)
|
||||||
setPC(thread, oldpc)
|
setPC(thread, oldpc)
|
||||||
case "arm64":
|
case "arm64", "ppc64le":
|
||||||
setLR(thread, oldlr)
|
setLR(thread, oldlr)
|
||||||
setPC(thread, oldpc)
|
setPC(thread, oldpc)
|
||||||
default:
|
default:
|
||||||
@ -1006,7 +1016,7 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
|||||||
if threadg, _ := GetG(thread); threadg != nil {
|
if threadg, _ := GetG(thread); threadg != nil {
|
||||||
callScope.callCtx.stacks = append(callScope.callCtx.stacks, threadg.stack)
|
callScope.callCtx.stacks = append(callScope.callCtx.stacks, threadg.stack)
|
||||||
}
|
}
|
||||||
if bi.Arch.Name == "arm64" {
|
if bi.Arch.Name == "arm64" || bi.Arch.Name == "ppc64le" {
|
||||||
oldlr, err := readUintRaw(thread.ProcessMemory(), regs.SP(), int64(bi.Arch.PtrSize()))
|
oldlr, err := readUintRaw(thread.ProcessMemory(), regs.SP(), int64(bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fncall.err = fmt.Errorf("could not restore LR: %v", err)
|
fncall.err = fmt.Errorf("could not restore LR: %v", err)
|
||||||
@ -1023,6 +1033,8 @@ func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread
|
|||||||
archoff := uint64(0)
|
archoff := uint64(0)
|
||||||
if bi.Arch.Name == "arm64" {
|
if bi.Arch.Name == "arm64" {
|
||||||
archoff = 8
|
archoff = 8
|
||||||
|
} else if bi.Arch.Name == "ppc64le" {
|
||||||
|
archoff = 32
|
||||||
}
|
}
|
||||||
fncall.panicvar, err = readStackVariable(p, thread, regs, archoff, "interface {}", callScope.callCtx.retLoadCfg)
|
fncall.panicvar, err = readStackVariable(p, thread, regs, archoff, "interface {}", callScope.callCtx.retLoadCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1068,7 +1080,6 @@ func fakeFunctionEntryScope(scope *EvalScope, fn *Function, cfa int64, sp uint64
|
|||||||
scope.PC = fn.Entry
|
scope.PC = fn.Entry
|
||||||
scope.Fn = fn
|
scope.Fn = fn
|
||||||
scope.File, scope.Line = scope.BinInfo.EntryLineForFunc(fn)
|
scope.File, scope.Line = scope.BinInfo.EntryLineForFunc(fn)
|
||||||
|
|
||||||
scope.Regs.CFA = cfa
|
scope.Regs.CFA = cfa
|
||||||
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = sp
|
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = sp
|
||||||
scope.Regs.Reg(scope.Regs.PCRegNum).Uint64Val = fn.Entry
|
scope.Regs.Reg(scope.Regs.PCRegNum).Uint64Val = fn.Entry
|
||||||
@ -1260,7 +1271,7 @@ func debugCallProtocolReg(archName string, version int) (uint64, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return protocolReg, true
|
return protocolReg, true
|
||||||
case "arm64":
|
case "arm64", "ppc64le":
|
||||||
if version == 2 {
|
if version == 2 {
|
||||||
return regnum.ARM64_X0 + 20, true
|
return regnum.ARM64_X0 + 20, true
|
||||||
}
|
}
|
||||||
@ -1335,6 +1346,15 @@ func regabiMallocgcWorkaround(bi *BinaryInfo) ([]*godwarf.Tree, error) {
|
|||||||
m("~r1", t("unsafe.Pointer"), regnum.ARM64_X0, true),
|
m("~r1", t("unsafe.Pointer"), regnum.ARM64_X0, true),
|
||||||
}
|
}
|
||||||
return r, err1
|
return r, err1
|
||||||
|
case "ppc64le":
|
||||||
|
r := []*godwarf.Tree{
|
||||||
|
m("size", t("uintptr"), regnum.PPC64LE_R0+3, false),
|
||||||
|
m("typ", t(ptrToRuntimeType), regnum.PPC64LE_R0+4, false),
|
||||||
|
m("needzero", t("bool"), regnum.PPC64LE_R0+5, false),
|
||||||
|
m("~r1", t("unsafe.Pointer"), regnum.PPC64LE_R0+3, true),
|
||||||
|
}
|
||||||
|
return r, err1
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package linutil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/regnum"
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,13 +164,51 @@ func (r *PPC64LERegisters) Copy() (proc.Registers, error) {
|
|||||||
return &rr, nil
|
return &rr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *PPC64LERegisters) SetReg(regNum uint64, reg *op.DwarfRegister) (fpchanged bool, err error) {
|
||||||
|
switch regNum {
|
||||||
|
case regnum.PPC64LE_PC:
|
||||||
|
r.Regs.Nip = reg.Uint64Val
|
||||||
|
return false, nil
|
||||||
|
case regnum.PPC64LE_LR:
|
||||||
|
r.Regs.Link = reg.Uint64Val
|
||||||
|
return false, nil
|
||||||
|
case regnum.PPC64LE_SP:
|
||||||
|
r.Regs.Gpr[1] = reg.Uint64Val
|
||||||
|
return false, nil
|
||||||
|
default:
|
||||||
|
switch {
|
||||||
|
case regNum >= regnum.PPC64LE_R0 && regNum <= regnum.PPC64LE_R0+31:
|
||||||
|
r.Regs.Gpr[regNum-regnum.PPC64LE_R0] = reg.Uint64Val
|
||||||
|
return false, nil
|
||||||
|
|
||||||
|
case regNum >= regnum.PPC64LE_F0 && regNum <= regnum.PPC64LE_F0+31:
|
||||||
|
if r.loadFpRegs != nil {
|
||||||
|
err := r.loadFpRegs(r)
|
||||||
|
r.loadFpRegs = nil
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On ppc64le, PPC64LE_VS0 .. PPC64LE_VS31 are mapped onto
|
||||||
|
// PPC64LE_F0 .. PPC64LE_F31
|
||||||
|
i := regNum - regnum.PPC64LE_VS0
|
||||||
|
reg.FillBytes()
|
||||||
|
copy(r.Fpregset[8*i:], reg.Bytes)
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("changing register %d not implemented", regNum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type PPC64LEPtraceFpRegs struct {
|
type PPC64LEPtraceFpRegs struct {
|
||||||
Fp []byte
|
Fp []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fpregs *PPC64LEPtraceFpRegs) Decode() (regs []proc.Register) {
|
func (fpregs *PPC64LEPtraceFpRegs) Decode() (regs []proc.Register) {
|
||||||
for i := 0; i < len(fpregs.Fp); i += 16 {
|
for i := 0; i < len(fpregs.Fp); i += 8 {
|
||||||
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("V%d", i/16), fpregs.Fp[i:i+16])
|
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("VS%d", i/8), fpregs.Fp[i:i+8])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/regnum"
|
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
"github.com/go-delve/delve/pkg/proc/linutil"
|
"github.com/go-delve/delve/pkg/proc/linutil"
|
||||||
sys "golang.org/x/sys/unix"
|
sys "golang.org/x/sys/unix"
|
||||||
@ -63,25 +62,30 @@ func (t *nativeThread) setPC(pc uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetReg changes the value of the specified register.
|
// SetReg changes the value of the specified register.
|
||||||
func (t *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
|
func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
|
||||||
ir, err := registers(t)
|
ir, err := registers(thread)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r := ir.(*linutil.PPC64LERegisters)
|
r := ir.(*linutil.PPC64LERegisters)
|
||||||
|
|
||||||
switch regNum {
|
fpchanged, err := r.SetReg(regNum, reg)
|
||||||
case regnum.PPC64LE_PC:
|
if err != nil {
|
||||||
r.Regs.Nip = reg.Uint64Val
|
return err
|
||||||
case regnum.PPC64LE_SP:
|
}
|
||||||
r.Regs.Gpr[1] = reg.Uint64Val
|
thread.dbp.execPtraceFunc(func() {
|
||||||
case regnum.PPC64LE_LR:
|
err = ptraceSetGRegs(thread.ID, r.Regs)
|
||||||
r.Regs.Link = reg.Uint64Val
|
if err != syscall.Errno(0) && err != nil {
|
||||||
default:
|
return
|
||||||
panic("SetReg")
|
}
|
||||||
|
if fpchanged && r.Fpregset != nil {
|
||||||
|
iov := sys.Iovec{Base: &r.Fpregset[0], Len: uint64(len(r.Fpregset))}
|
||||||
|
_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(thread.ID), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err == syscall.Errno(0) {
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t.dbp.execPtraceFunc(func() { err = ptraceSetGRegs(t.ID, r.Regs) })
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,12 @@ package native
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"debug/elf"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
sys "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
"github.com/go-delve/delve/pkg/proc/linutil"
|
"github.com/go-delve/delve/pkg/proc/linutil"
|
||||||
@ -21,5 +27,22 @@ func (t *nativeThread) fpRegisters() ([]proc.Register, []byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
||||||
panic("Unimplemented restoreRegisters method in threads_linux_ppc64le.go")
|
sr := savedRegs.(*linutil.PPC64LERegisters)
|
||||||
|
|
||||||
|
var restoreRegistersErr error
|
||||||
|
t.dbp.execPtraceFunc(func() {
|
||||||
|
restoreRegistersErr = ptraceSetGRegs(t.ID, sr.Regs)
|
||||||
|
if restoreRegistersErr != syscall.Errno(0) && restoreRegistersErr != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if sr.Fpregset != nil {
|
||||||
|
iov := sys.Iovec{Base: &sr.Fpregset[0], Len: _PPC64LE_FPREGS_SIZE}
|
||||||
|
_, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if restoreRegistersErr == syscall.Errno(0) {
|
||||||
|
restoreRegistersErr = nil
|
||||||
|
}
|
||||||
|
return restoreRegistersErr
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,9 +35,12 @@ func PPC64LEArch(goos string) *Arch {
|
|||||||
usesLR: true,
|
usesLR: true,
|
||||||
PCRegNum: regnum.PPC64LE_PC,
|
PCRegNum: regnum.PPC64LE_PC,
|
||||||
SPRegNum: regnum.PPC64LE_SP,
|
SPRegNum: regnum.PPC64LE_SP,
|
||||||
|
ContextRegNum: regnum.PPC64LE_R0 + 11,
|
||||||
LRRegNum: regnum.PPC64LE_LR,
|
LRRegNum: regnum.PPC64LE_LR,
|
||||||
asmRegisters: ppc64leAsmRegisters,
|
asmRegisters: ppc64leAsmRegisters,
|
||||||
RegisterNameToDwarf: nameToDwarfFunc(regnum.PPC64LENameToDwarf),
|
RegisterNameToDwarf: nameToDwarfFunc(regnum.PPC64LENameToDwarf),
|
||||||
|
debugCallMinStackSize: 320,
|
||||||
|
maxRegArgBytes: 13*8 + 13*8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4312,6 +4312,8 @@ func TestReadDeferArgs(t *testing.T) {
|
|||||||
|
|
||||||
func TestIssue1374(t *testing.T) {
|
func TestIssue1374(t *testing.T) {
|
||||||
// Continue did not work when stopped at a breakpoint immediately after calling CallFunction.
|
// Continue did not work when stopped at a breakpoint immediately after calling CallFunction.
|
||||||
|
skipOn(t, "broken - pie mode", "linux", "ppc64le", "native", "pie")
|
||||||
|
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestProcess("issue1374", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
withTestProcess("issue1374", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
||||||
setFileBreakpoint(p, t, fixture.Source, 7)
|
setFileBreakpoint(p, t, fixture.Source, 7)
|
||||||
@ -4537,6 +4539,8 @@ func testCallConcurrentCheckReturns(p *proc.Target, t *testing.T, gid1, gid2 int
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCallConcurrent(t *testing.T) {
|
func TestCallConcurrent(t *testing.T) {
|
||||||
|
skipOn(t, "broken - pie mode", "linux", "ppc64le", "native", "pie")
|
||||||
|
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestProcess("teststepconcurrent", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
withTestProcess("teststepconcurrent", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
||||||
bp := setFileBreakpoint(p, t, fixture.Source, 24)
|
bp := setFileBreakpoint(p, t, fixture.Source, 24)
|
||||||
@ -4932,6 +4936,7 @@ func TestIssue1925(t *testing.T) {
|
|||||||
// In particular the stepInstructionOut function called at the end of a
|
// In particular the stepInstructionOut function called at the end of a
|
||||||
// 'call' procedure should clean the G cache like every other function
|
// 'call' procedure should clean the G cache like every other function
|
||||||
// altering the state of the target process.
|
// altering the state of the target process.
|
||||||
|
skipOn(t, "broken - pie mode", "linux", "ppc64le", "native", "pie")
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestProcess("testvariables2", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
withTestProcess("testvariables2", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
||||||
assertNoError(grp.Continue(), t, "Continue()")
|
assertNoError(grp.Continue(), t, "Continue()")
|
||||||
|
|||||||
@ -252,7 +252,7 @@ func (t *Target) Valid() (bool, error) {
|
|||||||
// Currently only non-recorded processes running on AMD64 support
|
// Currently only non-recorded processes running on AMD64 support
|
||||||
// function calls.
|
// function calls.
|
||||||
func (t *Target) SupportsFunctionCalls() bool {
|
func (t *Target) SupportsFunctionCalls() bool {
|
||||||
return t.Process.BinInfo().Arch.Name == "amd64" || (t.Process.BinInfo().Arch.Name == "arm64" && t.Process.BinInfo().GOOS != "windows")
|
return t.Process.BinInfo().Arch.Name == "amd64" || (t.Process.BinInfo().Arch.Name == "arm64" && t.Process.BinInfo().GOOS != "windows") || t.Process.BinInfo().Arch.Name == "ppc64le"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearCaches clears internal caches that should not survive a restart.
|
// ClearCaches clears internal caches that should not survive a restart.
|
||||||
|
|||||||
@ -310,7 +310,7 @@ func MustSupportFunctionCalls(t *testing.T, testBackend string) {
|
|||||||
if runtime.GOOS == "darwin" && os.Getenv("TRAVIS") == "true" && runtime.GOARCH == "amd64" {
|
if runtime.GOOS == "darwin" && os.Getenv("TRAVIS") == "true" && runtime.GOARCH == "amd64" {
|
||||||
t.Skip("function call injection tests are failing on macOS on Travis-CI (see #1802)")
|
t.Skip("function call injection tests are failing on macOS on Travis-CI (see #1802)")
|
||||||
}
|
}
|
||||||
if runtime.GOARCH == "386" || runtime.GOARCH == "ppc64le" {
|
if runtime.GOARCH == "386" {
|
||||||
t.Skip(fmt.Errorf("%s does not support FunctionCall for now", runtime.GOARCH))
|
t.Skip(fmt.Errorf("%s does not support FunctionCall for now", runtime.GOARCH))
|
||||||
}
|
}
|
||||||
if runtime.GOARCH == "arm64" {
|
if runtime.GOARCH == "arm64" {
|
||||||
@ -318,6 +318,12 @@ func MustSupportFunctionCalls(t *testing.T, testBackend string) {
|
|||||||
t.Skip("this version of Go does not support function calls")
|
t.Skip("this version of Go does not support function calls")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOARCH == "ppc64le" {
|
||||||
|
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 22) {
|
||||||
|
t.Skip("On PPC64LE Building with Go lesser than 1.22 does not support function calls")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultTestBackend changes the value of testBackend to be the default
|
// DefaultTestBackend changes the value of testBackend to be the default
|
||||||
|
|||||||
@ -1158,6 +1158,8 @@ type testCaseCallFunction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCallFunction(t *testing.T) {
|
func TestCallFunction(t *testing.T) {
|
||||||
|
skipOn(t, "broken - pie mode", "linux", "ppc64le", "native", "pie")
|
||||||
|
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
protest.AllowRecording(t)
|
protest.AllowRecording(t)
|
||||||
|
|
||||||
@ -1289,6 +1291,7 @@ func TestCallFunction(t *testing.T) {
|
|||||||
testCallFunctionSetBreakpoint(t, p, grp, fixture)
|
testCallFunctionSetBreakpoint(t, p, grp, fixture)
|
||||||
|
|
||||||
assertNoError(grp.Continue(), t, "Continue()")
|
assertNoError(grp.Continue(), t, "Continue()")
|
||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
testCallFunction(t, grp, p, tc)
|
testCallFunction(t, grp, p, tc)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -996,6 +996,9 @@ func findStarFile(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue1598(t *testing.T) {
|
func TestIssue1598(t *testing.T) {
|
||||||
|
if buildMode == "pie" && runtime.GOARCH == "ppc64le" {
|
||||||
|
t.Skip("Debug function call Test broken in PIE mode")
|
||||||
|
}
|
||||||
test.MustSupportFunctionCalls(t, testBackend)
|
test.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestTerminal("issue1598", t, func(term *FakeTerminal) {
|
withTestTerminal("issue1598", t, func(term *FakeTerminal) {
|
||||||
term.MustExec("break issue1598.go:5")
|
term.MustExec("break issue1598.go:5")
|
||||||
|
|||||||
@ -2109,6 +2109,10 @@ func TestForceStopWhileContinue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClientServerFunctionCall(t *testing.T) {
|
func TestClientServerFunctionCall(t *testing.T) {
|
||||||
|
if buildMode == "pie" && runtime.GOARCH == "ppc64le" {
|
||||||
|
t.Skip("Debug function call Test broken in PIE mode")
|
||||||
|
}
|
||||||
|
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestClient2("fncall", t, func(c service.Client) {
|
withTestClient2("fncall", t, func(c service.Client) {
|
||||||
c.SetReturnValuesLoadConfig(&normalLoadConfig)
|
c.SetReturnValuesLoadConfig(&normalLoadConfig)
|
||||||
@ -2139,6 +2143,9 @@ func TestClientServerFunctionCall(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClientServerFunctionCallPanic(t *testing.T) {
|
func TestClientServerFunctionCallPanic(t *testing.T) {
|
||||||
|
if buildMode == "pie" && runtime.GOARCH == "ppc64le" {
|
||||||
|
t.Skip("Debug function call Test broken in PIE mode")
|
||||||
|
}
|
||||||
protest.MustSupportFunctionCalls(t, testBackend)
|
protest.MustSupportFunctionCalls(t, testBackend)
|
||||||
withTestClient2("fncall", t, func(c service.Client) {
|
withTestClient2("fncall", t, func(c service.Client) {
|
||||||
c.SetReturnValuesLoadConfig(&normalLoadConfig)
|
c.SetReturnValuesLoadConfig(&normalLoadConfig)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user