1
0
mirror of https://github.com/beego/bee.git synced 2025-06-21 15:10:19 +00:00

Use Delve v0.12.1 instead of master

This commit is contained in:
Faissal Elamraoui
2017-03-26 16:55:28 +02:00
parent abf3c41032
commit 4dd6983d3c
67 changed files with 448 additions and 925 deletions

View File

@ -0,0 +1,95 @@
package frame
import (
"encoding/binary"
"fmt"
"sort"
)
// 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
}
// Represents a Frame Descriptor Entry in the
// Dwarf .debug_frame section.
type FrameDescriptionEntry struct {
Length uint32
CIE *CommonInformationEntry
Instructions []byte
begin, end uint64
order binary.ByteOrder
}
// Returns whether or not the given address is within the
// bounds of this frame.
func (fde *FrameDescriptionEntry) Cover(addr uint64) bool {
if (addr - fde.begin) < fde.end {
return true
}
return false
}
// Address of first location for this frame.
func (fde *FrameDescriptionEntry) Begin() uint64 {
return fde.begin
}
// Address of last location for this frame.
func (fde *FrameDescriptionEntry) End() uint64 {
return fde.begin + fde.end
}
// Set up frame for the given PC.
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
return executeDwarfProgramUntilPC(fde, pc)
}
// Return the offset from the current SP that the return address is stored at.
func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) (frameOffset, returnAddressOffset int64) {
frame := fde.EstablishFrame(pc)
return frame.cfa.offset, frame.regs[fde.CIE.ReturnAddressRegister].offset
}
type FrameDescriptionEntries []*FrameDescriptionEntry
func NewFrameIndex() FrameDescriptionEntries {
return make(FrameDescriptionEntries, 0, 1000)
}
type NoFDEForPCError struct {
PC uint64
}
func (err *NoFDEForPCError) Error() string {
return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
}
// Returns the Frame Description Entry for the given PC.
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
idx := sort.Search(len(fdes), func(i int) bool {
if fdes[i].Cover(pc) {
return true
}
if fdes[i].LessThan(pc) {
return false
}
return true
})
if idx == len(fdes) {
return nil, &NoFDEForPCError{pc}
}
return fdes[idx], nil
}
func (frame *FrameDescriptionEntry) LessThan(pc uint64) bool {
return frame.End() <= pc
}

View File

