mirror of
https://github.com/go-delve/delve.git
synced 2025-10-30 18:27:37 +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