mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-04 06:32:16 +08:00 
			
		
		
		
	pkg/proc: fix StepBreakpoint handling
StepBreakpoints are set on CALL instructions, when they are hit we disassemble the current instruction, figure out the destination address and set a breakpoint after the prologue of the called function. In order to disassemble the current instruction we disassemble the area of memory starting from PC and going to PC+15 (because 15 bytes is the maximum length of one instruction on AMD64). This means that we won't just disassemble one instruction but also a few instructions following it ending with one truncated instruction. This usually works fine but sometimes the disassembler will panic with an array out of bounds error when trying to disassemble a truncated instruction. To avoid this problem this commit changes the funciton disassemble to take one extra parameter, singleInstr, when singleInstr is set disassemble will quit after disassembling a single instruction.
This commit is contained in:
		
				
					committed by
					
						
						Alessandro Arzilli
					
				
			
			
				
	
			
			
			
						parent
						
							5f0f77f414
						
					
				
				
					commit
					bc86c662a6
				
			@ -27,7 +27,7 @@ func Disassemble(dbp Process, g *G, startPC, endPC uint64) ([]AsmInstruction, er
 | 
			
		||||
	if g == nil {
 | 
			
		||||
		ct := dbp.CurrentThread()
 | 
			
		||||
		regs, _ := ct.Registers(false)
 | 
			
		||||
		return disassemble(ct, regs, dbp.Breakpoints(), dbp.BinInfo(), startPC, endPC)
 | 
			
		||||
		return disassemble(ct, regs, dbp.Breakpoints(), dbp.BinInfo(), startPC, endPC, false)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var regs Registers
 | 
			
		||||
@ -37,10 +37,10 @@ func Disassemble(dbp Process, g *G, startPC, endPC uint64) ([]AsmInstruction, er
 | 
			
		||||
		regs, _ = g.Thread.Registers(false)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return disassemble(mem, regs, dbp.Breakpoints(), dbp.BinInfo(), startPC, endPC)
 | 
			
		||||
	return disassemble(mem, regs, dbp.Breakpoints(), dbp.BinInfo(), startPC, endPC, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startPC, endPC uint64) ([]AsmInstruction, error) {
 | 
			
		||||
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startPC, endPC uint64, singleInstr bool) ([]AsmInstruction, error) {
 | 
			
		||||
	mem := make([]byte, int(endPC-startPC))
 | 
			
		||||
	_, err := memrw.ReadMemory(mem, uintptr(startPC))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -77,6 +77,9 @@ func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *Breakpoint
 | 
			
		||||
			pc++
 | 
			
		||||
			mem = mem[1:]
 | 
			
		||||
		}
 | 
			
		||||
		if singleInstr {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -144,7 +144,7 @@ func FirstPCAfterPrologue(p Process, fn *Function, sameline bool) (uint64, error
 | 
			
		||||
	var mem MemoryReadWriter = p.CurrentThread()
 | 
			
		||||
	breakpoints := p.Breakpoints()
 | 
			
		||||
	bi := p.BinInfo()
 | 
			
		||||
	text, err := disassemble(mem, nil, breakpoints, bi, fn.Entry, fn.End)
 | 
			
		||||
	text, err := disassemble(mem, nil, breakpoints, bi, fn.Entry, fn.End, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fn.Entry, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -136,7 +136,7 @@ func Continue(dbp Process) error {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				pc := regs.PC()
 | 
			
		||||
				text, err := disassemble(curthread, regs, dbp.Breakpoints(), dbp.BinInfo(), pc, pc+maxInstructionLength)
 | 
			
		||||
				text, err := disassemble(curthread, regs, dbp.Breakpoints(), dbp.BinInfo(), pc, pc+maxInstructionLength, true)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@ -131,7 +131,7 @@ func next(dbp Process, stepInto bool) error {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	text, err := disassemble(thread, regs, dbp.Breakpoints(), dbp.BinInfo(), topframe.Current.Fn.Entry, topframe.Current.Fn.End)
 | 
			
		||||
	text, err := disassemble(thread, regs, dbp.Breakpoints(), dbp.BinInfo(), topframe.Current.Fn.Entry, topframe.Current.Fn.End, false)
 | 
			
		||||
	if err != nil && stepInto {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user