@ -0,0 +1,164 @@
package frame
// Operation opcodes
const (
DW_OP_addr = 0x03
DW_OP_const1s = 0x09
)
const (
DW_OP_const2u = 0x0a
DW_OP_const2s = 0x0b
DW_OP_const4u = iota
DW_OP_const4s
DW_OP_const8u
DW_OP_const8s
DW_OP_constu
DW_OP_consts
DW_OP_dup
DW_OP_drop
DW_OP_over
DW_OP_pick
DW_OP_swap
DW_OP_rot
DW_OP_xderef
DW_OP_abs
DW_OP_and
DW_OP_div
DW_OP_minus
DW_OP_mod
DW_OP_mul
DW_OP_neg
DW_OP_not
DW_OP_or
DW_OP_plus
DW_OP_plus_uconst
DW_OP_shl
DW_OP_shr
DW_OP_shra
DW_OP_xor
DW_OP_skip
DW_OP_bra
DW_OP_eq
DW_OP_ge
DW_OP_gt
DW_OP_le
DW_OP_lt
DW_OP_ne
)
const (
DW_OP_lit0 = 0x30
DW_OP_lit1 = 0x31
DW_OP_lit2 = iota
DW_OP_lit3
DW_OP_lit4
DW_OP_lit5
DW_OP_lit6
DW_OP_lit7
DW_OP_lit8
DW_OP_lit9
DW_OP_lit10
DW_OP_lit11
DW_OP_lit12
DW_OP_lit13
DW_OP_lit14
DW_OP_lit15
DW_OP_lit16
DW_OP_lit17
DW_OP_lit18
DW_OP_lit19
DW_OP_lit20
DW_OP_lit21
DW_OP_lit22
DW_OP_lit23
DW_OP_lit24
DW_OP_lit25
DW_OP_lit26
DW_OP_lit27
DW_OP_lit28
DW_OP_lit29
DW_OP_lit30
DW_OP_lit31
DW_OP_reg0
DW_OP_reg1
DW_OP_reg2
DW_OP_reg3
DW_OP_reg4
DW_OP_reg5
DW_OP_reg6
DW_OP_reg7
DW_OP_reg8
DW_OP_reg9
DW_OP_reg10
DW_OP_reg11
DW_OP_reg12
DW_OP_reg13
DW_OP_reg14
DW_OP_reg15
DW_OP_reg16
DW_OP_reg17
DW_OP_reg18
DW_OP_reg19
DW_OP_reg20
DW_OP_reg21
DW_OP_reg22
DW_OP_reg23
DW_OP_reg24
DW_OP_reg25
DW_OP_reg26
DW_OP_reg27
DW_OP_reg28
DW_OP_reg29
DW_OP_reg30
DW_OP_reg31
DW_OP_breg0
DW_OP_breg1
DW_OP_breg2
DW_OP_breg3
DW_OP_breg4
DW_OP_breg5
DW_OP_breg6
DW_OP_breg7
DW_OP_breg8
DW_OP_breg9
DW_OP_breg10
DW_OP_breg11
DW_OP_breg12
DW_OP_breg13
DW_OP_breg14
DW_OP_breg15
DW_OP_breg16
DW_OP_breg17
DW_OP_breg18
DW_OP_breg19
DW_OP_breg20
DW_OP_breg21
DW_OP_breg22
DW_OP_breg23
DW_OP_breg24
DW_OP_breg25
DW_OP_breg26
DW_OP_breg27
DW_OP_breg28
DW_OP_breg29
DW_OP_breg30
DW_OP_breg31
DW_OP_regx
DW_OP_fbreg
DW_OP_bregx
DW_OP_piece
DW_OP_deref_size
DW_OP_xderef_size
DW_OP_nop
DW_OP_push_object_address
DW_OP_call2
DW_OP_call4
DW_OP_call_ref
DW_OP_form_tls_address
DW_OP_call_frame_cfa
DW_OP_bit_piece
DW_OP_lo_user = 0xe0
DW_OP_hi_user = 0xff
)

View File

@ -0,0 +1,125 @@
// Package frame contains data structures and
// related functions for parsing and searching
// through Dwarf .debug_frame data.
package frame
import (
"bytes"
"encoding/binary"
"github.com/derekparker/delve/dwarf/util"
)
type parsefunc func(*parseContext) parsefunc
type parseContext struct {
buf *bytes.Buffer
entries FrameDescriptionEntries
common *CommonInformationEntry
frame *FrameDescriptionEntry
length uint32
}
// 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, order binary.ByteOrder) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
pctx = &parseContext{buf: buf, entries: NewFrameIndex()}
)
for fn := parselength; buf.Len() != 0; {
fn = fn(pctx)
}
for i := range pctx.entries {
pctx.entries[i].order = order
}
return pctx.entries
}
func cieEntry(data []byte) bool {
return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff})
}
func parselength(ctx *parseContext) parsefunc {
var data = ctx.buf.Next(8)
ctx.length = binary.LittleEndian.Uint32(data[:4]) - 4 // take off the length of the CIE id / CIE pointer.
if cieEntry(data[4:]) {
ctx.common = &CommonInformationEntry{Length: ctx.length}
return parseCIE
}
ctx.frame = &FrameDescriptionEntry{Length: ctx.length, CIE: ctx.common}
return parseFDE
}
func parseFDE(ctx *parseContext) parsefunc {
r := ctx.buf.Next(int(ctx.length))
ctx.frame.begin = binary.LittleEndian.Uint64(r[:8])
ctx.frame.end = binary.LittleEndian.Uint64(r[8:16])
// Insert into the tree after setting address range begin
// otherwise compares won't work.
ctx.entries = append(ctx.entries, ctx.frame)
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
ctx.frame.Instructions = r[16:]
ctx.length = 0
return parselength
}
func parseCIE(ctx *parseContext) parsefunc {
data := ctx.buf.Next(int(ctx.length))
buf := bytes.NewBuffer(data)
// parse version
ctx.common.Version = data[0]
// parse augmentation
ctx.common.Augmentation, _ = util.ParseString(buf)
// parse code alignment factor
ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
// parse data alignment factor
ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
// parse return address register
ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
// parse initial instructions
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
ctx.common.InitialInstructions = buf.Bytes() //ctx.buf.Next(int(ctx.length))
ctx.length = 0
return parselength
}
// DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section
// Trick borrowed from "debug/dwarf".New()
func DwarfEndian(infoSec []byte) binary.ByteOrder {
if len(infoSec) < 6 {
return binary.BigEndian
}
x, y := infoSec[4], infoSec[5]
switch {
case x == 0 && y == 0:
return binary.BigEndian
case x == 0:
return binary.BigEndian
case y == 0:
return binary.LittleEndian
default:
return binary.BigEndian
}
}

