mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-01 03:42:59 +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:
		 Alessandro Arzilli
					Alessandro Arzilli
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						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,15 +508,19 @@ 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) | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user