mirror of
https://github.com/go-delve/delve.git
synced 2025-11-01 12:01:35 +08:00
dwarf/frame: handle unknown opcodes more gracefully (#4037)
Instead of panic'ing on unknown opcodes (there are a few around which gdb handles) report an error and continue as if the FDE did not exist. Fixes #4035
This commit is contained in:
committed by
GitHub
parent
50a45f1b07
commit
26806dcaf3
@ -55,8 +55,12 @@ func (fde *FrameDescriptionEntry) Translate(delta uint64) {
|
||||
}
|
||||
|
||||
// EstablishFrame set up frame for the given PC.
|
||||
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
|
||||
return executeDwarfProgramUntilPC(fde, pc)
|
||||
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) (*FrameContext, error) {
|
||||
fctxt := executeDwarfProgramUntilPC(fde, pc)
|
||||
if fctxt.err != nil {
|
||||
return nil, fctxt.err
|
||||
}
|
||||
return fctxt, nil
|
||||
}
|
||||
|
||||
type FrameDescriptionEntries []*FrameDescriptionEntry
|
||||
|
||||
@ -30,6 +30,7 @@ type FrameContext struct {
|
||||
codeAlignment uint64
|
||||
dataAlignment int64
|
||||
rememberedState *stateStack
|
||||
err error
|
||||
}
|
||||
|
||||
type rowState struct {
|
||||
@ -179,7 +180,7 @@ func (frame *FrameContext) executeDwarfProgram() {
|
||||
}
|
||||
|
||||
// ExecuteUntilPC execute dwarf instructions.
|
||||
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
|
||||
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) error {
|
||||
frame.buf.Truncate(0)
|
||||
frame.buf.Write(instructions)
|
||||
|
||||
@ -189,9 +190,13 @@ func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
|
||||
for frame.address >= frame.loc && frame.buf.Len() > 0 {
|
||||
executeDwarfInstruction(frame)
|
||||
}
|
||||
return frame.err
|
||||
}
|
||||
|
||||
func executeDwarfInstruction(frame *FrameContext) {
|
||||
if frame.err != nil {
|
||||
return
|
||||
}
|
||||
instruction, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not read from instruction buffer")
|
||||
@ -203,6 +208,11 @@ func executeDwarfInstruction(frame *FrameContext) {
|
||||
|
||||
fn := lookupFunc(instruction, frame.buf)
|
||||
|
||||
if fn == nil {
|
||||
frame.err = fmt.Errorf("encountered an unexpected DWARF CFA opcode: %#v", instruction)
|
||||
return
|
||||
}
|
||||
|
||||
fn(frame)
|
||||
}
|
||||
|
||||
@ -233,12 +243,7 @@ func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
|
||||
}
|
||||
}
|
||||
|
||||
fn, ok := fnlookup[instruction]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction))
|
||||
}
|
||||
|
||||
return fn
|
||||
return fnlookup[instruction]
|
||||
}
|
||||
|
||||
func advanceloc(frame *FrameContext) {
|
||||
|
||||
@ -508,16 +508,20 @@ func (it *stackIterator) appendInlineCalls(callback func(Stackframe) bool, frame
|
||||
// it.regs.CFA; the caller has to eventually switch it.regs when the iterator
|
||||
// advances to the next frame.
|
||||
func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uint64, retaddr uint64) {
|
||||
logger := logflags.StackLogger()
|
||||
|
||||
fde, err := it.bi.frameEntries.FDEForPC(it.pc)
|
||||
var framectx *frame.FrameContext
|
||||
if _, nofde := err.(*frame.ErrNoFDEForPC); nofde {
|
||||
framectx = it.bi.Arch.fixFrameUnwindContext(nil, it.pc, it.bi)
|
||||
} else {
|
||||
framectx = it.bi.Arch.fixFrameUnwindContext(fde.EstablishFrame(it.pc), it.pc, it.bi)
|
||||
fctxt, err := fde.EstablishFrame(it.pc)
|
||||
if err != nil {
|
||||
logger.Errorf("Error executing Frame Debug Entry for PC %x: %v", it.pc, err)
|
||||
}
|
||||
framectx = it.bi.Arch.fixFrameUnwindContext(fctxt, it.pc, it.bi)
|
||||
}
|
||||
|
||||
logger := logflags.StackLogger()
|
||||
|
||||
logger.Debugf("advanceRegs at %#x", it.pc)
|
||||
|
||||
cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0)
|
||||
|
||||
Reference in New Issue
Block a user