mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	Use external red/black tree package
This commit is contained in:
		| @ -1,6 +1,10 @@ | |||||||
| package frame | package frame | ||||||
|  |  | ||||||
| import "fmt" | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	"github.com/derekparker/rbtree" | ||||||
|  | ) | ||||||
|  |  | ||||||
| // Represents a Common Information Entry in | // Represents a Common Information Entry in | ||||||
| // the Dwarf .debug_frame section. | // the Dwarf .debug_frame section. | ||||||
| @ -54,112 +58,40 @@ func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) int64 { | |||||||
| 	return frame.cfa.offset + frame.regs[fde.CIE.ReturnAddressRegister].offset | 	return frame.cfa.offset + frame.regs[fde.CIE.ReturnAddressRegister].offset | ||||||
| } | } | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	RED   = true |  | ||||||
| 	BLACK = false |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type FrameDescriptionEntries struct { | type FrameDescriptionEntries struct { | ||||||
| 	root *FrameNode | 	*rbtree.RedBlackTree | ||||||
| } |  | ||||||
|  |  | ||||||
| type FrameNode struct { |  | ||||||
| 	entry       *FrameDescriptionEntry |  | ||||||
| 	left, right *FrameNode |  | ||||||
| 	color       bool |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewFrameIndex() *FrameDescriptionEntries { | func NewFrameIndex() *FrameDescriptionEntries { | ||||||
| 	return &FrameDescriptionEntries{} | 	return &FrameDescriptionEntries{rbtree.New()} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (fs *FrameDescriptionEntries) Find(pc uint64) (*FrameDescriptionEntry, bool) { | func (fdes *FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) { | ||||||
| 	return find(fs.root, pc) | 	node, ok := fdes.Find(Addr(pc)) | ||||||
| } |  | ||||||
|  |  | ||||||
| func find(fn *FrameNode, pc uint64) (*FrameDescriptionEntry, bool) { |  | ||||||
| 	switch { |  | ||||||
| 	case fn == nil: |  | ||||||
| 		return nil, false |  | ||||||
| 	case fn.entry.AddressRange.Cover(pc): |  | ||||||
| 		return fn.entry, true |  | ||||||
| 	case pc < fn.entry.AddressRange.begin: |  | ||||||
| 		return find(fn.left, pc) |  | ||||||
| 	case pc > fn.entry.AddressRange.begin+fn.entry.AddressRange.end: |  | ||||||
| 		return find(fn.right, pc) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return nil, false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (fs *FrameDescriptionEntries) Put(entry *FrameDescriptionEntry) { |  | ||||||
| 	fs.root = put(fs.root, entry) |  | ||||||
| 	fs.root.color = BLACK |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func put(fn *FrameNode, entry *FrameDescriptionEntry) *FrameNode { |  | ||||||
| 	switch { |  | ||||||
| 	case fn == nil: |  | ||||||
| 		return &FrameNode{entry: entry, color: RED} |  | ||||||
| 	case entry.AddressRange.begin < fn.entry.AddressRange.begin: |  | ||||||
| 		fn.left = put(fn.left, entry) |  | ||||||
| 	case entry.AddressRange.begin > fn.entry.AddressRange.begin: |  | ||||||
| 		fn.right = put(fn.right, entry) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	leftRed := isRed(fn.left) |  | ||||||
| 	rightRed := isRed(fn.right) |  | ||||||
|  |  | ||||||
| 	if !leftRed && rightRed { |  | ||||||
| 		fn = rotateLeft(fn) |  | ||||||
| 	} else if leftRed && isRed(fn.left.left) { |  | ||||||
| 		fn = rotateRight(fn) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if leftRed && rightRed { |  | ||||||
| 		fn.left.color = BLACK |  | ||||||
| 		fn.right.color = BLACK |  | ||||||
| 		fn.color = RED |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return fn |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func isRed(fn *FrameNode) bool { |  | ||||||
| 	if fn == nil { |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return fn.color |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func rotateLeft(fn *FrameNode) *FrameNode { |  | ||||||
| 	x := fn.right |  | ||||||
| 	fn.right = x.left |  | ||||||
| 	x.left = fn |  | ||||||
|  |  | ||||||
| 	x.color = fn.color |  | ||||||
| 	fn.color = RED |  | ||||||
|  |  | ||||||
| 	return x |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func rotateRight(fn *FrameNode) *FrameNode { |  | ||||||
| 	x := fn.left |  | ||||||
| 	fn.left = x.right |  | ||||||
| 	x.right = fn |  | ||||||
|  |  | ||||||
| 	x.color = fn.color |  | ||||||
| 	fn.color = RED |  | ||||||
|  |  | ||||||
| 	return x |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) { |  | ||||||
| 	fde, ok := fdes.Find(pc) |  | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return nil, fmt.Errorf("Could not find FDE for %#v", pc) | 		return nil, fmt.Errorf("Could not find FDE for %#v", pc) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return fde, nil | 	return node.(*FrameDescriptionEntry), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (frame *FrameDescriptionEntry) Less(item rbtree.Item) bool { | ||||||
|  | 	return frame.AddressRange.begin < item.(*FrameDescriptionEntry).AddressRange.begin | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (frame *FrameDescriptionEntry) More(item rbtree.Item) bool { | ||||||
|  | 	r := item.(*FrameDescriptionEntry).AddressRange | ||||||
|  | 	fnr := frame.AddressRange | ||||||
|  | 	return fnr.begin+fnr.end > r.begin+r.end | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Addr uint64 | ||||||
|  |  | ||||||
|  | func (a Addr) Less(item rbtree.Item) bool { | ||||||
|  | 	return uint64(a) < item.(*FrameDescriptionEntry).AddressRange.begin | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (a Addr) More(item rbtree.Item) bool { | ||||||
|  | 	r := item.(*FrameDescriptionEntry).AddressRange | ||||||
|  | 	return uint64(a) > r.begin+r.end | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,12 +19,12 @@ func TestFDEForPC(t *testing.T) { | |||||||
| 	tree.Put(fde3) | 	tree.Put(fde3) | ||||||
| 	tree.Put(fde4) | 	tree.Put(fde4) | ||||||
|  |  | ||||||
| 	fde, ok := tree.Find(35) | 	node, ok := tree.Find(Addr(35)) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		t.Fatal("Could not find FDE") | 		t.Fatal("Could not find FDE") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if fde != fde3 { | 	if node != fde3 { | ||||||
| 		t.Fatal("Got incorrect fde") | 		t.Fatal("Got incorrect fde") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ type parsefunc func(*parseContext) parsefunc | |||||||
|  |  | ||||||
| type parseContext struct { | type parseContext struct { | ||||||
| 	Buf     *bytes.Buffer | 	Buf     *bytes.Buffer | ||||||
| 	Entries FrameDescriptionEntries | 	Entries *FrameDescriptionEntries | ||||||
| 	Common  *CommonInformationEntry | 	Common  *CommonInformationEntry | ||||||
| 	Frame   *FrameDescriptionEntry | 	Frame   *FrameDescriptionEntry | ||||||
| 	Length  uint32 | 	Length  uint32 | ||||||
| @ -23,10 +23,10 @@ type parseContext struct { | |||||||
| // Parse takes in data (a byte slice) and returns a slice of | // Parse takes in data (a byte slice) and returns a slice of | ||||||
| // CommonInformationEntry structures. Each CommonInformationEntry | // CommonInformationEntry structures. Each CommonInformationEntry | ||||||
| // has a slice of FrameDescriptionEntry structures. | // has a slice of FrameDescriptionEntry structures. | ||||||
| func Parse(data []byte) FrameDescriptionEntries { | func Parse(data []byte) *FrameDescriptionEntries { | ||||||
| 	var ( | 	var ( | ||||||
| 		buf  = bytes.NewBuffer(data) | 		buf  = bytes.NewBuffer(data) | ||||||
| 		pctx = &parseContext{Buf: buf} | 		pctx = &parseContext{Buf: buf, Entries: NewFrameIndex()} | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	for fn := parseLength; buf.Len() != 0; { | 	for fn := parseLength; buf.Len() != 0; { | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ type DebuggedProcess struct { | |||||||
| 	Executable      *elf.File | 	Executable      *elf.File | ||||||
| 	Symbols         []elf.Symbol | 	Symbols         []elf.Symbol | ||||||
| 	GoSymTable      *gosym.Table | 	GoSymTable      *gosym.Table | ||||||
| 	FrameEntries    frame.FrameDescriptionEntries | 	FrameEntries    *frame.FrameDescriptionEntries | ||||||
| 	DebugLine       *line.DebugLineInfo | 	DebugLine       *line.DebugLineInfo | ||||||
| 	BreakPoints     map[string]*BreakPoint | 	BreakPoints     map[string]*BreakPoint | ||||||
| 	TempBreakPoints map[uint64]*BreakPoint | 	TempBreakPoints map[uint64]*BreakPoint | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker