mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 17:56:45 +08:00
Use external red/black tree package
This commit is contained in:
@ -1,6 +1,10 @@
|
||||
package frame
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/derekparker/rbtree"
|
||||
)
|
||||
|
||||
// Represents a Common Information Entry in
|
||||
// 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
|
||||
}
|
||||
|
||||
const (
|
||||
RED = true
|
||||
BLACK = false
|
||||
)
|
||||
|
||||
type FrameDescriptionEntries struct {
|
||||
root *FrameNode
|
||||
}
|
||||
|
||||
type FrameNode struct {
|
||||
entry *FrameDescriptionEntry
|
||||
left, right *FrameNode
|
||||
color bool
|
||||
*rbtree.RedBlackTree
|
||||
}
|
||||
|
||||
func NewFrameIndex() *FrameDescriptionEntries {
|
||||
return &FrameDescriptionEntries{}
|
||||
return &FrameDescriptionEntries{rbtree.New()}
|
||||
}
|
||||
|
||||
func (fs *FrameDescriptionEntries) Find(pc uint64) (*FrameDescriptionEntry, bool) {
|
||||
return find(fs.root, 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)
|
||||
func (fdes *FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
|
||||
node, ok := fdes.Find(Addr(pc))
|
||||
if !ok {
|
||||
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(fde4)
|
||||
|
||||
fde, ok := tree.Find(35)
|
||||
node, ok := tree.Find(Addr(35))
|
||||
if !ok {
|
||||
t.Fatal("Could not find FDE")
|
||||
}
|
||||
|
||||
if fde != fde3 {
|
||||
if node != fde3 {
|
||||
t.Fatal("Got incorrect fde")
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ type parsefunc func(*parseContext) parsefunc
|
||||
|
||||
type parseContext struct {
|
||||
Buf *bytes.Buffer
|
||||
Entries FrameDescriptionEntries
|
||||
Entries *FrameDescriptionEntries
|
||||
Common *CommonInformationEntry
|
||||
Frame *FrameDescriptionEntry
|
||||
Length uint32
|
||||
@ -23,10 +23,10 @@ type parseContext struct {
|
||||
// Parse takes in data (a byte slice) and returns a slice of
|
||||
// CommonInformationEntry structures. Each CommonInformationEntry
|
||||
// has a slice of FrameDescriptionEntry structures.
|
||||
func Parse(data []byte) FrameDescriptionEntries {
|
||||
func Parse(data []byte) *FrameDescriptionEntries {
|
||||
var (
|
||||
buf = bytes.NewBuffer(data)
|
||||
pctx = &parseContext{Buf: buf}
|
||||
pctx = &parseContext{Buf: buf, Entries: NewFrameIndex()}
|
||||
)
|
||||
|
||||
for fn := parseLength; buf.Len() != 0; {
|
||||
|
||||
@ -30,7 +30,7 @@ type DebuggedProcess struct {
|
||||
Executable *elf.File
|
||||
Symbols []elf.Symbol
|
||||
GoSymTable *gosym.Table
|
||||
FrameEntries frame.FrameDescriptionEntries
|
||||
FrameEntries *frame.FrameDescriptionEntries
|
||||
DebugLine *line.DebugLineInfo
|
||||
BreakPoints map[string]*BreakPoint
|
||||
TempBreakPoints map[uint64]*BreakPoint
|
||||
|
||||
Reference in New Issue
Block a user