delve/dwarf/frame/frame_entries.go

166 lines
3.2 KiB
Go
Raw Normal View History

package frame
import "fmt"
// Represents a Common Information Entry in
// the Dwarf .debug_frame section.
type CommonInformationEntry struct {
Length uint32
CIE_id uint32
Version uint8
Augmentation string
CodeAlignmentFactor uint64
DataAlignmentFactor int64
ReturnAddressRegister uint64
InitialInstructions []byte
}
2014-06-29 16:52:30 +00:00
type addrange struct {
begin, end uint64
}
func (r *addrange) Begin() uint64 {
return r.begin
}
func (r *addrange) End() uint64 {
return r.end
}
2014-06-29 16:52:30 +00:00
func (r *addrange) Cover(addr uint64) bool {
if (addr - r.begin) < r.end {
return true
}
return false
}
// Represents a Frame Descriptor Entry in the
// Dwarf .debug_frame section.
type FrameDescriptionEntry struct {
Length uint32
CIE *CommonInformationEntry
AddressRange *addrange
Instructions []byte
}
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
return executeDwarfProgramUntilPC(fde, pc)
}
2014-06-29 16:52:30 +00:00
func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) int64 {
frame := fde.EstablishFrame(pc)
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
}
func NewFrameIndex() *FrameDescriptionEntries {
return &FrameDescriptionEntries{}
}
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
}
2014-06-29 16:52:30 +00:00
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
fde, ok := fdes.Find(pc)
if !ok {
return nil, fmt.Errorf("Could not find FDE for %#v", pc)
}
return fde, nil
}