diff --git a/pkg/dwarf/frame/entries.go b/pkg/dwarf/frame/entries.go index 75b3cdf3..61fcb0e5 100644 --- a/pkg/dwarf/frame/entries.go +++ b/pkg/dwarf/frame/entries.go @@ -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 diff --git a/pkg/dwarf/frame/table.go b/pkg/dwarf/frame/table.go index 628d7b36..6ee274f6 100644 --- a/pkg/dwarf/frame/table.go +++ b/pkg/dwarf/frame/table.go @@ -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) { diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index a3f4fba4..635e8bc8 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -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)