未验证 提交 7ace7a8e 编写于 作者: A Alessandro Arzilli 提交者: GitHub

proc/gdbserial: remove unnecessary conditional compilation (#2389)

Remove unnecessary conditionally compiled files introduced with the
darwin/arm64 port.
上级 c223ef65
......@@ -138,8 +138,9 @@ var canUnmaskSignalsCached bool
// gdbProcess implements proc.Process using a connection to a debugger stub
// that understands Gdb Remote Serial Protocol.
type gdbProcess struct {
bi *proc.BinaryInfo
conn gdbConn
bi *proc.BinaryInfo
regnames *gdbRegnames
conn gdbConn
threads map[int]*gdbThread
currentThread *gdbThread
......@@ -157,6 +158,8 @@ type gdbProcess struct {
loadGInstrAddr uint64 // address of the g loading instruction, zero if we couldn't allocate it
breakpointKind int // breakpoint kind to pass to 'z' and 'Z' when creating software breakpoints
process *os.Process
waitChan chan *os.ProcessState
......@@ -196,6 +199,7 @@ type gdbRegisters struct {
hasgaddr bool
buf []byte
arch *proc.Arch
regnames *gdbRegnames
}
type gdbRegister struct {
......@@ -203,6 +207,11 @@ type gdbRegister struct {
regnum int
}
// gdbRegname records names of important CPU registers
type gdbRegnames struct {
PC, SP, BP, CX, FsBase string
}
// newProcess creates a new Process instance.
// If process is not nil it is the stub's process and will be killed after
// Detach.
......@@ -218,12 +227,37 @@ func newProcess(process *os.Process) *gdbProcess {
},
threads: make(map[int]*gdbThread),
bi: proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH),
regnames: new(gdbRegnames),
breakpoints: proc.NewBreakpointMap(),
gcmdok: true,
threadStopInfo: true,
process: process,
}
switch p.bi.Arch.Name {
default:
fallthrough
case "amd64":
p.breakpointKind = 1
case "arm64":
p.breakpointKind = 4
}
p.regnames.PC = registerName(p.bi.Arch, p.bi.Arch.PCRegNum)
p.regnames.SP = registerName(p.bi.Arch, p.bi.Arch.SPRegNum)
p.regnames.BP = registerName(p.bi.Arch, p.bi.Arch.BPRegNum)
switch p.bi.Arch.Name {
case "arm64":
p.regnames.BP = "fp"
p.regnames.CX = "x0"
case "amd64":
p.regnames.CX = "rcx"
p.regnames.FsBase = "fs_base"
default:
panic("not implemented")
}
if process != nil {
p.waitChan = make(chan *os.ProcessState)
go func() {
......@@ -282,7 +316,7 @@ func (p *gdbProcess) Dial(addr string, path string, pid int, debugInfoDirs []str
func (p *gdbProcess) Connect(conn net.Conn, path string, pid int, debugInfoDirs []string, stopReason proc.StopReason) (*proc.Target, error) {
p.conn.conn = conn
p.conn.pid = pid
err := p.conn.handshake()
err := p.conn.handshake(p.regnames)
if err != nil {
conn.Close()
return nil, err
......@@ -1038,7 +1072,7 @@ func (p *gdbProcess) Restart(pos string) (proc.Thread, error) {
p.clearThreadRegisters()
for addr := range p.breakpoints.M {
p.conn.setBreakpoint(addr)
p.conn.setBreakpoint(addr, p.breakpointKind)
}
return p.currentThread, p.setCurrentBreakpoints()
......@@ -1175,11 +1209,11 @@ func (p *gdbProcess) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) {
}
func (p *gdbProcess) WriteBreakpoint(bp *proc.Breakpoint) error {
return p.conn.setBreakpoint(bp.Addr)
return p.conn.setBreakpoint(bp.Addr, p.breakpointKind)
}
func (p *gdbProcess) EraseBreakpoint(bp *proc.Breakpoint) error {
return p.conn.clearBreakpoint(bp.Addr)
return p.conn.clearBreakpoint(bp.Addr, p.breakpointKind)
}
type threadUpdater struct {
......@@ -1350,7 +1384,7 @@ func (t *gdbThread) Location() (*proc.Location, error) {
if err != nil {
return nil, err
}
if pcreg, ok := regs.(*gdbRegisters).regs[regnamePC]; !ok {
if pcreg, ok := regs.(*gdbRegisters).regs[regs.(*gdbRegisters).regnames.PC]; !ok {
t.p.conn.log.Errorf("thread %d could not find RIP register", t.ID)
} else if len(pcreg.value) < t.p.bi.Arch.PtrSize() {
t.p.conn.log.Errorf("thread %d bad length for RIP register: %d", t.ID, len(pcreg.value))
......@@ -1400,11 +1434,11 @@ func (t *gdbThread) Common() *proc.CommonThread {
func (t *gdbThread) StepInstruction() error {
pc := t.regs.PC()
if _, atbp := t.p.breakpoints.M[pc]; atbp {
err := t.p.conn.clearBreakpoint(pc)
err := t.p.conn.clearBreakpoint(pc, t.p.breakpointKind)
if err != nil {
return err
}
defer t.p.conn.setBreakpoint(pc)
defer t.p.conn.setBreakpoint(pc, t.p.breakpointKind)
}
// Reset thread registers so the next call to
// Thread.Registers will not be cached.
......@@ -1490,8 +1524,9 @@ func (p *gdbProcess) DumpProcessNotes(notes []elfwriter.Note, threadDone func())
return false, notes, nil
}
func (regs *gdbRegisters) init(regsInfo []gdbRegisterInfo, arch *proc.Arch) {
func (regs *gdbRegisters) init(regsInfo []gdbRegisterInfo, arch *proc.Arch, regnames *gdbRegnames) {
regs.arch = arch
regs.regnames = regnames
regs.regs = make(map[string]gdbRegister)
regs.regsInfo = regsInfo
......@@ -1513,7 +1548,7 @@ func (regs *gdbRegisters) init(regsInfo []gdbRegisterInfo, arch *proc.Arch) {
// the stub can allocate memory, or reloadGAtPC, if the stub can't.
func (t *gdbThread) reloadRegisters() error {
if t.regs.regs == nil {
t.regs.init(t.p.conn.regsInfo, t.p.bi.Arch)
t.regs.init(t.p.conn.regsInfo, t.p.bi.Arch, t.p.regnames)
}
if t.p.gcmdok {
......@@ -1535,7 +1570,7 @@ func (t *gdbThread) reloadRegisters() error {
switch t.p.bi.GOOS {
case "linux":
if reg, hasFsBase := t.regs.regs[regnameFsBase]; hasFsBase {
if reg, hasFsBase := t.regs.regs[t.p.regnames.FsBase]; hasFsBase {
t.regs.gaddr = 0
t.regs.tls = binary.LittleEndian.Uint64(reg.value)
t.regs.hasgaddr = false
......@@ -1622,11 +1657,11 @@ func (t *gdbThread) reloadGAtPC() error {
// Additionally all breakpoints in [pc, pc+len(movinstr)] need to be removed
for addr := range t.p.breakpoints.M {
if addr >= pc && addr <= pc+uint64(len(movinstr)) {
err := t.p.conn.clearBreakpoint(addr)
err := t.p.conn.clearBreakpoint(addr, t.p.breakpointKind)
if err != nil {
return err
}
defer t.p.conn.setBreakpoint(addr)
defer t.p.conn.setBreakpoint(addr, t.p.breakpointKind)
}
}
......@@ -1648,7 +1683,7 @@ func (t *gdbThread) reloadGAtPC() error {
}
t.regs.setPC(pc)
t.regs.setCX(cx)
err1 := t.writeSomeRegisters(regnamePC, regnameCX)
err1 := t.writeSomeRegisters(t.p.regnames.PC, t.p.regnames.CX)
if err == nil {
err = err1
}
......@@ -1665,7 +1700,7 @@ func (t *gdbThread) reloadGAtPC() error {
return err
}
if err := t.readSomeRegisters(regnamePC, regnameCX); err != nil {
if err := t.readSomeRegisters(t.p.regnames.PC, t.p.regnames.CX); err != nil {
return err
}
......@@ -1692,7 +1727,7 @@ func (t *gdbThread) reloadGAlloc() error {
pc := t.regs.PC()
t.regs.setPC(t.p.loadGInstrAddr)
if err := t.writeSomeRegisters(regnamePC); err != nil {
if err := t.writeSomeRegisters(t.p.regnames.PC); err != nil {
return err
}
......@@ -1701,7 +1736,7 @@ func (t *gdbThread) reloadGAlloc() error {
defer func() {
t.regs.setPC(pc)
t.regs.setCX(cx)
err1 := t.writeSomeRegisters(regnamePC, regnameCX)
err1 := t.writeSomeRegisters(t.p.regnames.PC, t.p.regnames.CX)
if err == nil {
err = err1
}
......@@ -1718,7 +1753,7 @@ func (t *gdbThread) reloadGAlloc() error {
return err
}
if err := t.readSomeRegisters(regnameCX); err != nil {
if err := t.readSomeRegisters(t.p.regnames.CX); err != nil {
return err
}
......@@ -1761,27 +1796,27 @@ func (t *gdbThread) SetCurrentBreakpoint(adjustPC bool) error {
}
func (regs *gdbRegisters) PC() uint64 {
return binary.LittleEndian.Uint64(regs.regs[regnamePC].value)
return binary.LittleEndian.Uint64(regs.regs[regs.regnames.PC].value)
}
func (regs *gdbRegisters) setPC(value uint64) {
binary.LittleEndian.PutUint64(regs.regs[regnamePC].value, value)
binary.LittleEndian.PutUint64(regs.regs[regs.regnames.PC].value, value)
}
func (regs *gdbRegisters) SP() uint64 {
return binary.LittleEndian.Uint64(regs.regs[regnameSP].value)
return binary.LittleEndian.Uint64(regs.regs[regs.regnames.SP].value)
}
func (regs *gdbRegisters) BP() uint64 {
return binary.LittleEndian.Uint64(regs.regs[regnameBP].value)
return binary.LittleEndian.Uint64(regs.regs[regs.regnames.BP].value)
}
func (regs *gdbRegisters) CX() uint64 {
return binary.LittleEndian.Uint64(regs.regs[regnameCX].value)
return binary.LittleEndian.Uint64(regs.regs[regs.regnames.CX].value)
}
func (regs *gdbRegisters) setCX(value uint64) {
binary.LittleEndian.PutUint64(regs.regs[regnameCX].value, value)
binary.LittleEndian.PutUint64(regs.regs[regs.regnames.CX].value, value)
}
func (regs *gdbRegisters) TLS() uint64 {
......@@ -2180,14 +2215,13 @@ func (t *gdbThread) setPC(pc uint64) error {
if t.p.gcmdok {
return t.p.conn.writeRegisters(t.strID, t.regs.buf)
}
reg := t.regs.regs[regnamePC]
reg := t.regs.regs[t.regs.regnames.PC]
return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value)
}
// SetReg will change the value of a list of registers
func (t *gdbThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
regName, _, _ := t.p.bi.Arch.DwarfRegisterToString(int(regNum), nil)
regName = strings.ToLower(regName)
regName := registerName(t.p.bi.Arch, regNum)
_, _ = t.Registers() // Registers must be loaded first
gdbreg, ok := t.regs.regs[regName]
if !ok && strings.HasPrefix(regName, "xmm") {
......@@ -2261,7 +2295,12 @@ func (regs *gdbRegisters) Slice(floatingPoint bool) ([]proc.Register, error) {
func (regs *gdbRegisters) Copy() (proc.Registers, error) {
savedRegs := &gdbRegisters{}
savedRegs.init(regs.regsInfo, regs.arch)
savedRegs.init(regs.regsInfo, regs.arch, regs.regnames)
copy(savedRegs.buf, regs.buf)
return savedRegs, nil
}
func registerName(arch *proc.Arch, regNum uint64) string {
regName, _, _ := arch.DwarfRegisterToString(int(regNum), nil)
return strings.ToLower(regName)
}
......@@ -94,7 +94,7 @@ const (
qSupportedMultiprocess = "$qSupported:multiprocess+;swbreak+;hwbreak+;no-resumed+;xmlRegisters=i386"
)
func (conn *gdbConn) handshake() error {
func (conn *gdbConn) handshake(regnames *gdbRegnames) error {
conn.ack = true
conn.packetSize = 256
conn.rdr = bufio.NewReader(conn.conn)
......@@ -140,15 +140,29 @@ func (conn *gdbConn) handshake() error {
// Attempt to figure out the name of the processor register.
// We either need qXfer:features:read (gdbserver/rr) or qRegisterInfo (lldb)
if err := conn.readRegisterInfo(); err != nil {
regFound := map[string]bool{
regnames.PC: false,
regnames.SP: false,
regnames.BP: false,
regnames.CX: false,
}
if err := conn.readRegisterInfo(regFound); err != nil {
if isProtocolErrorUnsupported(err) {
if err := conn.readTargetXml(); err != nil {
if err := conn.readTargetXml(regFound); err != nil {
return err
}
} else {
return err
}
}
for n := range regFound {
if n == "" {
continue
}
if !regFound[n] {
return fmt.Errorf("could not find %s register", n)
}
}
// We either need:
// * QListThreadsInStopReply + qThreadStopInfo (i.e. lldb-server/debugserver),
......@@ -226,17 +240,24 @@ type gdbRegisterInfo struct {
Group string `xml:"group,attr"`
}
func setRegFound(regFound map[string]bool, name string) {
for n := range regFound {
if name == n {
regFound[n] = true
}
}
}
// readTargetXml reads target.xml file from stub using qXfer:features:read,
// then parses it requesting any additional files.
// The schema of target.xml is described by:
// https://github.com/bminor/binutils-gdb/blob/61baf725eca99af2569262d10aca03dcde2698f6/gdb/features/gdb-target.dtd
func (conn *gdbConn) readTargetXml() (err error) {
func (conn *gdbConn) readTargetXml(regFound map[string]bool) (err error) {
conn.regsInfo, err = conn.readAnnex("target.xml")
if err != nil {
return err
}
var offset int
var pcFound, cxFound, spFound bool
regnum := 0
for i := range conn.regsInfo {
if conn.regsInfo[i].Regnum == 0 {
......@@ -246,25 +267,9 @@ func (conn *gdbConn) readTargetXml() (err error) {
}
conn.regsInfo[i].Offset = offset
offset += conn.regsInfo[i].Bitsize / 8
switch conn.regsInfo[i].Name {
case regnamePC:
pcFound = true
case regnameCX:
cxFound = true
case regnameSP:
spFound = true
}
regnum++
}
if !pcFound {
return errors.New("could not find RIP register")
}
if !spFound {
return errors.New("could not find RSP register")
}
if !cxFound {
return errors.New("could not find RCX register")
setRegFound(regFound, conn.regsInfo[i].Name)
regnum++
}
return nil
......@@ -272,9 +277,8 @@ func (conn *gdbConn) readTargetXml() (err error) {
// readRegisterInfo uses qRegisterInfo to read register information (used
// when qXfer:feature:read is not supported).
func (conn *gdbConn) readRegisterInfo() (err error) {
func (conn *gdbConn) readRegisterInfo(regFound map[string]bool) (err error) {
regnum := 0
var pcFound, cxFound, spFound bool
for {
conn.outbuf.Reset()
fmt.Fprintf(&conn.outbuf, "$qRegisterInfo%x", regnum)
......@@ -327,30 +331,13 @@ func (conn *gdbConn) readRegisterInfo() (err error) {
continue
}
switch regname {
case regnamePC:
pcFound = true
case regnameCX:
cxFound = true
case regnameSP:
spFound = true
}
setRegFound(regFound, regname)
conn.regsInfo = append(conn.regsInfo, gdbRegisterInfo{Regnum: regnum, Name: regname, Bitsize: bitsize, Offset: offset})
regnum++
}
if !pcFound {
return errors.New("could not find RIP register")
}
if !spFound {
return errors.New("could not find RSP register")
}
if !cxFound {
return errors.New("could not find RCX register")
}
return nil
}
......@@ -410,17 +397,17 @@ func (conn *gdbConn) qXfer(kind, annex string, binary bool) ([]byte, error) {
}
// setBreakpoint executes a 'Z' (insert breakpoint) command of type '0' and kind '1' or '4'
func (conn *gdbConn) setBreakpoint(addr uint64) error {
func (conn *gdbConn) setBreakpoint(addr uint64, kind int) error {
conn.outbuf.Reset()
fmt.Fprintf(&conn.outbuf, "$Z0,%x,%d", addr, breakpointKind)
fmt.Fprintf(&conn.outbuf, "$Z0,%x,%d", addr, kind)
_, err := conn.exec(conn.outbuf.Bytes(), "set breakpoint")
return err
}
// clearBreakpoint executes a 'z' (remove breakpoint) command of type '0' and kind '1' or '4'
func (conn *gdbConn) clearBreakpoint(addr uint64) error {
func (conn *gdbConn) clearBreakpoint(addr uint64, kind int) error {
conn.outbuf.Reset()
fmt.Fprintf(&conn.outbuf, "$z0,%x,%d", addr, breakpointKind)
fmt.Fprintf(&conn.outbuf, "$z0,%x,%d", addr, kind)
_, err := conn.exec(conn.outbuf.Bytes(), "clear breakpoint")
return err
}
......
//+build 386
package gdbserial
const (
regnamePC = "rip"
regnameCX = "rcx"
regnameSP = "rsp"
regnameDX = "rdx"
regnameBP = "rbp"
regnameFsBase = "fs_base"
regnameGsBase = "gs_base"
breakpointKind = 1
)
//+build amd64
package gdbserial
const (
regnamePC = "rip"
regnameCX = "rcx"
regnameSP = "rsp"
regnameDX = "rdx"
regnameBP = "rbp"
regnameFsBase = "fs_base"
regnameGsBase = "gs_base"
breakpointKind = 1
)
//+build arm64
package gdbserial
const (
regnamePC = "pc"
regnameCX = "x0"
regnameSP = "sp"
regnameBP = "fp"
// not needed but needs to be declared
regnameFsBase = ""
regnameDX = ""
breakpointKind = 4
)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册