From 32bdd19f8fa1e9a3b44a84191ad75cb2c4897fcd Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Tue, 17 May 2022 18:19:34 +0200 Subject: [PATCH] proc/gdbserver: fix function call injection on rr (#3007) Issue https://github.com/rr-debugger/rr/issues/3208 was fixed so finish fixing call injection on rr and remove the test exception. --- pkg/proc/gdbserial/gdbserver.go | 66 +++++++++++++++++++++++++-------- pkg/proc/proc_test.go | 1 + service/test/variables_test.go | 5 --- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index aafca0c5..7c0ca13f 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1958,27 +1958,61 @@ func (t *gdbThread) SetReg(regNum uint64, reg *op.DwarfRegister) error { if !ok && t.p.bi.Arch.Name == "arm64" && regName == "x30" { gdbreg, ok = t.regs.regs["lr"] } + if !ok && regName == "rflags" { + // rr has eflags instead of rflags + regName = "eflags" + gdbreg, ok = t.regs.regs[regName] + if ok { + reg.FillBytes() + reg.Bytes = reg.Bytes[:4] + } + } if !ok { return fmt.Errorf("could not set register %s: not found", regName) } reg.FillBytes() - if len(reg.Bytes) != len(gdbreg.value) { - return fmt.Errorf("could not set register %s: wrong size, expected %d got %d", regName, len(gdbreg.value), len(reg.Bytes)) + + wrongSizeErr := func(n int) error { + return fmt.Errorf("could not set register %s: wrong size, expected %d got %d", regName, n, len(reg.Bytes)) } - copy(gdbreg.value, reg.Bytes) - err := t.p.conn.writeRegister(t.strID, gdbreg.regnum, gdbreg.value) - if err != nil { - return err - } - if t.p.conn.workaroundReg != nil && len(gdbreg.value) > 16 { - // This is a workaround for a bug in debugserver where register writes (P - // packet) on AVX-2 and AVX-512 registers are ignored unless they are - // followed by a write to an AVX register. - // See: - // Issue #2767 - // https://bugs.llvm.org/show_bug.cgi?id=52362 - reg := t.regs.gdbRegisterNew(t.p.conn.workaroundReg) - return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value) + + if len(reg.Bytes) == len(gdbreg.value) { + copy(gdbreg.value, reg.Bytes) + err := t.p.conn.writeRegister(t.strID, gdbreg.regnum, gdbreg.value) + if err != nil { + return err + } + if t.p.conn.workaroundReg != nil && len(gdbreg.value) > 16 { + // This is a workaround for a bug in debugserver where register writes (P + // packet) on AVX-2 and AVX-512 registers are ignored unless they are + // followed by a write to an AVX register. + // See: + // Issue #2767 + // https://bugs.llvm.org/show_bug.cgi?id=52362 + reg := t.regs.gdbRegisterNew(t.p.conn.workaroundReg) + return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value) + } + } else if len(reg.Bytes) == 2*len(gdbreg.value) && strings.HasPrefix(regName, "xmm") { + // rr uses xmmN for the low part of the register and ymmNh for the high part + gdbregh, ok := t.regs.regs["y"+regName[1:]+"h"] + if !ok { + return wrongSizeErr(len(gdbreg.value)) + } + if len(reg.Bytes) != len(gdbreg.value)+len(gdbregh.value) { + return wrongSizeErr(len(gdbreg.value) + len(gdbregh.value)) + } + copy(gdbreg.value, reg.Bytes[:len(gdbreg.value)]) + copy(gdbregh.value, reg.Bytes[len(gdbreg.value):]) + err := t.p.conn.writeRegister(t.strID, gdbreg.regnum, gdbreg.value) + if err != nil { + return err + } + err = t.p.conn.writeRegister(t.strID, gdbregh.regnum, gdbregh.value) + if err != nil { + return err + } + } else { + return wrongSizeErr(len(gdbreg.value)) } return nil } diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 0a74ac2a..f156a6f1 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -5860,6 +5860,7 @@ func TestCallInjectionFlagCorruption(t *testing.T) { // time, after stepping out of debugCallV2. // Fixes issue https://github.com/go-delve/delve/issues/2985 skipUnlessOn(t, "not relevant", "amd64") + protest.MustSupportFunctionCalls(t, testBackend) withTestProcessArgs("badflags", t, ".", []string{"0"}, 0, func(p *proc.Target, fixture protest.Fixture) { mainfn := p.BinInfo().LookupFunc["main.main"] diff --git a/service/test/variables_test.go b/service/test/variables_test.go index c8c4a7d0..6a83c397 100644 --- a/service/test/variables_test.go +++ b/service/test/variables_test.go @@ -1340,11 +1340,6 @@ func TestCallFunction(t *testing.T) { if goversion.VersionAfterOrEqual(runtime.Version(), 1, 17) { for _, tc := range testcases117 { - if strings.Contains(tc.expr, "floatsum") && testBackend == "rr" { - // Can not set floating point registers with RR. - // See: https://github.com/rr-debugger/rr/issues/3208 - continue - } testCallFunction(t, p, tc) } }