Use external red/black tree package

This commit is contained in:
Derek Parker
2014-08-07 11:03:42 -05:00
parent d977810626
commit 0af47b64ce
4 changed files with 37 additions and 105 deletions

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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; {

View File

@ -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