View File

@ -0,0 +1,429 @@
package frame
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/derekparker/delve/dwarf/util"
)
type CurrentFrameAddress struct {
register uint64
offset int64
expression []byte
rule byte
}
type DWRule struct {
rule byte
offset int64
newreg uint64
expression []byte
}
type FrameContext struct {
loc uint64
order binary.ByteOrder
address uint64
cfa CurrentFrameAddress
regs map[uint64]DWRule
initialRegs map[uint64]DWRule
prevRegs map[uint64]DWRule
buf *bytes.Buffer
cie *CommonInformationEntry
codeAlignment uint64
dataAlignment int64
}
func (fctx *FrameContext) CFAOffset() int64 {
return fctx.cfa.offset
}
// Instructions used to recreate the table from the .debug_frame data.
const (
DW_CFA_nop = 0x0 // No ops
DW_CFA_set_loc = 0x01 // op1: address
DW_CFA_advance_loc1 = iota // op1: 1-bytes delta
DW_CFA_advance_loc2 // op1: 2-byte delta
DW_CFA_advance_loc4 // op1: 4-byte delta
DW_CFA_offset_extended // op1: ULEB128 register, op2: ULEB128 offset
DW_CFA_restore_extended // op1: ULEB128 register
DW_CFA_undefined // op1: ULEB128 register
DW_CFA_same_value // op1: ULEB128 register
DW_CFA_register // op1: ULEB128 register, op2: ULEB128 register
DW_CFA_remember_state // No ops
DW_CFA_restore_state // No ops
DW_CFA_def_cfa // op1: ULEB128 register, op2: ULEB128 offset
DW_CFA_def_cfa_register // op1: ULEB128 register
DW_CFA_def_cfa_offset // op1: ULEB128 offset
DW_CFA_def_cfa_expression // op1: BLOCK
DW_CFA_expression // op1: ULEB128 register, op2: BLOCK
DW_CFA_offset_extended_sf // op1: ULEB128 register, op2: SLEB128 BLOCK
DW_CFA_def_cfa_sf // op1: ULEB128 register, op2: SLEB128 offset
DW_CFA_def_cfa_offset_sf // op1: SLEB128 offset
DW_CFA_val_offset // op1: ULEB128, op2: ULEB128
DW_CFA_val_offset_sf // op1: ULEB128, op2: SLEB128
DW_CFA_val_expression // op1: ULEB128, op2: BLOCK
DW_CFA_lo_user = 0x1c // op1: BLOCK
DW_CFA_hi_user = 0x3f // op1: ULEB128 register, op2: BLOCK
DW_CFA_advance_loc = (0x1 << 6) // High 2 bits: 0x1, low 6: delta
DW_CFA_offset = (0x2 << 6) // High 2 bits: 0x2, low 6: register
DW_CFA_restore = (0x3 << 6) // High 2 bits: 0x3, low 6: register
)
// Rules defined for register values.
const (
rule_undefined = iota
rule_sameval
rule_offset
rule_valoffset
rule_register
rule_expression
rule_valexpression
rule_architectural
)
const low_6_offset = 0x3f
type instruction func(frame *FrameContext)
// // Mapping from DWARF opcode to function.
var fnlookup = map[byte]instruction{
DW_CFA_advance_loc: advanceloc,
DW_CFA_offset: offset,
DW_CFA_restore: restore,
DW_CFA_set_loc: setloc,
DW_CFA_advance_loc1: advanceloc1,
DW_CFA_advance_loc2: advanceloc2,
DW_CFA_advance_loc4: advanceloc4,
DW_CFA_offset_extended: offsetextended,
DW_CFA_restore_extended: restoreextended,
DW_CFA_undefined: undefined,
DW_CFA_same_value: samevalue,
DW_CFA_register: register,
DW_CFA_remember_state: rememberstate,
DW_CFA_restore_state: restorestate,
DW_CFA_def_cfa: defcfa,
DW_CFA_def_cfa_register: defcfaregister,
DW_CFA_def_cfa_offset: defcfaoffset,
DW_CFA_def_cfa_expression: defcfaexpression,
DW_CFA_expression: expression,
DW_CFA_offset_extended_sf: offsetextendedsf,
DW_CFA_def_cfa_sf: defcfasf,
DW_CFA_def_cfa_offset_sf: defcfaoffsetsf,
DW_CFA_val_offset: valoffset,
DW_CFA_val_offset_sf: valoffsetsf,
DW_CFA_val_expression: valexpression,
DW_CFA_lo_user: louser,
DW_CFA_hi_user: hiuser,
}
func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
initialInstructions := make([]byte, len(cie.InitialInstructions))
copy(initialInstructions, cie.InitialInstructions)
frame := &FrameContext{
cie: cie,
regs: make(map[uint64]DWRule),
initialRegs: make(map[uint64]DWRule),
prevRegs: make(map[uint64]DWRule),
codeAlignment: cie.CodeAlignmentFactor,
dataAlignment: cie.DataAlignmentFactor,
buf: bytes.NewBuffer(initialInstructions),
}
frame.ExecuteDwarfProgram()
return frame
}
// Unwind the stack to find the return address register.
func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext {
frame := executeCIEInstructions(fde.CIE)
frame.order = fde.order
frame.loc = fde.Begin()
frame.address = pc
fdeInstructions := make([]byte, len(fde.Instructions))
copy(fdeInstructions, fde.Instructions)
frame.ExecuteUntilPC(fdeInstructions)
return frame
}
func (frame *FrameContext) ExecuteDwarfProgram() {
for frame.buf.Len() > 0 {
executeDwarfInstruction(frame)
}
}
// Execute dwarf instructions.
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
frame.buf.Truncate(0)
frame.buf.Write(instructions)
// We only need to execute the instructions until
// ctx.loc > ctx.addess (which is the address we
// are currently at in the traced process).
for frame.address >= frame.loc && frame.buf.Len() > 0 {
executeDwarfInstruction(frame)
}
}
func executeDwarfInstruction(frame *FrameContext) {
instruction, err := frame.buf.ReadByte()
if err != nil {
panic("Could not read from instruction buffer")
}
if instruction == DW_CFA_nop {
return
}
fn := lookupFunc(instruction, frame.buf)
fn(frame)
}
func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
const high_2_bits = 0xc0
var restore bool
// Special case the 3 opcodes that have their argument encoded in the opcode itself.
switch instruction & high_2_bits {
case DW_CFA_advance_loc:
instruction = DW_CFA_advance_loc
restore = true
case DW_CFA_offset:
instruction = DW_CFA_offset
restore = true
case DW_CFA_restore:
instruction = DW_CFA_restore
restore = true
}
if restore {
// Restore the last byte as it actually contains the argument for the opcode.
err := buf.UnreadByte()
if err != nil {
panic("Could not unread byte")
}
}
fn, ok := fnlookup[instruction]
if !ok {
panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction))
}
return fn
}
func advanceloc(frame *FrameContext) {
b, err := frame.buf.ReadByte()
if err != nil {
panic("Could not read byte")
}
delta := b & low_6_offset
frame.loc += uint64(delta) * frame.codeAlignment
}
func advanceloc1(frame *FrameContext) {
delta, err := frame.buf.ReadByte()
if err != nil {
panic("Could not read byte")
}
frame.loc += uint64(delta) * frame.codeAlignment
}
func advanceloc2(frame *FrameContext) {
var delta uint16
binary.Read(frame.buf, frame.order, &delta)
frame.loc += uint64(delta) * frame.codeAlignment
}
func advanceloc4(frame *FrameContext) {
var delta uint32
binary.Read(frame.buf, frame.order, &delta)
frame.loc += uint64(delta) * frame.codeAlignment
}
func offset(frame *FrameContext) {
b, err := frame.buf.ReadByte()
if err != nil {
panic(err)
}
var (
reg = b & low_6_offset
offset, _ = util.DecodeULEB128(frame.buf)
)
frame.regs[uint64(reg)] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
}
func restore(frame *FrameContext) {
b, err := frame.buf.ReadByte()
if err != nil {
panic(err)
}
reg := uint64(b & low_6_offset)
oldrule, ok := frame.initialRegs[reg]
if ok {
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
} else {
frame.regs[reg] = DWRule{rule: rule_undefined}
}
}
func setloc(frame *FrameContext) {
var loc uint64
binary.Read(frame.buf, frame.order, &loc)
frame.loc = loc
}
func offsetextended(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeULEB128(frame.buf)
)
frame.regs[reg] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
}
func undefined(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg] = DWRule{rule: rule_undefined}
}
func samevalue(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg] = DWRule{rule: rule_sameval}
}
func register(frame *FrameContext) {
reg1, _ := util.DecodeULEB128(frame.buf)
reg2, _ := util.DecodeULEB128(frame.buf)
frame.regs[reg1] = DWRule{newreg: reg2, rule: rule_register}
}
func rememberstate(frame *FrameContext) {
frame.prevRegs = frame.regs
}
func restorestate(frame *FrameContext) {
frame.regs = frame.prevRegs
}
func restoreextended(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
oldrule, ok := frame.initialRegs[reg]
if ok {
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
} else {
frame.regs[reg] = DWRule{rule: rule_undefined}
}
}
func defcfa(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeULEB128(frame.buf)
frame.cfa.register = reg
frame.cfa.offset = int64(offset)
}
func defcfaregister(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.cfa.register = reg
}
func defcfaoffset(frame *FrameContext) {
offset, _ := util.DecodeULEB128(frame.buf)
frame.cfa.offset = int64(offset)
}
func defcfasf(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeSLEB128(frame.buf)
frame.cfa.register = reg
frame.cfa.offset = offset * frame.dataAlignment
}
func defcfaoffsetsf(frame *FrameContext) {
offset, _ := util.DecodeSLEB128(frame.buf)
offset *= frame.dataAlignment
frame.cfa.offset = offset
}
func defcfaexpression(frame *FrameContext) {
var (
l, _ = util.DecodeULEB128(frame.buf)
expr = frame.buf.Next(int(l))
)
frame.cfa.expression = expr
frame.cfa.rule = rule_expression
}
func expression(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
l, _ = util.DecodeULEB128(frame.buf)
expr = frame.buf.Next(int(l))
)
frame.regs[reg] = DWRule{rule: rule_expression, expression: expr}
}
func offsetextendedsf(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeSLEB128(frame.buf)
)
frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_offset}
}
func valoffset(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeULEB128(frame.buf)
)
frame.regs[reg] = DWRule{offset: int64(offset), rule: rule_valoffset}
}
func valoffsetsf(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeSLEB128(frame.buf)
)
frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_valoffset}
}
func valexpression(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
l, _ = util.DecodeULEB128(frame.buf)
expr = frame.buf.Next(int(l))
)
frame.regs[reg] = DWRule{rule: rule_valexpression, expression: expr}
}
func louser(frame *FrameContext) {
frame.buf.Next(1)
}
func hiuser(frame *FrameContext) {
frame.buf.Next(1)
}