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.
|
// EstablishFrame set up frame for the given PC.
|
||||||
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
|
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) (*FrameContext, error) {
|
||||||
return executeDwarfProgramUntilPC(fde, pc)
|
fctxt := executeDwarfProgramUntilPC(fde, pc)
|
||||||
|
if fctxt.err != nil {
|
||||||
|
return nil, fctxt.err
|
||||||
|
}
|
||||||
|
return fctxt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type FrameDescriptionEntries []*FrameDescriptionEntry
|
type FrameDescriptionEntries []*FrameDescriptionEntry
|
||||||
|
|||||||
@ -30,6 +30,7 @@ type FrameContext struct {
|
|||||||
codeAlignment uint64
|
codeAlignment uint64
|
||||||
dataAlignment int64
|
dataAlignment int64
|
||||||
rememberedState *stateStack
|
rememberedState *stateStack
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
type rowState struct {
|
type rowState struct {
|
||||||
@ -179,7 +180,7 @@ func (frame *FrameContext) executeDwarfProgram() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteUntilPC execute dwarf instructions.
|
// ExecuteUntilPC execute dwarf instructions.
|
||||||
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
|
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) error {
|
||||||
frame.buf.Truncate(0)
|
frame.buf.Truncate(0)
|
||||||
frame.buf.Write(instructions)
|
frame.buf.Write(instructions)
|
||||||
|
|
||||||
@ -189,9 +190,13 @@ func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
|
|||||||
for frame.address >= frame.loc && frame.buf.Len() > 0 {
|
for frame.address >= frame.loc && frame.buf.Len() > 0 {
|
||||||
executeDwarfInstruction(frame)
|
executeDwarfInstruction(frame)
|
||||||
}
|
}
|
||||||
|
return frame.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeDwarfInstruction(frame *FrameContext) {
|
func executeDwarfInstruction(frame *FrameContext) {
|
||||||
|
if frame.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
instruction, err := frame.buf.ReadByte()
|
instruction, err := frame.buf.ReadByte()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not read from instruction buffer")
|
panic("Could not read from instruction buffer")
|
||||||
@ -203,6 +208,11 @@ func executeDwarfInstruction(frame *FrameContext) {
|
|||||||
|
|
||||||
fn := lookupFunc(instruction, frame.buf)
|
fn := lookupFunc(instruction, frame.buf)
|
||||||
|
|
||||||
|
if fn == nil {
|
||||||
|
frame.err = fmt.Errorf("encountered an unexpected DWARF CFA opcode: %#v", instruction)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
fn(frame)
|
fn(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,12 +243,7 @@ func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn, ok := fnlookup[instruction]
|
return fnlookup[instruction]
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction))
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func advanceloc(frame *FrameContext) {
|
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
|
// it.regs.CFA; the caller has to eventually switch it.regs when the iterator
|
||||||
// advances to the next frame.
|
// advances to the next frame.
|
||||||
func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uint64, retaddr uint64) {
|
func (it *stackIterator) advanceRegs() (callFrameRegs op.DwarfRegisters, ret uint64, retaddr uint64) {
|
||||||
|
logger := logflags.StackLogger()
|
||||||
|
|
||||||
fde, err := it.bi.frameEntries.FDEForPC(it.pc)
|
fde, err := it.bi.frameEntries.FDEForPC(it.pc)
|
||||||
var framectx *frame.FrameContext
|
var framectx *frame.FrameContext
|
||||||
if _, nofde := err.(*frame.ErrNoFDEForPC); nofde {
|
if _, nofde := err.(*frame.ErrNoFDEForPC); nofde {
|
||||||
framectx = it.bi.Arch.fixFrameUnwindContext(nil, it.pc, it.bi)
|
framectx = it.bi.Arch.fixFrameUnwindContext(nil, it.pc, it.bi)
|
||||||
} else {
|
} 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)
|
logger.Debugf("advanceRegs at %#x", it.pc)
|
||||||
|
|
||||||
cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0)
|
cfareg, err := it.executeFrameRegRule(0, framectx.CFA, 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user