Rename: s/BreakPoint/Breakpoint/
This commit is contained in:
parent
98e7089dd3
commit
a71f218e35
@ -7,7 +7,7 @@ type Arch interface {
|
|||||||
BreakpointInstruction() []byte
|
BreakpointInstruction() []byte
|
||||||
BreakpointSize() int
|
BreakpointSize() int
|
||||||
CurgInstructions() []byte
|
CurgInstructions() []byte
|
||||||
HardwareBreakPoints() []*BreakPoint
|
HardwareBreakpoints() []*Breakpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
type AMD64 struct {
|
type AMD64 struct {
|
||||||
@ -15,7 +15,7 @@ type AMD64 struct {
|
|||||||
breakInstruction []byte
|
breakInstruction []byte
|
||||||
breakInstructionLen int
|
breakInstructionLen int
|
||||||
curgInstructions []byte
|
curgInstructions []byte
|
||||||
hardwareBreakPoints []*BreakPoint // Slice of hardware breakpoints
|
hardwareBreakpoints []*Breakpoint // Slice of hardware breakpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
func AMD64Arch() *AMD64 {
|
func AMD64Arch() *AMD64 {
|
||||||
@ -42,7 +42,7 @@ func AMD64Arch() *AMD64 {
|
|||||||
breakInstruction: breakInstr,
|
breakInstruction: breakInstr,
|
||||||
breakInstructionLen: 1,
|
breakInstructionLen: 1,
|
||||||
curgInstructions: curg,
|
curgInstructions: curg,
|
||||||
hardwareBreakPoints: make([]*BreakPoint, 4),
|
hardwareBreakpoints: make([]*Breakpoint, 4),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +62,6 @@ func (a *AMD64) CurgInstructions() []byte {
|
|||||||
return a.curgInstructions
|
return a.curgInstructions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AMD64) HardwareBreakPoints() []*BreakPoint {
|
func (a *AMD64) HardwareBreakpoints() []*Breakpoint {
|
||||||
return a.hardwareBreakPoints
|
return a.hardwareBreakpoints
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
// Represents a single breakpoint. Stores information on the break
|
// Represents a single breakpoint. Stores information on the break
|
||||||
// point including the byte of data that originally was stored at that
|
// point including the byte of data that originally was stored at that
|
||||||
// address.
|
// address.
|
||||||
type BreakPoint struct {
|
type Breakpoint struct {
|
||||||
// File & line information for printing.
|
// File & line information for printing.
|
||||||
FunctionName string
|
FunctionName string
|
||||||
File string
|
File string
|
||||||
@ -22,13 +22,13 @@ type BreakPoint struct {
|
|||||||
reg int // If hardware breakpoint, what debug register it belongs to.
|
reg int // If hardware breakpoint, what debug register it belongs to.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bp *BreakPoint) String() string {
|
func (bp *Breakpoint) String() string {
|
||||||
return fmt.Sprintf("Breakpoint %d at %#v %s:%d", bp.ID, bp.Addr, bp.File, bp.Line)
|
return fmt.Sprintf("Breakpoint %d at %#v %s:%d", bp.ID, bp.Addr, bp.File, bp.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear this breakpoint appropriately depending on whether it is a
|
// Clear this breakpoint appropriately depending on whether it is a
|
||||||
// hardware or software breakpoint.
|
// hardware or software breakpoint.
|
||||||
func (bp *BreakPoint) Clear(thread *ThreadContext) (*BreakPoint, error) {
|
func (bp *Breakpoint) Clear(thread *ThreadContext) (*Breakpoint, error) {
|
||||||
if bp.hardware {
|
if bp.hardware {
|
||||||
if err := clearHardwareBreakpoint(bp.reg, thread.Id); err != nil {
|
if err := clearHardwareBreakpoint(bp.reg, thread.Id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -43,13 +43,13 @@ func (bp *BreakPoint) Clear(thread *ThreadContext) (*BreakPoint, error) {
|
|||||||
|
|
||||||
// Returned when trying to set a breakpoint at
|
// Returned when trying to set a breakpoint at
|
||||||
// an address that already has a breakpoint set for it.
|
// an address that already has a breakpoint set for it.
|
||||||
type BreakPointExistsError struct {
|
type BreakpointExistsError struct {
|
||||||
file string
|
file string
|
||||||
line int
|
line int
|
||||||
addr uint64
|
addr uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bpe BreakPointExistsError) Error() string {
|
func (bpe BreakpointExistsError) Error() string {
|
||||||
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
|
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ func (iae InvalidAddressError) Error() string {
|
|||||||
|
|
||||||
// Returns whether or not a breakpoint has been set for the given address.
|
// Returns whether or not a breakpoint has been set for the given address.
|
||||||
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
|
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
|
||||||
for _, bp := range dbp.arch.HardwareBreakPoints() {
|
for _, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
// TODO(darwin)
|
// TODO(darwin)
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
break
|
break
|
||||||
@ -74,11 +74,11 @@ func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, ok := dbp.BreakPoints[addr]
|
_, ok := dbp.Breakpoints[addr]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte, temp bool) *BreakPoint {
|
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte, temp bool) *Breakpoint {
|
||||||
var id int
|
var id int
|
||||||
if temp {
|
if temp {
|
||||||
dbp.tempBreakpointIDCounter++
|
dbp.tempBreakpointIDCounter++
|
||||||
@ -87,7 +87,7 @@ func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data
|
|||||||
dbp.breakpointIDCounter++
|
dbp.breakpointIDCounter++
|
||||||
id = dbp.breakpointIDCounter
|
id = dbp.breakpointIDCounter
|
||||||
}
|
}
|
||||||
return &BreakPoint{
|
return &Breakpoint{
|
||||||
FunctionName: fn,
|
FunctionName: fn,
|
||||||
File: f,
|
File: f,
|
||||||
Line: l,
|
Line: l,
|
||||||
@ -98,23 +98,23 @@ func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) newHardwareBreakpoint(fn, f string, l int, addr uint64, data []byte, temp bool, reg int) *BreakPoint {
|
func (dbp *DebuggedProcess) newHardwareBreakpoint(fn, f string, l int, addr uint64, data []byte, temp bool, reg int) *Breakpoint {
|
||||||
bp := dbp.newBreakpoint(fn, f, l, addr, data, temp)
|
bp := dbp.newBreakpoint(fn, f, l, addr, data, temp)
|
||||||
bp.hardware = true
|
bp.hardware = true
|
||||||
bp.reg = reg
|
bp.reg = reg
|
||||||
return bp
|
return bp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*Breakpoint, error) {
|
||||||
var f, l, fn = dbp.goSymTable.PCToLine(uint64(addr))
|
var f, l, fn = dbp.goSymTable.PCToLine(uint64(addr))
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
return nil, InvalidAddressError{address: addr}
|
return nil, InvalidAddressError{address: addr}
|
||||||
}
|
}
|
||||||
if dbp.BreakpointExists(addr) {
|
if dbp.BreakpointExists(addr) {
|
||||||
return nil, BreakPointExistsError{f, l, addr}
|
return nil, BreakpointExistsError{f, l, addr}
|
||||||
}
|
}
|
||||||
// Try and set a hardware breakpoint.
|
// Try and set a hardware breakpoint.
|
||||||
for i, v := range dbp.arch.HardwareBreakPoints() {
|
for i, v := range dbp.arch.HardwareBreakpoints() {
|
||||||
// TODO(darwin)
|
// TODO(darwin)
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
break
|
break
|
||||||
@ -125,8 +125,8 @@ func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*Bre
|
|||||||
return nil, fmt.Errorf("could not set hardware breakpoint on thread %d: %s", t, err)
|
return nil, fmt.Errorf("could not set hardware breakpoint on thread %d: %s", t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbp.arch.HardwareBreakPoints()[i] = dbp.newHardwareBreakpoint(fn.Name, f, l, addr, nil, temp, i)
|
dbp.arch.HardwareBreakpoints()[i] = dbp.newHardwareBreakpoint(fn.Name, f, l, addr, nil, temp, i)
|
||||||
return dbp.arch.HardwareBreakPoints()[i], nil
|
return dbp.arch.HardwareBreakpoints()[i], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall back to software breakpoint. 0xCC is INT 3 trap interrupt.
|
// Fall back to software breakpoint. 0xCC is INT 3 trap interrupt.
|
||||||
@ -138,23 +138,23 @@ func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*Bre
|
|||||||
if _, err := writeMemory(thread, uintptr(addr), dbp.arch.BreakpointInstruction()); err != nil {
|
if _, err := writeMemory(thread, uintptr(addr), dbp.arch.BreakpointInstruction()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData, temp)
|
dbp.Breakpoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData, temp)
|
||||||
return dbp.BreakPoints[addr], nil
|
return dbp.Breakpoints[addr], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error thrown when trying to clear a breakpoint that does not exist.
|
// Error thrown when trying to clear a breakpoint that does not exist.
|
||||||
type NoBreakPointError struct {
|
type NoBreakpointError struct {
|
||||||
addr uint64
|
addr uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nbp NoBreakPointError) Error() string {
|
func (nbp NoBreakpointError) Error() string {
|
||||||
return fmt.Sprintf("no breakpoint at %#v", nbp.addr)
|
return fmt.Sprintf("no breakpoint at %#v", nbp.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*Breakpoint, error) {
|
||||||
thread := dbp.Threads[tid]
|
thread := dbp.Threads[tid]
|
||||||
// Check for hardware breakpoint
|
// Check for hardware breakpoint
|
||||||
for i, bp := range dbp.arch.HardwareBreakPoints() {
|
for i, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
if bp == nil {
|
if bp == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -163,17 +163,17 @@ func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dbp.arch.HardwareBreakPoints()[i] = nil
|
dbp.arch.HardwareBreakpoints()[i] = nil
|
||||||
return bp, nil
|
return bp, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for software breakpoint
|
// Check for software breakpoint
|
||||||
if bp, ok := dbp.BreakPoints[addr]; ok {
|
if bp, ok := dbp.Breakpoints[addr]; ok {
|
||||||
if _, err := bp.Clear(thread); err != nil {
|
if _, err := bp.Clear(thread); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
delete(dbp.BreakPoints, addr)
|
delete(dbp.Breakpoints, addr)
|
||||||
return bp, nil
|
return bp, nil
|
||||||
}
|
}
|
||||||
return nil, NoBreakPointError{addr: addr}
|
return nil, NoBreakpointError{addr: addr}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ type DebuggedProcess struct {
|
|||||||
Process *os.Process // Pointer to process struct for the actual process we are debugging
|
Process *os.Process // Pointer to process struct for the actual process we are debugging
|
||||||
|
|
||||||
// Software breakpoint table. Hardware breakpoints are stored in proctl/arch.go, as they are architecture dependant.
|
// Software breakpoint table. Hardware breakpoints are stored in proctl/arch.go, as they are architecture dependant.
|
||||||
BreakPoints map[uint64]*BreakPoint
|
Breakpoints map[uint64]*Breakpoint
|
||||||
|
|
||||||
// List of threads mapped as such: pid -> *ThreadContext
|
// List of threads mapped as such: pid -> *ThreadContext
|
||||||
Threads map[int]*ThreadContext
|
Threads map[int]*ThreadContext
|
||||||
@ -75,7 +75,7 @@ func Attach(pid int) (*DebuggedProcess, error) {
|
|||||||
dbp := &DebuggedProcess{
|
dbp := &DebuggedProcess{
|
||||||
Pid: pid,
|
Pid: pid,
|
||||||
Threads: make(map[int]*ThreadContext),
|
Threads: make(map[int]*ThreadContext),
|
||||||
BreakPoints: make(map[uint64]*BreakPoint),
|
Breakpoints: make(map[uint64]*Breakpoint),
|
||||||
os: new(OSProcessDetails),
|
os: new(OSProcessDetails),
|
||||||
ast: source.New(),
|
ast: source.New(),
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ func (dbp *DebuggedProcess) FindLocation(str string) (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use as breakpoint id
|
// Use as breakpoint id
|
||||||
for _, bp := range dbp.arch.HardwareBreakPoints() {
|
for _, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
if bp == nil {
|
if bp == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ func (dbp *DebuggedProcess) FindLocation(str string) (uint64, error) {
|
|||||||
return bp.Addr, nil
|
return bp.Addr, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, bp := range dbp.BreakPoints {
|
for _, bp := range dbp.Breakpoints {
|
||||||
if uint64(bp.ID) == id {
|
if uint64(bp.ID) == id {
|
||||||
return bp.Addr, nil
|
return bp.Addr, nil
|
||||||
}
|
}
|
||||||
@ -203,17 +203,17 @@ func (dbp *DebuggedProcess) RequestManualStop() error {
|
|||||||
// hardware supports it, and there are free debug registers, Delve
|
// hardware supports it, and there are free debug registers, Delve
|
||||||
// will set a hardware breakpoint. Otherwise we fall back to software
|
// will set a hardware breakpoint. Otherwise we fall back to software
|
||||||
// breakpoints, which are a bit more work for us.
|
// breakpoints, which are a bit more work for us.
|
||||||
func (dbp *DebuggedProcess) Break(addr uint64) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) Break(addr uint64) (*Breakpoint, error) {
|
||||||
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, false)
|
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a temp breakpoint, for the 'next' command.
|
// Sets a temp breakpoint, for the 'next' command.
|
||||||
func (dbp *DebuggedProcess) TempBreak(addr uint64) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||||
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, true)
|
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a breakpoint by location string (function, file+line, address)
|
// Sets a breakpoint by location string (function, file+line, address)
|
||||||
func (dbp *DebuggedProcess) BreakByLocation(loc string) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) BreakByLocation(loc string) (*Breakpoint, error) {
|
||||||
addr, err := dbp.FindLocation(loc)
|
addr, err := dbp.FindLocation(loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -221,17 +221,17 @@ func (dbp *DebuggedProcess) BreakByLocation(loc string) (*BreakPoint, error) {
|
|||||||
return dbp.Break(addr)
|
return dbp.Break(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) HardwareBreakPoints() []*BreakPoint {
|
func (dbp *DebuggedProcess) HardwareBreakpoints() []*Breakpoint {
|
||||||
return dbp.arch.HardwareBreakPoints()
|
return dbp.arch.HardwareBreakpoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears a breakpoint in the current thread.
|
// Clears a breakpoint in the current thread.
|
||||||
func (dbp *DebuggedProcess) Clear(addr uint64) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) Clear(addr uint64) (*Breakpoint, error) {
|
||||||
return dbp.clearBreakpoint(dbp.CurrentThread.Id, addr)
|
return dbp.clearBreakpoint(dbp.CurrentThread.Id, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears a breakpoint by location (function, file+line, address, breakpoint id)
|
// Clears a breakpoint by location (function, file+line, address, breakpoint id)
|
||||||
func (dbp *DebuggedProcess) ClearByLocation(loc string) (*BreakPoint, error) {
|
func (dbp *DebuggedProcess) ClearByLocation(loc string) (*Breakpoint, error) {
|
||||||
addr, err := dbp.FindLocation(loc)
|
addr, err := dbp.FindLocation(loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -468,7 +468,7 @@ func (dbp *DebuggedProcess) PC() (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the PC of the current thread.
|
// Returns the PC of the current thread.
|
||||||
func (dbp *DebuggedProcess) CurrentBreakpoint() *BreakPoint {
|
func (dbp *DebuggedProcess) CurrentBreakpoint() *Breakpoint {
|
||||||
return dbp.CurrentThread.CurrentBreakpoint
|
return dbp.CurrentThread.CurrentBreakpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,13 +498,13 @@ func (dbp *DebuggedProcess) PCToLine(pc uint64) (string, int, *gosym.Func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finds the breakpoint for the given pc.
|
// Finds the breakpoint for the given pc.
|
||||||
func (dbp *DebuggedProcess) FindBreakpoint(pc uint64) (*BreakPoint, bool) {
|
func (dbp *DebuggedProcess) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
|
||||||
for _, bp := range dbp.arch.HardwareBreakPoints() {
|
for _, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
if bp != nil && bp.Addr == pc {
|
if bp != nil && bp.Addr == pc {
|
||||||
return bp, true
|
return bp, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bp, ok := dbp.BreakPoints[pc]; ok {
|
if bp, ok := dbp.Breakpoints[pc]; ok {
|
||||||
return bp, true
|
return bp, true
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -547,14 +547,14 @@ func initializeDebugProcess(dbp *DebuggedProcess, path string, attach bool) (*De
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
||||||
for _, bp := range dbp.arch.HardwareBreakPoints() {
|
for _, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
if bp != nil && bp.Temp {
|
if bp != nil && bp.Temp {
|
||||||
if _, err := dbp.Clear(bp.Addr); err != nil {
|
if _, err := dbp.Clear(bp.Addr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, bp := range dbp.BreakPoints {
|
for _, bp := range dbp.Breakpoints {
|
||||||
if !bp.Temp {
|
if !bp.Temp {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -575,14 +575,14 @@ func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*ThreadContext, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Check for hardware breakpoint
|
// Check for hardware breakpoint
|
||||||
for _, bp := range dbp.arch.HardwareBreakPoints() {
|
for _, bp := range dbp.arch.HardwareBreakpoints() {
|
||||||
if bp != nil && bp.Addr == pc {
|
if bp != nil && bp.Addr == pc {
|
||||||
thread.CurrentBreakpoint = bp
|
thread.CurrentBreakpoint = bp
|
||||||
return thread, nil
|
return thread, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check to see if we have hit a software breakpoint.
|
// Check to see if we have hit a software breakpoint.
|
||||||
if bp, ok := dbp.BreakPoints[pc-1]; ok {
|
if bp, ok := dbp.Breakpoints[pc-1]; ok {
|
||||||
thread.CurrentBreakpoint = bp
|
thread.CurrentBreakpoint = bp
|
||||||
if err = thread.SetPC(bp.Addr); err != nil {
|
if err = thread.SetPC(bp.Addr); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -603,7 +603,7 @@ func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*ThreadContext, er
|
|||||||
}
|
}
|
||||||
return thread, nil
|
return thread, nil
|
||||||
}
|
}
|
||||||
return nil, NoBreakPointError{addr: pc}
|
return nil, NoBreakpointError{addr: pc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *DebuggedProcess) run(fn func() error) error {
|
func (dbp *DebuggedProcess) run(fn func() error) error {
|
||||||
|
@ -46,7 +46,7 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
|||||||
|
|
||||||
dbp := &DebuggedProcess{
|
dbp := &DebuggedProcess{
|
||||||
Threads: make(map[int]*ThreadContext),
|
Threads: make(map[int]*ThreadContext),
|
||||||
BreakPoints: make(map[uint64]*BreakPoint),
|
Breakpoints: make(map[uint64]*Breakpoint),
|
||||||
firstStart: true,
|
firstStart: true,
|
||||||
os: new(OSProcessDetails),
|
os: new(OSProcessDetails),
|
||||||
ast: source.New(),
|
ast: source.New(),
|
||||||
@ -249,7 +249,7 @@ func (dbp *DebuggedProcess) trapWait(pid int) (*ThreadContext, error) {
|
|||||||
dbp.updateThreadList()
|
dbp.updateThreadList()
|
||||||
th, err = dbp.handleBreakpointOnThread(int(port))
|
th, err = dbp.handleBreakpointOnThread(int(port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(NoBreakPointError); ok {
|
if _, ok := err.(NoBreakpointError); ok {
|
||||||
th := dbp.Threads[int(port)]
|
th := dbp.Threads[int(port)]
|
||||||
if dbp.firstStart || dbp.singleStepping || th.singleStepping {
|
if dbp.firstStart || dbp.singleStepping || th.singleStepping {
|
||||||
dbp.firstStart = false
|
dbp.firstStart = false
|
||||||
|
@ -47,7 +47,7 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
|||||||
dbp := &DebuggedProcess{
|
dbp := &DebuggedProcess{
|
||||||
Pid: proc.Process.Pid,
|
Pid: proc.Process.Pid,
|
||||||
Threads: make(map[int]*ThreadContext),
|
Threads: make(map[int]*ThreadContext),
|
||||||
BreakPoints: make(map[uint64]*BreakPoint),
|
Breakpoints: make(map[uint64]*Breakpoint),
|
||||||
os: new(OSProcessDetails),
|
os: new(OSProcessDetails),
|
||||||
ast: source.New(),
|
ast: source.New(),
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ func (dbp *DebuggedProcess) trapWait(pid int) (*ThreadContext, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for reg, bp := range dbp.HardwareBreakPoints() {
|
for reg, bp := range dbp.HardwareBreakpoints() {
|
||||||
if bp == nil {
|
if bp == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ func TestStep(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBreakPoint(t *testing.T) {
|
func TestBreakpoint(t *testing.T) {
|
||||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||||
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
|
helloworldfunc := p.goSymTable.LookupFunc("main.helloworld")
|
||||||
helloworldaddr := helloworldfunc.Entry
|
helloworldaddr := helloworldfunc.Entry
|
||||||
@ -159,7 +159,7 @@ func TestBreakPoint(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBreakPointInSeperateGoRoutine(t *testing.T) {
|
func TestBreakpointInSeperateGoRoutine(t *testing.T) {
|
||||||
withTestProcess("testthreads", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
withTestProcess("testthreads", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||||
fn := p.goSymTable.LookupFunc("main.anotherthread")
|
fn := p.goSymTable.LookupFunc("main.anotherthread")
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
@ -188,7 +188,7 @@ func TestBreakPointInSeperateGoRoutine(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBreakPointWithNonExistantFunction(t *testing.T) {
|
func TestBreakpointWithNonExistantFunction(t *testing.T) {
|
||||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||||
_, err := p.Break(0)
|
_, err := p.Break(0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -197,7 +197,7 @@ func TestBreakPointWithNonExistantFunction(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClearBreakPoint(t *testing.T) {
|
func TestClearBreakpoint(t *testing.T) {
|
||||||
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
withTestProcess("testprog", t, func(p *DebuggedProcess, fixture protest.Fixture) {
|
||||||
fn := p.goSymTable.LookupFunc("main.sleepytime")
|
fn := p.goSymTable.LookupFunc("main.sleepytime")
|
||||||
bp, err := p.Break(fn.Entry)
|
bp, err := p.Break(fn.Entry)
|
||||||
@ -216,7 +216,7 @@ func TestClearBreakPoint(t *testing.T) {
|
|||||||
t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
|
t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.BreakPoints) != 0 {
|
if len(p.Breakpoints) != 0 {
|
||||||
t.Fatal("Breakpoint not removed internally")
|
t.Fatal("Breakpoint not removed internally")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -248,10 +248,10 @@ func testnext(program string, testcases []nextTest, initialLocation string, t *t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.BreakPoints) != 0 {
|
if len(p.Breakpoints) != 0 {
|
||||||
t.Fatal("Not all breakpoints were cleaned up", len(p.BreakPoints))
|
t.Fatal("Not all breakpoints were cleaned up", len(p.Breakpoints))
|
||||||
}
|
}
|
||||||
for _, bp := range p.arch.HardwareBreakPoints() {
|
for _, bp := range p.arch.HardwareBreakpoints() {
|
||||||
if bp != nil {
|
if bp != nil {
|
||||||
t.Fatal("Not all breakpoints were cleaned up", bp.Addr)
|
t.Fatal("Not all breakpoints were cleaned up", bp.Addr)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
type ThreadContext struct {
|
type ThreadContext struct {
|
||||||
Id int
|
Id int
|
||||||
Status *sys.WaitStatus
|
Status *sys.WaitStatus
|
||||||
CurrentBreakpoint *BreakPoint
|
CurrentBreakpoint *Breakpoint
|
||||||
dbp *DebuggedProcess
|
dbp *DebuggedProcess
|
||||||
singleStepping bool
|
singleStepping bool
|
||||||
running bool
|
running bool
|
||||||
@ -44,7 +44,7 @@ func (thread *ThreadContext) Continue() error {
|
|||||||
|
|
||||||
// Check whether we are stopped at a breakpoint, and
|
// Check whether we are stopped at a breakpoint, and
|
||||||
// if so, single step over it before continuing.
|
// if so, single step over it before continuing.
|
||||||
if _, ok := thread.dbp.BreakPoints[pc]; ok {
|
if _, ok := thread.dbp.Breakpoints[pc]; ok {
|
||||||
if err := thread.Step(); err != nil {
|
if err := thread.Step(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func (thread *ThreadContext) Step() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bp, ok := thread.dbp.BreakPoints[pc]
|
bp, ok := thread.dbp.Breakpoints[pc]
|
||||||
if ok {
|
if ok {
|
||||||
// Clear the breakpoint so that we can continue execution.
|
// Clear the breakpoint so that we can continue execution.
|
||||||
_, err = thread.dbp.Clear(bp.Addr)
|
_, err = thread.dbp.Clear(bp.Addr)
|
||||||
@ -72,7 +72,7 @@ func (thread *ThreadContext) Step() (err error) {
|
|||||||
|
|
||||||
// Restore breakpoint now that we have passed it.
|
// Restore breakpoint now that we have passed it.
|
||||||
defer func() {
|
defer func() {
|
||||||
var nbp *BreakPoint
|
var nbp *Breakpoint
|
||||||
nbp, err = thread.dbp.Break(bp.Addr)
|
nbp, err = thread.dbp.Break(bp.Addr)
|
||||||
nbp.Temp = bp.Temp
|
nbp.Temp = bp.Temp
|
||||||
}()
|
}()
|
||||||
@ -86,17 +86,17 @@ func (thread *ThreadContext) Step() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set breakpoint using this thread.
|
// Set breakpoint using this thread.
|
||||||
func (thread *ThreadContext) Break(addr uint64) (*BreakPoint, error) {
|
func (thread *ThreadContext) Break(addr uint64) (*Breakpoint, error) {
|
||||||
return thread.dbp.setBreakpoint(thread.Id, addr, false)
|
return thread.dbp.setBreakpoint(thread.Id, addr, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set breakpoint using this thread.
|
// Set breakpoint using this thread.
|
||||||
func (thread *ThreadContext) TempBreak(addr uint64) (*BreakPoint, error) {
|
func (thread *ThreadContext) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||||
return thread.dbp.setBreakpoint(thread.Id, addr, true)
|
return thread.dbp.setBreakpoint(thread.Id, addr, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear breakpoint using this thread.
|
// Clear breakpoint using this thread.
|
||||||
func (thread *ThreadContext) Clear(addr uint64) (*BreakPoint, error) {
|
func (thread *ThreadContext) Clear(addr uint64) (*Breakpoint, error) {
|
||||||
return thread.dbp.clearBreakpoint(thread.Id, addr)
|
return thread.dbp.clearBreakpoint(thread.Id, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ func (thread *ThreadContext) setNextTempBreakpoints(curpc uint64, pcs []uint64)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, err := thread.dbp.TempBreak(pcs[i]); err != nil {
|
if _, err := thread.dbp.TempBreak(pcs[i]); err != nil {
|
||||||
if _, ok := err.(BreakPointExistsError); !ok {
|
if _, ok := err.(BreakpointExistsError); !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,18 @@ package api
|
|||||||
|
|
||||||
// DebuggerState represents the current context of the debugger.
|
// DebuggerState represents the current context of the debugger.
|
||||||
type DebuggerState struct {
|
type DebuggerState struct {
|
||||||
// BreakPoint is the current breakpoint at which the debugged process is
|
// Breakpoint is the current breakpoint at which the debugged process is
|
||||||
// suspended, and may be empty if the process is not suspended.
|
// suspended, and may be empty if the process is not suspended.
|
||||||
BreakPoint *BreakPoint `json:"breakPoint,omitempty"`
|
Breakpoint *Breakpoint `json:"breakPoint,omitempty"`
|
||||||
// CurrentThread is the currently selected debugger thread.
|
// CurrentThread is the currently selected debugger thread.
|
||||||
CurrentThread *Thread `json:"currentThread,omitempty"`
|
CurrentThread *Thread `json:"currentThread,omitempty"`
|
||||||
// Exited indicates whether the debugged process has exited.
|
// Exited indicates whether the debugged process has exited.
|
||||||
Exited bool `json:"exited"`
|
Exited bool `json:"exited"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BreakPoint addresses a location at which process execution may be
|
// Breakpoint addresses a location at which process execution may be
|
||||||
// suspended.
|
// suspended.
|
||||||
type BreakPoint struct {
|
type Breakpoint struct {
|
||||||
// ID is a unique identifier for the breakpoint.
|
// ID is a unique identifier for the breakpoint.
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
// Addr is the address of the breakpoint.
|
// Addr is the address of the breakpoint.
|
||||||
|
@ -24,14 +24,14 @@ type Client interface {
|
|||||||
// Halt suspends the process.
|
// Halt suspends the process.
|
||||||
Halt() (*api.DebuggerState, error)
|
Halt() (*api.DebuggerState, error)
|
||||||
|
|
||||||
// GetBreakPoint gets a breakpoint by ID.
|
// GetBreakpoint gets a breakpoint by ID.
|
||||||
GetBreakPoint(id int) (*api.BreakPoint, error)
|
GetBreakpoint(id int) (*api.Breakpoint, error)
|
||||||
// CreateBreakPoint creates a new breakpoint.
|
// CreateBreakpoint creates a new breakpoint.
|
||||||
CreateBreakPoint(*api.BreakPoint) (*api.BreakPoint, error)
|
CreateBreakpoint(*api.Breakpoint) (*api.Breakpoint, error)
|
||||||
// ListBreakPoints gets all breakpoints.
|
// ListBreakpoints gets all breakpoints.
|
||||||
ListBreakPoints() ([]*api.BreakPoint, error)
|
ListBreakpoints() ([]*api.Breakpoint, error)
|
||||||
// ClearBreakPoint deletes a breakpoint by ID.
|
// ClearBreakpoint deletes a breakpoint by ID.
|
||||||
ClearBreakPoint(id int) (*api.BreakPoint, error)
|
ClearBreakpoint(id int) (*api.Breakpoint, error)
|
||||||
|
|
||||||
// ListThreads lists all threads.
|
// ListThreads lists all threads.
|
||||||
ListThreads() ([]*api.Thread, error)
|
ListThreads() ([]*api.Thread, error)
|
||||||
|
@ -113,13 +113,13 @@ func (d *Debugger) Run() error {
|
|||||||
log.Print("debugger is stopping")
|
log.Print("debugger is stopping")
|
||||||
|
|
||||||
// Clear breakpoints
|
// Clear breakpoints
|
||||||
bps := []*proctl.BreakPoint{}
|
bps := []*proc.Breakpoint{}
|
||||||
for _, bp := range d.process.BreakPoints {
|
for _, bp := range d.process.Breakpoints {
|
||||||
if bp != nil {
|
if bp != nil {
|
||||||
bps = append(bps, bp)
|
bps = append(bps, bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, bp := range d.process.HardwareBreakPoints() {
|
for _, bp := range d.process.HardwareBreakpoints() {
|
||||||
if bp != nil {
|
if bp != nil {
|
||||||
bps = append(bps, bp)
|
bps = append(bps, bp)
|
||||||
}
|
}
|
||||||
@ -176,14 +176,14 @@ func (d *Debugger) State() (*api.DebuggerState, error) {
|
|||||||
thread = convertThread(th)
|
thread = convertThread(th)
|
||||||
}
|
}
|
||||||
|
|
||||||
var breakpoint *api.BreakPoint
|
var breakpoint *api.Breakpoint
|
||||||
bp := p.CurrentBreakpoint()
|
bp := p.CurrentBreakpoint()
|
||||||
if bp != nil {
|
if bp != nil {
|
||||||
breakpoint = convertBreakPoint(bp)
|
breakpoint = convertBreakpoint(bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
state = &api.DebuggerState{
|
state = &api.DebuggerState{
|
||||||
BreakPoint: breakpoint,
|
Breakpoint: breakpoint,
|
||||||
CurrentThread: thread,
|
CurrentThread: thread,
|
||||||
Exited: p.Exited(),
|
Exited: p.Exited(),
|
||||||
}
|
}
|
||||||
@ -193,9 +193,9 @@ func (d *Debugger) State() (*api.DebuggerState, error) {
|
|||||||
return state, err
|
return state, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Debugger) CreateBreakPoint(requestedBp *api.BreakPoint) (*api.BreakPoint, error) {
|
|
||||||
var createdBp *api.BreakPoint
|
|
||||||
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
|
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
|
||||||
|
func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) {
|
||||||
|
var createdBp *api.Breakpoint
|
||||||
var loc string
|
var loc string
|
||||||
switch {
|
switch {
|
||||||
case len(requestedBp.File) > 0:
|
case len(requestedBp.File) > 0:
|
||||||
@ -210,50 +210,50 @@ func (d *Debugger) CreateBreakPoint(requestedBp *api.BreakPoint) (*api.BreakPoin
|
|||||||
if breakError != nil {
|
if breakError != nil {
|
||||||
return breakError
|
return breakError
|
||||||
}
|
}
|
||||||
createdBp = convertBreakPoint(bp)
|
createdBp = convertBreakpoint(bp)
|
||||||
log.Printf("created breakpoint: %#v", createdBp)
|
log.Printf("created breakpoint: %#v", createdBp)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return createdBp, err
|
return createdBp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Debugger) ClearBreakPoint(requestedBp *api.BreakPoint) (*api.BreakPoint, error) {
|
func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint, error) {
|
||||||
var clearedBp *api.BreakPoint
|
var clearedBp *api.Breakpoint
|
||||||
err := d.withProcess(func(p *proctl.DebuggedProcess) error {
|
err := d.withProcess(func(p *proc.DebuggedProcess) error {
|
||||||
bp, err := p.Clear(requestedBp.Addr)
|
bp, err := p.Clear(requestedBp.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Can't clear breakpoint @%x: %s", requestedBp.Addr, err)
|
return fmt.Errorf("Can't clear breakpoint @%x: %s", requestedBp.Addr, err)
|
||||||
}
|
}
|
||||||
clearedBp = convertBreakPoint(bp)
|
clearedBp = convertBreakpoint(bp)
|
||||||
log.Printf("cleared breakpoint: %#v", clearedBp)
|
log.Printf("cleared breakpoint: %#v", clearedBp)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return clearedBp, err
|
return clearedBp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Debugger) BreakPoints() []*api.BreakPoint {
|
func (d *Debugger) Breakpoints() []*api.Breakpoint {
|
||||||
bps := []*api.BreakPoint{}
|
bps := []*api.Breakpoint{}
|
||||||
d.withProcess(func(p *proctl.DebuggedProcess) error {
|
d.withProcess(func(p *proc.DebuggedProcess) error {
|
||||||
for _, bp := range p.HardwareBreakPoints() {
|
for _, bp := range p.HardwareBreakpoints() {
|
||||||
if bp == nil {
|
if bp == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bps = append(bps, convertBreakPoint(bp))
|
bps = append(bps, convertBreakpoint(bp))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, bp := range p.BreakPoints {
|
for _, bp := range p.Breakpoints {
|
||||||
if bp.Temp {
|
if bp.Temp {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bps = append(bps, convertBreakPoint(bp))
|
bps = append(bps, convertBreakpoint(bp))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return bps
|
return bps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Debugger) FindBreakPoint(id int) *api.BreakPoint {
|
func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
|
||||||
for _, bp := range d.BreakPoints() {
|
for _, bp := range d.Breakpoints() {
|
||||||
if bp.ID == id {
|
if bp.ID == id {
|
||||||
return bp
|
return bp
|
||||||
}
|
}
|
||||||
@ -459,9 +459,9 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) {
|
|||||||
return goroutines, err
|
return goroutines, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertBreakPoint converts an internal breakpoint to an API BreakPoint.
|
// convertBreakpoint converts an internal breakpoint to an API Breakpoint.
|
||||||
func convertBreakPoint(bp *proctl.BreakPoint) *api.BreakPoint {
|
func convertBreakpoint(bp *proctl.Breakpoint) *api.Breakpoint {
|
||||||
return &api.BreakPoint{
|
return &api.Breakpoint{
|
||||||
ID: bp.ID,
|
ID: bp.ID,
|
||||||
FunctionName: bp.FunctionName,
|
FunctionName: bp.FunctionName,
|
||||||
File: bp.File,
|
File: bp.File,
|
||||||
|
@ -106,8 +106,8 @@ func (c *RESTClient) Halt() (*api.DebuggerState, error) {
|
|||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) GetBreakPoint(id int) (*api.BreakPoint, error) {
|
func (c *RESTClient) GetBreakpoint(id int) (*api.Breakpoint, error) {
|
||||||
var breakPoint *api.BreakPoint
|
var breakPoint *api.Breakpoint
|
||||||
err := c.doGET(fmt.Sprintf("/breakpoints/%d", id), &breakPoint)
|
err := c.doGET(fmt.Sprintf("/breakpoints/%d", id), &breakPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -115,17 +115,17 @@ func (c *RESTClient) GetBreakPoint(id int) (*api.BreakPoint, error) {
|
|||||||
return breakPoint, nil
|
return breakPoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) CreateBreakPoint(breakPoint *api.BreakPoint) (*api.BreakPoint, error) {
|
func (c *RESTClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) {
|
||||||
var newBreakPoint *api.BreakPoint
|
var newBreakpoint *api.Breakpoint
|
||||||
err := c.doPOST("/breakpoints", breakPoint, &newBreakPoint)
|
err := c.doPOST("/breakpoints", breakPoint, &newBreakpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newBreakPoint, nil
|
return newBreakpoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) ListBreakPoints() ([]*api.BreakPoint, error) {
|
func (c *RESTClient) ListBreakpoints() ([]*api.Breakpoint, error) {
|
||||||
var breakPoints []*api.BreakPoint
|
var breakPoints []*api.Breakpoint
|
||||||
err := c.doGET("/breakpoints", &breakPoints)
|
err := c.doGET("/breakpoints", &breakPoints)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -133,8 +133,8 @@ func (c *RESTClient) ListBreakPoints() ([]*api.BreakPoint, error) {
|
|||||||
return breakPoints, nil
|
return breakPoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) ClearBreakPoint(id int) (*api.BreakPoint, error) {
|
func (c *RESTClient) ClearBreakpoint(id int) (*api.Breakpoint, error) {
|
||||||
var breakPoint *api.BreakPoint
|
var breakPoint *api.Breakpoint
|
||||||
err := c.doDELETE(fmt.Sprintf("/breakpoints/%d", id), &breakPoint)
|
err := c.doDELETE(fmt.Sprintf("/breakpoints/%d", id), &breakPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -53,7 +53,7 @@ func TestClientServer_exit(t *testing.T) {
|
|||||||
|
|
||||||
func TestClientServer_step(t *testing.T) {
|
func TestClientServer_step(t *testing.T) {
|
||||||
withTestClient("testprog", t, func(c service.Client) {
|
withTestClient("testprog", t, func(c service.Client) {
|
||||||
_, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: "main.helloworld"})
|
_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ type nextTest struct {
|
|||||||
|
|
||||||
func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
|
func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
|
||||||
withTestClient("testnextprog", t, func(c service.Client) {
|
withTestClient("testnextprog", t, func(c service.Client) {
|
||||||
bp, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: initialLocation})
|
bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: initialLocation})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
|
|||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.ClearBreakPoint(bp.ID)
|
_, err = c.ClearBreakpoint(bp.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ func TestNextFunctionReturn(t *testing.T) {
|
|||||||
|
|
||||||
func TestClientServer_breakpointInMainThread(t *testing.T) {
|
func TestClientServer_breakpointInMainThread(t *testing.T) {
|
||||||
withTestClient("testprog", t, func(c service.Client) {
|
withTestClient("testprog", t, func(c service.Client) {
|
||||||
bp, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: "main.helloworld"})
|
bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ func TestClientServer_breakpointInMainThread(t *testing.T) {
|
|||||||
|
|
||||||
func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
|
func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
|
||||||
withTestClient("testthreads", t, func(c service.Client) {
|
withTestClient("testthreads", t, func(c service.Client) {
|
||||||
_, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: "main.anotherthread"})
|
_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.anotherthread"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
|
|||||||
|
|
||||||
func TestClientServer_breakAtNonexistentPoint(t *testing.T) {
|
func TestClientServer_breakAtNonexistentPoint(t *testing.T) {
|
||||||
withTestClient("testprog", t, func(c service.Client) {
|
withTestClient("testprog", t, func(c service.Client) {
|
||||||
_, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: "nowhere"})
|
_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "nowhere"})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Should not be able to break at non existent function")
|
t.Fatal("Should not be able to break at non existent function")
|
||||||
}
|
}
|
||||||
@ -201,17 +201,17 @@ func TestClientServer_breakAtNonexistentPoint(t *testing.T) {
|
|||||||
|
|
||||||
func TestClientServer_clearBreakpoint(t *testing.T) {
|
func TestClientServer_clearBreakpoint(t *testing.T) {
|
||||||
withTestClient("testprog", t, func(c service.Client) {
|
withTestClient("testprog", t, func(c service.Client) {
|
||||||
bp, err := c.CreateBreakPoint(&api.BreakPoint{FunctionName: "main.sleepytime"})
|
bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sleepytime"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bps, err := c.ListBreakPoints()
|
bps, err := c.ListBreakpoints()
|
||||||
if e, a := 1, len(bps); e != a {
|
if e, a := 1, len(bps); e != a {
|
||||||
t.Fatalf("Expected breakpoint count %d, got %d", e, a)
|
t.Fatalf("Expected breakpoint count %d, got %d", e, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted, err := c.ClearBreakPoint(bp.ID)
|
deleted, err := c.ClearBreakpoint(bp.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ func TestClientServer_clearBreakpoint(t *testing.T) {
|
|||||||
t.Fatalf("Expected deleted breakpoint ID %v, got %v", bp.ID, deleted.ID)
|
t.Fatalf("Expected deleted breakpoint ID %v, got %v", bp.ID, deleted.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
bps, err = c.ListBreakPoints()
|
bps, err = c.ListBreakpoints()
|
||||||
if e, a := 0, len(bps); e != a {
|
if e, a := 0, len(bps); e != a {
|
||||||
t.Fatalf("Expected breakpoint count %d, got %d", e, a)
|
t.Fatalf("Expected breakpoint count %d, got %d", e, a)
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ func TestClientServer_switchThread(t *testing.T) {
|
|||||||
t.Fatal("Expected error for invalid thread id")
|
t.Fatal("Expected error for invalid thread id")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.CreateBreakPoint(&api.BreakPoint{FunctionName: "main.main"})
|
_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ func TestClientServer_infoLocals(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = c.CreateBreakPoint(&api.BreakPoint{File: fp, Line: 23})
|
_, err = c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 23})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ func TestClientServer_infoArgs(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = c.CreateBreakPoint(&api.BreakPoint{File: fp, Line: 47})
|
_, err = c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 47})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -81,10 +81,10 @@ func (s *RESTServer) Run() error {
|
|||||||
Consumes(restful.MIME_JSON).
|
Consumes(restful.MIME_JSON).
|
||||||
Produces(restful.MIME_JSON).
|
Produces(restful.MIME_JSON).
|
||||||
Route(ws.GET("/state").To(s.getState)).
|
Route(ws.GET("/state").To(s.getState)).
|
||||||
Route(ws.GET("/breakpoints").To(s.listBreakPoints)).
|
Route(ws.GET("/breakpoints").To(s.listBreakpoints)).
|
||||||
Route(ws.GET("/breakpoints/{breakpoint-id}").To(s.getBreakPoint)).
|
Route(ws.GET("/breakpoints/{breakpoint-id}").To(s.getBreakpoint)).
|
||||||
Route(ws.POST("/breakpoints").To(s.createBreakPoint)).
|
Route(ws.POST("/breakpoints").To(s.createBreakpoint)).
|
||||||
Route(ws.DELETE("/breakpoints/{breakpoint-id}").To(s.clearBreakPoint)).
|
Route(ws.DELETE("/breakpoints/{breakpoint-id}").To(s.clearBreakpoint)).
|
||||||
Route(ws.GET("/threads").To(s.listThreads)).
|
Route(ws.GET("/threads").To(s.listThreads)).
|
||||||
Route(ws.GET("/threads/{thread-id}").To(s.getThread)).
|
Route(ws.GET("/threads/{thread-id}").To(s.getThread)).
|
||||||
Route(ws.GET("/threads/{thread-id}/vars").To(s.listThreadPackageVars)).
|
Route(ws.GET("/threads/{thread-id}/vars").To(s.listThreadPackageVars)).
|
||||||
@ -166,14 +166,14 @@ func (s *RESTServer) doCommand(request *restful.Request, response *restful.Respo
|
|||||||
response.WriteEntity(state)
|
response.WriteEntity(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RESTServer) getBreakPoint(request *restful.Request, response *restful.Response) {
|
func (s *RESTServer) getBreakpoint(request *restful.Request, response *restful.Response) {
|
||||||
id, err := strconv.Atoi(request.PathParameter("breakpoint-id"))
|
id, err := strconv.Atoi(request.PathParameter("breakpoint-id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(response, http.StatusBadRequest, "invalid breakpoint id")
|
writeError(response, http.StatusBadRequest, "invalid breakpoint id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
found := s.debugger.FindBreakPoint(id)
|
found := s.debugger.FindBreakpoint(id)
|
||||||
if found == nil {
|
if found == nil {
|
||||||
writeError(response, http.StatusNotFound, "breakpoint not found")
|
writeError(response, http.StatusNotFound, "breakpoint not found")
|
||||||
return
|
return
|
||||||
@ -182,12 +182,12 @@ func (s *RESTServer) getBreakPoint(request *restful.Request, response *restful.R
|
|||||||
response.WriteEntity(found)
|
response.WriteEntity(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RESTServer) listBreakPoints(request *restful.Request, response *restful.Response) {
|
func (s *RESTServer) listBreakpoints(request *restful.Request, response *restful.Response) {
|
||||||
response.WriteEntity(s.debugger.BreakPoints())
|
response.WriteEntity(s.debugger.Breakpoints())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RESTServer) createBreakPoint(request *restful.Request, response *restful.Response) {
|
func (s *RESTServer) createBreakpoint(request *restful.Request, response *restful.Response) {
|
||||||
incomingBp := new(api.BreakPoint)
|
incomingBp := new(api.Breakpoint)
|
||||||
err := request.ReadEntity(incomingBp)
|
err := request.ReadEntity(incomingBp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(response, http.StatusInternalServerError, err.Error())
|
writeError(response, http.StatusInternalServerError, err.Error())
|
||||||
@ -199,7 +199,7 @@ func (s *RESTServer) createBreakPoint(request *restful.Request, response *restfu
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
createdbp, err := s.debugger.CreateBreakPoint(incomingBp)
|
createdbp, err := s.debugger.CreateBreakpoint(incomingBp)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(response, http.StatusInternalServerError, err.Error())
|
writeError(response, http.StatusInternalServerError, err.Error())
|
||||||
@ -210,20 +210,20 @@ func (s *RESTServer) createBreakPoint(request *restful.Request, response *restfu
|
|||||||
response.WriteEntity(createdbp)
|
response.WriteEntity(createdbp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RESTServer) clearBreakPoint(request *restful.Request, response *restful.Response) {
|
func (s *RESTServer) clearBreakpoint(request *restful.Request, response *restful.Response) {
|
||||||
id, err := strconv.Atoi(request.PathParameter("breakpoint-id"))
|
id, err := strconv.Atoi(request.PathParameter("breakpoint-id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(response, http.StatusBadRequest, "invalid breakpoint id")
|
writeError(response, http.StatusBadRequest, "invalid breakpoint id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
found := s.debugger.FindBreakPoint(id)
|
found := s.debugger.FindBreakpoint(id)
|
||||||
if found == nil {
|
if found == nil {
|
||||||
writeError(response, http.StatusNotFound, "breakpoint not found")
|
writeError(response, http.StatusNotFound, "breakpoint not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted, err := s.debugger.ClearBreakPoint(found)
|
deleted, err := s.debugger.ClearBreakpoint(found)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(response, http.StatusInternalServerError, err.Error())
|
writeError(response, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -231,7 +231,7 @@ func clear(client service.Client, args ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bp, err := client.ClearBreakPoint(id)
|
bp, err := client.ClearBreakpoint(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -240,12 +240,12 @@ func clear(client service.Client, args ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func clearAll(client service.Client, args ...string) error {
|
func clearAll(client service.Client, args ...string) error {
|
||||||
breakPoints, err := client.ListBreakPoints()
|
breakPoints, err := client.ListBreakpoints()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, bp := range breakPoints {
|
for _, bp := range breakPoints {
|
||||||
_, err := client.ClearBreakPoint(bp.ID)
|
_, err := client.ClearBreakpoint(bp.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Couldn't delete breakpoint %d at %#v %s:%d: %s\n", bp.ID, bp.Addr, bp.File, bp.Line, err)
|
fmt.Printf("Couldn't delete breakpoint %d at %#v %s:%d: %s\n", bp.ID, bp.Addr, bp.File, bp.Line, err)
|
||||||
}
|
}
|
||||||
@ -254,14 +254,14 @@ func clearAll(client service.Client, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ById []*api.BreakPoint
|
type ById []*api.Breakpoint
|
||||||
|
|
||||||
func (a ById) Len() int { return len(a) }
|
func (a ById) Len() int { return len(a) }
|
||||||
func (a ById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a ById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a ById) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
func (a ById) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
||||||
|
|
||||||
func breakpoints(client service.Client, args ...string) error {
|
func breakpoints(client service.Client, args ...string) error {
|
||||||
breakPoints, err := client.ListBreakPoints()
|
breakPoints, err := client.ListBreakpoints()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ func breakpoint(client service.Client, args ...string) error {
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return fmt.Errorf("argument must be either a function name or <file:line>")
|
return fmt.Errorf("argument must be either a function name or <file:line>")
|
||||||
}
|
}
|
||||||
requestedBp := &api.BreakPoint{}
|
requestedBp := &api.Breakpoint{}
|
||||||
tokens := strings.Split(args[0], ":")
|
tokens := strings.Split(args[0], ":")
|
||||||
switch {
|
switch {
|
||||||
case len(tokens) == 1:
|
case len(tokens) == 1:
|
||||||
@ -294,7 +294,7 @@ func breakpoint(client service.Client, args ...string) error {
|
|||||||
return fmt.Errorf("invalid line reference")
|
return fmt.Errorf("invalid line reference")
|
||||||
}
|
}
|
||||||
|
|
||||||
bp, err := client.CreateBreakPoint(requestedBp)
|
bp, err := client.CreateBreakpoint(requestedBp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user