1
0
mirror of https://github.com/beego/bee.git synced 2025-07-01 17:20:17 +00:00

Updated vendor

This commit is contained in:
Ruben Cid
2019-04-15 16:43:01 +02:00
parent 33dd897647
commit da91d50ab8
134 changed files with 4988 additions and 2530 deletions

View File

@ -0,0 +1,77 @@
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
staticBase uint64
}
// Represents a Frame Descriptor Entry in the
// Dwarf .debug_frame section.
type FrameDescriptionEntry struct {
Length uint32
CIE *CommonInformationEntry
Instructions []byte
begin, size 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 {
return (addr - fde.begin) < fde.size
}
// 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.size
}
// Set up frame for the given PC.
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
return executeDwarfProgramUntilPC(fde, pc)
}
type FrameDescriptionEntries []*FrameDescriptionEntry
func NewFrameIndex() FrameDescriptionEntries {
return make(FrameDescriptionEntries, 0, 1000)
}
type ErrNoFDEForPC struct {
PC uint64
}
func (err *ErrNoFDEForPC) 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 {
return fdes[i].Cover(pc) || fdes[i].Begin() >= pc
})
if idx == len(fdes) || !fdes[idx].Cover(pc) {
return nil, &ErrNoFDEForPC{pc}
}
return fdes[idx], nil
}

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,134 @@
// 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/go-delve/delve/pkg/dwarf/util"
)
type parsefunc func(*parseContext) parsefunc
type parseContext struct {
staticBase uint64
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, staticBase uint64) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
pctx = &parseContext{buf: buf, entries: NewFrameIndex(), staticBase: staticBase}
)
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 {
binary.Read(ctx.buf, binary.LittleEndian, &ctx.length)
if ctx.length == 0 {
// ZERO terminator
return parselength
}
var data = ctx.buf.Next(4)
ctx.length -= 4 // take off the length of the CIE id / CIE pointer.
if cieEntry(data) {
ctx.common = &CommonInformationEntry{Length: ctx.length, staticBase: ctx.staticBase}
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.staticBase
ctx.frame.size = 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,424 @@
package frame
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/go-delve/delve/pkg/dwarf/util"
)
type DWRule struct {
Rule Rule
Offset int64
Reg uint64
Expression []byte
}
type FrameContext struct {
loc uint64
order binary.ByteOrder
address uint64
CFA DWRule
Regs map[uint64]DWRule
initialRegs map[uint64]DWRule
prevRegs map[uint64]DWRule
buf *bytes.Buffer
cie *CommonInformationEntry
RetAddrReg uint64
codeAlignment uint64
dataAlignment int64
}
// 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.
type Rule byte
const (
RuleUndefined Rule = iota
RuleSameVal
RuleOffset
RuleValOffset
RuleRegister
RuleExpression
RuleValExpression
RuleArchitectural
RuleCFA // Value is rule.Reg + rule.Offset
RuleFramePointer // Value is stored at address rule.Reg + rule.Offset, but only if it's less than the current CFA, otherwise same value
)
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),
RetAddrReg: cie.ReturnAddressRegister,
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
frame.ExecuteUntilPC(fde.Instructions)
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.address (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: RuleOffset}
}
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: RuleOffset}
} else {
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
}
func setloc(frame *FrameContext) {
var loc uint64
binary.Read(frame.buf, frame.order, &loc)
frame.loc = loc + frame.cie.staticBase
}
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: RuleOffset}
}
func undefined(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
func samevalue(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.Regs[reg] = DWRule{Rule: RuleSameVal}
}
func register(frame *FrameContext) {
reg1, _ := util.DecodeULEB128(frame.buf)
reg2, _ := util.DecodeULEB128(frame.buf)
frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
}
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: RuleOffset}
} else {
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
}
func defcfa(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeULEB128(frame.buf)
frame.CFA.Rule = RuleCFA
frame.CFA.Reg = reg
frame.CFA.Offset = int64(offset)
}
func defcfaregister(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
frame.CFA.Reg = 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.Rule = RuleCFA
frame.CFA.Reg = 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 = RuleExpression
}
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: RuleExpression, 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: RuleOffset}
}
func valoffset(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeULEB128(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
}
func valoffsetsf(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeSLEB128(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
}
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: RuleValExpression, Expression: expr}
}
func louser(frame *FrameContext) {
frame.buf.Next(1)
}
func hiuser(frame *FrameContext) {
frame.buf.Next(1)
}

View File

@ -0,0 +1,107 @@
package godwarf
import (
"bytes"
"compress/zlib"
"debug/elf"
"debug/macho"
"debug/pe"
"encoding/binary"
"fmt"
"io"
)
// GetDebugSectionElf returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionElf("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionElf(f *elf.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
// GetDebugSectionPE returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionPE("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionPE(f *pe.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return peSectionData(sec)
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := peSectionData(sec)
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
func peSectionData(sec *pe.Section) ([]byte, error) {
b, err := sec.Data()
if err != nil {
return nil, err
}
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
b = b[:sec.VirtualSize]
}
return b, nil
}
// GetDebugSectionMacho returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionMacho("line") will return the contents of
// __debug_line, if __debug_line doesn't exist it will try to return the
// decompressed contents of __zdebug_line.
func GetDebugSectionMacho(f *macho.File, name string) ([]byte, error) {
sec := f.Section("__debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section("__zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
func decompressMaybe(b []byte) ([]byte, error) {
if len(b) < 12 || string(b[:4]) != "ZLIB" {
// not compressed
return b, nil
}
dlen := binary.BigEndian.Uint64(b[4:12])
dbuf := make([]byte, dlen)
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
if err != nil {
return nil, err
}
if _, err := io.ReadFull(r, dbuf); err != nil {
return nil, err
}
if err := r.Close(); err != nil {
return nil, err
}
return dbuf, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
package line
import (
"bytes"
"encoding/binary"
"path/filepath"
"github.com/go-delve/delve/pkg/dwarf/util"
)
type DebugLinePrologue struct {
UnitLength uint32
Version uint16
Length uint32
MinInstrLength uint8
InitialIsStmt uint8
LineBase int8
LineRange uint8
OpcodeBase uint8
StdOpLengths []uint8
}
type DebugLineInfo struct {
Prologue *DebugLinePrologue
IncludeDirs []string
FileNames []*FileEntry
Instructions []byte
Lookup map[string]*FileEntry
Logf func(string, ...interface{})
// stateMachineCache[pc] is a state machine stopped at pc
stateMachineCache map[uint64]*StateMachine
// lastMachineCache[pc] is a state machine stopped at an address after pc
lastMachineCache map[uint64]*StateMachine
// staticBase is the address at which the executable is loaded, 0 for non-PIEs
staticBase uint64
}
type FileEntry struct {
Path string
DirIdx uint64
LastModTime uint64
Length uint64
}
type DebugLines []*DebugLineInfo
// ParseAll parses all debug_line segments found in data
func ParseAll(data []byte, logfn func(string, ...interface{}), staticBase uint64) DebugLines {
var (
lines = make(DebugLines, 0)
buf = bytes.NewBuffer(data)
)
// We have to parse multiple file name tables here.
for buf.Len() > 0 {
lines = append(lines, Parse("", buf, logfn, staticBase))
}
return lines
}
// Parse parses a single debug_line segment from buf. Compdir is the
// DW_AT_comp_dir attribute of the associated compile unit.
func Parse(compdir string, buf *bytes.Buffer, logfn func(string, ...interface{}), staticBase uint64) *DebugLineInfo {
dbl := new(DebugLineInfo)
dbl.Logf = logfn
dbl.staticBase = staticBase
dbl.Lookup = make(map[string]*FileEntry)
if compdir != "" {
dbl.IncludeDirs = append(dbl.IncludeDirs, compdir)
}
dbl.stateMachineCache = make(map[uint64]*StateMachine)
dbl.lastMachineCache = make(map[uint64]*StateMachine)
parseDebugLinePrologue(dbl, buf)
parseIncludeDirs(dbl, buf)
parseFileEntries(dbl, buf)
// Instructions size calculation breakdown:
// - dbl.Prologue.UnitLength is the length of the entire unit, not including the 4 bytes to represent that length.
// - dbl.Prologue.Length is the length of the prologue not including unit length, version or prologue length itself.
// - So you have UnitLength - PrologueLength - (version_length_bytes(2) + prologue_length_bytes(4)).
dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - 6))
return dbl
}
func parseDebugLinePrologue(dbl *DebugLineInfo, buf *bytes.Buffer) {
p := new(DebugLinePrologue)
p.UnitLength = binary.LittleEndian.Uint32(buf.Next(4))
p.Version = binary.LittleEndian.Uint16(buf.Next(2))
p.Length = binary.LittleEndian.Uint32(buf.Next(4))
p.MinInstrLength = uint8(buf.Next(1)[0])
p.InitialIsStmt = uint8(buf.Next(1)[0])
p.LineBase = int8(buf.Next(1)[0])
p.LineRange = uint8(buf.Next(1)[0])
p.OpcodeBase = uint8(buf.Next(1)[0])
p.StdOpLengths = make([]uint8, p.OpcodeBase-1)
binary.Read(buf, binary.LittleEndian, &p.StdOpLengths)
dbl.Prologue = p
}
func parseIncludeDirs(info *DebugLineInfo, buf *bytes.Buffer) {
for {
str, _ := util.ParseString(buf)
if str == "" {
break
}
info.IncludeDirs = append(info.IncludeDirs, str)
}
}
func parseFileEntries(info *DebugLineInfo, buf *bytes.Buffer) {
for {
entry := readFileEntry(info, buf, true)
if entry.Path == "" {
break
}
info.FileNames = append(info.FileNames, entry)
info.Lookup[entry.Path] = entry
}
}
func readFileEntry(info *DebugLineInfo, buf *bytes.Buffer, exitOnEmptyPath bool) *FileEntry {
entry := new(FileEntry)
entry.Path, _ = util.ParseString(buf)
if entry.Path == "" && exitOnEmptyPath {
return entry
}
entry.DirIdx, _ = util.DecodeULEB128(buf)
entry.LastModTime, _ = util.DecodeULEB128(buf)
entry.Length, _ = util.DecodeULEB128(buf)
if !filepath.IsAbs(entry.Path) {
if entry.DirIdx >= 0 && entry.DirIdx < uint64(len(info.IncludeDirs)) {
entry.Path = filepath.Join(info.IncludeDirs[entry.DirIdx], entry.Path)
}
}
return entry
}

View File

@ -0,0 +1,450 @@
package line
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/util"
)
type Location struct {
File string
Line int
Address uint64
Delta int
}
type StateMachine struct {
dbl *DebugLineInfo
file string
line int
address uint64
column uint
isStmt bool
basicBlock bool
endSeq bool
lastDelta int
prologueEnd bool
epilogueBegin bool
// valid is true if the current value of the state machine is the address of
// an instruction (using the terminology used by DWARF spec the current
// value of the state machine should be appended to the matrix representing
// the compilation unit)
valid bool
started bool
buf *bytes.Buffer // remaining instructions
opcodes []opcodefn
definedFiles []*FileEntry // files defined with DW_LINE_define_file
lastAddress uint64
lastFile string
lastLine int
}
type opcodeKind uint8
const (
specialOpcode opcodeKind = iota
standardOpcode
extendedOpcode
)
type opcodefn func(*StateMachine, *bytes.Buffer)
// Special opcodes
const (
DW_LNS_copy = 1
DW_LNS_advance_pc = 2
DW_LNS_advance_line = 3
DW_LNS_set_file = 4
DW_LNS_set_column = 5
DW_LNS_negate_stmt = 6
DW_LNS_set_basic_block = 7
DW_LNS_const_add_pc = 8
DW_LNS_fixed_advance_pc = 9
DW_LNS_prologue_end = 10
DW_LNS_epilogue_begin = 11
)
// Extended opcodes
const (
DW_LINE_end_sequence = 1
DW_LINE_set_address = 2
DW_LINE_define_file = 3
)
var standardopcodes = map[byte]opcodefn{
DW_LNS_copy: copyfn,
DW_LNS_advance_pc: advancepc,
DW_LNS_advance_line: advanceline,
DW_LNS_set_file: setfile,
DW_LNS_set_column: setcolumn,
DW_LNS_negate_stmt: negatestmt,
DW_LNS_set_basic_block: setbasicblock,
DW_LNS_const_add_pc: constaddpc,
DW_LNS_fixed_advance_pc: fixedadvancepc,
DW_LNS_prologue_end: prologueend,
DW_LNS_epilogue_begin: epiloguebegin,
}
var extendedopcodes = map[byte]opcodefn{
DW_LINE_end_sequence: endsequence,
DW_LINE_set_address: setaddress,
DW_LINE_define_file: definefile,
}
func newStateMachine(dbl *DebugLineInfo, instructions []byte) *StateMachine {
opcodes := make([]opcodefn, len(standardopcodes)+1)
opcodes[0] = execExtendedOpcode
for op := range standardopcodes {
opcodes[op] = standardopcodes[op]
}
sm := &StateMachine{dbl: dbl, file: dbl.FileNames[0].Path, line: 1, buf: bytes.NewBuffer(instructions), opcodes: opcodes, isStmt: dbl.Prologue.InitialIsStmt == uint8(1), address: dbl.staticBase}
return sm
}
// Returns all PCs for a given file/line. Useful for loops where the 'for' line
// could be split amongst 2 PCs.
func (lineInfo *DebugLineInfo) AllPCsForFileLine(f string, l int) (pcs []uint64) {
if lineInfo == nil {
return nil
}
var (
lastAddr uint64
sm = newStateMachine(lineInfo, lineInfo.Instructions)
)
for {
if err := sm.next(); err != nil {
if lineInfo.Logf != nil {
lineInfo.Logf("AllPCsForFileLine error: %v", err)
}
break
}
if sm.line == l && sm.file == f && sm.address != lastAddr && sm.isStmt && sm.valid {
pcs = append(pcs, sm.address)
lastAddr = sm.address
}
}
return
}
var NoSourceError = errors.New("no source available")
// AllPCsBetween returns all PC addresses between begin and end (including both begin and end) that have the is_stmt flag set and do not belong to excludeFile:excludeLine
func (lineInfo *DebugLineInfo) AllPCsBetween(begin, end uint64, excludeFile string, excludeLine int) ([]uint64, error) {
if lineInfo == nil {
return nil, NoSourceError
}
var (
pcs []uint64
lastaddr uint64
sm = newStateMachine(lineInfo, lineInfo.Instructions)
)
for {
if err := sm.next(); err != nil {
if lineInfo.Logf != nil {
lineInfo.Logf("AllPCsBetween error: %v", err)
}
break
}
if !sm.valid {
continue
}
if sm.address > end {
break
}
if (sm.address >= begin && sm.address > lastaddr) && sm.isStmt && ((sm.file != excludeFile) || (sm.line != excludeLine)) {
lastaddr = sm.address
pcs = append(pcs, sm.address)
}
}
return pcs, nil
}
// copy returns a copy of this state machine, running the returned state
// machine will not affect sm.
func (sm *StateMachine) copy() *StateMachine {
var r StateMachine
r = *sm
r.buf = bytes.NewBuffer(sm.buf.Bytes())
return &r
}
func (lineInfo *DebugLineInfo) stateMachineForEntry(basePC uint64) (sm *StateMachine) {
sm = lineInfo.stateMachineCache[basePC]
if sm == nil {
sm = newStateMachine(lineInfo, lineInfo.Instructions)
sm.PCToLine(basePC)
lineInfo.stateMachineCache[basePC] = sm
}
sm = sm.copy()
return
}
// PCToLine returns the filename and line number associated with pc.
// If pc isn't found inside lineInfo's table it will return the filename and
// line number associated with the closest PC address preceding pc.
// basePC will be used for caching, it's normally the entry point for the
// function containing pc.
func (lineInfo *DebugLineInfo) PCToLine(basePC, pc uint64) (string, int) {
if lineInfo == nil {
return "", 0
}
if basePC > pc {
panic(fmt.Errorf("basePC after pc %#x %#x", basePC, pc))
}
var sm *StateMachine
if basePC == 0 {
sm = newStateMachine(lineInfo, lineInfo.Instructions)
} else {
// Try to use the last state machine that we used for this function, if
// there isn't one or it's already past pc try to clone the cached state
// machine stopped at the entry point of the function.
// As a last resort start from the start of the debug_line section.
sm = lineInfo.lastMachineCache[basePC]
if sm == nil || sm.lastAddress > pc {
sm = lineInfo.stateMachineForEntry(basePC)
lineInfo.lastMachineCache[basePC] = sm
}
}
file, line, _ := sm.PCToLine(pc)
return file, line
}
func (sm *StateMachine) PCToLine(pc uint64) (string, int, bool) {
if !sm.started {
if err := sm.next(); err != nil {
if sm.dbl.Logf != nil {
sm.dbl.Logf("PCToLine error: %v", err)
}
return "", 0, false
}
}
if sm.lastAddress > pc {
return "", 0, false
}
for {
if sm.valid {
if sm.address > pc {
return sm.lastFile, sm.lastLine, true
}
if sm.address == pc {
return sm.file, sm.line, true
}
}
if err := sm.next(); err != nil {
if sm.dbl.Logf != nil {
sm.dbl.Logf("PCToLine error: %v", err)
}
break
}
}
if sm.valid {
return sm.file, sm.line, true
}
return "", 0, false
}
// LineToPC returns the first PC address associated with filename:lineno.
func (lineInfo *DebugLineInfo) LineToPC(filename string, lineno int) uint64 {
if lineInfo == nil {
return 0
}
sm := newStateMachine(lineInfo, lineInfo.Instructions)
// if no instruction marked is_stmt is found fallback to the first
// instruction assigned to the filename:line.
var fallbackPC uint64
for {
if err := sm.next(); err != nil {
if lineInfo.Logf != nil && err != io.EOF {
lineInfo.Logf("LineToPC error: %v", err)
}
break
}
if sm.line == lineno && sm.file == filename && sm.valid {
if sm.isStmt {
return sm.address
} else if fallbackPC == 0 {
fallbackPC = sm.address
}
}
}
return fallbackPC
}
// PrologueEndPC returns the first PC address marked as prologue_end in the half open interval [start, end)
func (lineInfo *DebugLineInfo) PrologueEndPC(start, end uint64) (pc uint64, file string, line int, ok bool) {
sm := lineInfo.stateMachineForEntry(start)
for {
if sm.valid {
if sm.address >= end {
return 0, "", 0, false
}
if sm.prologueEnd {
return sm.address, sm.file, sm.line, true
}
}
if err := sm.next(); err != nil {
if lineInfo.Logf != nil {
lineInfo.Logf("PrologueEnd error: %v", err)
}
return 0, "", 0, false
}
}
}
func (sm *StateMachine) next() error {
sm.started = true
if sm.valid {
sm.lastAddress, sm.lastFile, sm.lastLine = sm.address, sm.file, sm.line
// valid is set by either a special opcode or a DW_LNS_copy, in both cases
// we need to reset basic_block, prologue_end and epilogue_begin
sm.basicBlock = false
sm.prologueEnd = false
sm.epilogueBegin = false
}
if sm.endSeq {
sm.endSeq = false
sm.file = sm.dbl.FileNames[0].Path
sm.line = 1
sm.column = 0
sm.isStmt = sm.dbl.Prologue.InitialIsStmt == uint8(1)
sm.basicBlock = false
}
b, err := sm.buf.ReadByte()
if err != nil {
return err
}
if b < sm.dbl.Prologue.OpcodeBase {
if int(b) < len(sm.opcodes) {
sm.valid = false
sm.opcodes[b](sm, sm.buf)
} else {
// unimplemented standard opcode, read the number of arguments specified
// in the prologue and do nothing with them
opnum := sm.dbl.Prologue.StdOpLengths[b-1]
for i := 0; i < int(opnum); i++ {
util.DecodeSLEB128(sm.buf)
}
fmt.Printf("unknown opcode\n")
}
} else {
execSpecialOpcode(sm, b)
}
return nil
}
func execSpecialOpcode(sm *StateMachine, instr byte) {
var (
opcode = uint8(instr)
decoded = opcode - sm.dbl.Prologue.OpcodeBase
)
sm.lastDelta = int(sm.dbl.Prologue.LineBase + int8(decoded%sm.dbl.Prologue.LineRange))
sm.line += sm.lastDelta
sm.address += uint64(decoded/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength)
sm.valid = true
}
func execExtendedOpcode(sm *StateMachine, buf *bytes.Buffer) {
_, _ = util.DecodeULEB128(buf)
b, _ := buf.ReadByte()
if fn, ok := extendedopcodes[b]; ok {
fn(sm, buf)
}
}
func copyfn(sm *StateMachine, buf *bytes.Buffer) {
sm.valid = true
}
func advancepc(sm *StateMachine, buf *bytes.Buffer) {
addr, _ := util.DecodeULEB128(buf)
sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength)
}
func advanceline(sm *StateMachine, buf *bytes.Buffer) {
line, _ := util.DecodeSLEB128(buf)
sm.line += int(line)
sm.lastDelta = int(line)
}
func setfile(sm *StateMachine, buf *bytes.Buffer) {
i, _ := util.DecodeULEB128(buf)
if i-1 < uint64(len(sm.dbl.FileNames)) {
sm.file = sm.dbl.FileNames[i-1].Path
} else {
j := (i - 1) - uint64(len(sm.dbl.FileNames))
if j < uint64(len(sm.definedFiles)) {
sm.file = sm.definedFiles[j].Path
} else {
sm.file = ""
}
}
}
func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
c, _ := util.DecodeULEB128(buf)
sm.column = uint(c)
}
func negatestmt(sm *StateMachine, buf *bytes.Buffer) {
sm.isStmt = !sm.isStmt
}
func setbasicblock(sm *StateMachine, buf *bytes.Buffer) {
sm.basicBlock = true
}
func constaddpc(sm *StateMachine, buf *bytes.Buffer) {
sm.address += uint64((255-sm.dbl.Prologue.OpcodeBase)/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength)
}
func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) {
var operand uint16
binary.Read(buf, binary.LittleEndian, &operand)
sm.address += uint64(operand)
}
func endsequence(sm *StateMachine, buf *bytes.Buffer) {
sm.endSeq = true
sm.valid = true
}
func setaddress(sm *StateMachine, buf *bytes.Buffer) {
var addr uint64
binary.Read(buf, binary.LittleEndian, &addr)
sm.address = addr + sm.dbl.staticBase
}
func definefile(sm *StateMachine, buf *bytes.Buffer) {
entry := readFileEntry(sm.dbl, sm.buf, false)
sm.definedFiles = append(sm.definedFiles, entry)
}
func prologueend(sm *StateMachine, buf *bytes.Buffer) {
sm.prologueEnd = true
}
func epiloguebegin(sm *StateMachine, buf *bytes.Buffer) {
sm.epilogueBegin = true
}

197
vendor/github.com/go-delve/delve/pkg/dwarf/op/op.go generated vendored Normal file
View File

@ -0,0 +1,197 @@
package op
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/util"
)
type Opcode byte
//go:generate go run ../../../scripts/gen-opcodes.go opcodes.table opcodes.go
type stackfn func(Opcode, *context) error
type context struct {
buf *bytes.Buffer
stack []int64
pieces []Piece
reg bool
DwarfRegisters
}
// Piece is a piece of memory stored either at an address or in a register.
type Piece struct {
Size int
Addr int64
RegNum uint64
IsRegister bool
}
// ExecuteStackProgram executes a DWARF location expression and returns
// either an address (int64), or a slice of Pieces for location expressions
// that don't evaluate to an address (such as register and composite expressions).
func ExecuteStackProgram(regs DwarfRegisters, instructions []byte) (int64, []Piece, error) {
ctxt := &context{
buf: bytes.NewBuffer(instructions),
stack: make([]int64, 0, 3),
DwarfRegisters: regs,
}
for {
opcodeByte, err := ctxt.buf.ReadByte()
if err != nil {
break
}
opcode := Opcode(opcodeByte)
if ctxt.reg && opcode != DW_OP_piece {
break
}
fn, ok := oplut[opcode]
if !ok {
return 0, nil, fmt.Errorf("invalid instruction %#v", opcode)
}
err = fn(opcode, ctxt)
if err != nil {
return 0, nil, err
}
}
if ctxt.pieces != nil {
return 0, ctxt.pieces, nil
}
if len(ctxt.stack) == 0 {
return 0, nil, errors.New("empty OP stack")
}
return ctxt.stack[len(ctxt.stack)-1], nil, nil
}
// PrettyPrint prints instructions to out.
func PrettyPrint(out io.Writer, instructions []byte) {
in := bytes.NewBuffer(instructions)
for {
opcode, err := in.ReadByte()
if err != nil {
break
}
if name, hasname := opcodeName[Opcode(opcode)]; hasname {
io.WriteString(out, name)
out.Write([]byte{' '})
} else {
fmt.Fprintf(out, "%#x ", opcode)
}
for _, arg := range opcodeArgs[Opcode(opcode)] {
switch arg {
case 's':
n, _ := util.DecodeSLEB128(in)
fmt.Fprintf(out, "%#x ", n)
case 'u':
n, _ := util.DecodeULEB128(in)
fmt.Fprintf(out, "%#x ", n)
case '1':
var x uint8
binary.Read(in, binary.LittleEndian, &x)
fmt.Fprintf(out, "%#x ", x)
case '2':
var x uint16
binary.Read(in, binary.LittleEndian, &x)
fmt.Fprintf(out, "%#x ", x)
case '4':
var x uint32
binary.Read(in, binary.LittleEndian, &x)
fmt.Fprintf(out, "%#x ", x)
case '8':
var x uint64
binary.Read(in, binary.LittleEndian, &x)
fmt.Fprintf(out, "%#x ", x)
case 'B':
sz, _ := util.DecodeULEB128(in)
data := make([]byte, sz)
sz2, _ := in.Read(data)
data = data[:sz2]
fmt.Fprintf(out, "%d [%x] ", sz, data)
}
}
}
}
func callframecfa(opcode Opcode, ctxt *context) error {
if ctxt.CFA == 0 {
return fmt.Errorf("Could not retrieve CFA for current PC")
}
ctxt.stack = append(ctxt.stack, int64(ctxt.CFA))
return nil
}
func addr(opcode Opcode, ctxt *context) error {
ctxt.stack = append(ctxt.stack, int64(binary.LittleEndian.Uint64(ctxt.buf.Next(8))+ctxt.StaticBase))
return nil
}
func plus(opcode Opcode, ctxt *context) error {
var (
slen = len(ctxt.stack)
digits = ctxt.stack[slen-2 : slen]
st = ctxt.stack[:slen-2]
)
ctxt.stack = append(st, digits[0]+digits[1])
return nil
}
func plusuconsts(opcode Opcode, ctxt *context) error {
slen := len(ctxt.stack)
num, _ := util.DecodeULEB128(ctxt.buf)
ctxt.stack[slen-1] = ctxt.stack[slen-1] + int64(num)
return nil
}
func consts(opcode Opcode, ctxt *context) error {
num, _ := util.DecodeSLEB128(ctxt.buf)
ctxt.stack = append(ctxt.stack, num)
return nil
}
func framebase(opcode Opcode, ctxt *context) error {
num, _ := util.DecodeSLEB128(ctxt.buf)
ctxt.stack = append(ctxt.stack, ctxt.FrameBase+num)
return nil
}
func register(opcode Opcode, ctxt *context) error {
ctxt.reg = true
if opcode == DW_OP_regx {
n, _ := util.DecodeSLEB128(ctxt.buf)
ctxt.pieces = append(ctxt.pieces, Piece{IsRegister: true, RegNum: uint64(n)})
} else {
ctxt.pieces = append(ctxt.pieces, Piece{IsRegister: true, RegNum: uint64(opcode - DW_OP_reg0)})
}
return nil
}
func piece(opcode Opcode, ctxt *context) error {
sz, _ := util.DecodeULEB128(ctxt.buf)
if ctxt.reg {
ctxt.reg = false
ctxt.pieces[len(ctxt.pieces)-1].Size = int(sz)
return nil
}
if len(ctxt.stack) == 0 {
return errors.New("empty OP stack")
}
addr := ctxt.stack[len(ctxt.stack)-1]
ctxt.pieces = append(ctxt.pieces, Piece{Size: int(sz), Addr: addr})
ctxt.stack = ctxt.stack[:0]
return nil
}

View File

@ -0,0 +1,515 @@
// THIS FILE IS AUTOGENERATED, EDIT opcodes.table INSTEAD
package op
const (
DW_OP_addr Opcode = 0x03
DW_OP_deref Opcode = 0x06
DW_OP_const1u Opcode = 0x08
DW_OP_const1s Opcode = 0x09
DW_OP_const2u Opcode = 0x0a
DW_OP_const2s Opcode = 0x0b
DW_OP_const4u Opcode = 0x0c
DW_OP_const4s Opcode = 0x0d
DW_OP_const8u Opcode = 0x0e
DW_OP_const8s Opcode = 0x0f
DW_OP_constu Opcode = 0x10
DW_OP_consts Opcode = 0x11
DW_OP_dup Opcode = 0x12
DW_OP_drop Opcode = 0x13
DW_OP_over Opcode = 0x14
DW_OP_pick Opcode = 0x15
DW_OP_swap Opcode = 0x16
DW_OP_rot Opcode = 0x17
DW_OP_xderef Opcode = 0x18
DW_OP_abs Opcode = 0x19
DW_OP_and Opcode = 0x1a
DW_OP_div Opcode = 0x1b
DW_OP_minus Opcode = 0x1c
DW_OP_mod Opcode = 0x1d
DW_OP_mul Opcode = 0x1e
DW_OP_neg Opcode = 0x1f
DW_OP_not Opcode = 0x20
DW_OP_or Opcode = 0x21
DW_OP_plus Opcode = 0x22
DW_OP_plus_uconst Opcode = 0x23
DW_OP_shl Opcode = 0x24
DW_OP_shr Opcode = 0x25
DW_OP_shra Opcode = 0x26
DW_OP_xor Opcode = 0x27
DW_OP_bra Opcode = 0x28
DW_OP_eq Opcode = 0x29
DW_OP_ge Opcode = 0x2a
DW_OP_gt Opcode = 0x2b
DW_OP_le Opcode = 0x2c
DW_OP_lt Opcode = 0x2d
DW_OP_ne Opcode = 0x2e
DW_OP_skip Opcode = 0x2f
DW_OP_lit0 Opcode = 0x30
DW_OP_lit1 Opcode = 0x31
DW_OP_lit2 Opcode = 0x32
DW_OP_lit3 Opcode = 0x33
DW_OP_lit4 Opcode = 0x34
DW_OP_lit5 Opcode = 0x35
DW_OP_lit6 Opcode = 0x36
DW_OP_lit7 Opcode = 0x37
DW_OP_lit8 Opcode = 0x38
DW_OP_lit9 Opcode = 0x39
DW_OP_lit10 Opcode = 0x3a
DW_OP_lit11 Opcode = 0x3b
DW_OP_lit12 Opcode = 0x3c
DW_OP_lit13 Opcode = 0x3d
DW_OP_lit14 Opcode = 0x3e
DW_OP_lit15 Opcode = 0x3f
DW_OP_lit16 Opcode = 0x40
DW_OP_lit17 Opcode = 0x41
DW_OP_lit18 Opcode = 0x42
DW_OP_lit19 Opcode = 0x43
DW_OP_lit20 Opcode = 0x44
DW_OP_lit21 Opcode = 0x45
DW_OP_lit22 Opcode = 0x46
DW_OP_lit23 Opcode = 0x47
DW_OP_lit24 Opcode = 0x48
DW_OP_lit25 Opcode = 0x49
DW_OP_lit26 Opcode = 0x4a
DW_OP_lit27 Opcode = 0x4b
DW_OP_lit28 Opcode = 0x4c
DW_OP_lit29 Opcode = 0x4d
DW_OP_lit30 Opcode = 0x4e
DW_OP_lit31 Opcode = 0x4f
DW_OP_reg0 Opcode = 0x50
DW_OP_reg1 Opcode = 0x51
DW_OP_reg2 Opcode = 0x52
DW_OP_reg3 Opcode = 0x53
DW_OP_reg4 Opcode = 0x54
DW_OP_reg5 Opcode = 0x55
DW_OP_reg6 Opcode = 0x56
DW_OP_reg7 Opcode = 0x57
DW_OP_reg8 Opcode = 0x58
DW_OP_reg9 Opcode = 0x59
DW_OP_reg10 Opcode = 0x5a
DW_OP_reg11 Opcode = 0x5b
DW_OP_reg12 Opcode = 0x5c
DW_OP_reg13 Opcode = 0x5d
DW_OP_reg14 Opcode = 0x5e
DW_OP_reg15 Opcode = 0x5f
DW_OP_reg16 Opcode = 0x60
DW_OP_reg17 Opcode = 0x61
DW_OP_reg18 Opcode = 0x62
DW_OP_reg19 Opcode = 0x63
DW_OP_reg20 Opcode = 0x64
DW_OP_reg21 Opcode = 0x65
DW_OP_reg22 Opcode = 0x66
DW_OP_reg23 Opcode = 0x67
DW_OP_reg24 Opcode = 0x68
DW_OP_reg25 Opcode = 0x69
DW_OP_reg26 Opcode = 0x6a
DW_OP_reg27 Opcode = 0x6b
DW_OP_reg28 Opcode = 0x6c
DW_OP_reg29 Opcode = 0x6d
DW_OP_reg30 Opcode = 0x6e
DW_OP_reg31 Opcode = 0x6f
DW_OP_breg0 Opcode = 0x70
DW_OP_breg1 Opcode = 0x71
DW_OP_breg2 Opcode = 0x72
DW_OP_breg3 Opcode = 0x73
DW_OP_breg4 Opcode = 0x74
DW_OP_breg5 Opcode = 0x75
DW_OP_breg6 Opcode = 0x76
DW_OP_breg7 Opcode = 0x77
DW_OP_breg8 Opcode = 0x78
DW_OP_breg9 Opcode = 0x79
DW_OP_breg10 Opcode = 0x7a
DW_OP_breg11 Opcode = 0x7b
DW_OP_breg12 Opcode = 0x7c
DW_OP_breg13 Opcode = 0x7d
DW_OP_breg14 Opcode = 0x7e
DW_OP_breg15 Opcode = 0x7f
DW_OP_breg16 Opcode = 0x80
DW_OP_breg17 Opcode = 0x81
DW_OP_breg18 Opcode = 0x82
DW_OP_breg19 Opcode = 0x83
DW_OP_breg20 Opcode = 0x84
DW_OP_breg21 Opcode = 0x85
DW_OP_breg22 Opcode = 0x86
DW_OP_breg23 Opcode = 0x87
DW_OP_breg24 Opcode = 0x88
DW_OP_breg25 Opcode = 0x89
DW_OP_breg26 Opcode = 0x8a
DW_OP_breg27 Opcode = 0x8b
DW_OP_breg28 Opcode = 0x8c
DW_OP_breg29 Opcode = 0x8d
DW_OP_breg30 Opcode = 0x8e
DW_OP_breg31 Opcode = 0x8f
DW_OP_regx Opcode = 0x90
DW_OP_fbreg Opcode = 0x91
DW_OP_bregx Opcode = 0x92
DW_OP_piece Opcode = 0x93
DW_OP_deref_size Opcode = 0x94
DW_OP_xderef_size Opcode = 0x95
DW_OP_nop Opcode = 0x96
DW_OP_push_object_address Opcode = 0x97
DW_OP_call2 Opcode = 0x98
DW_OP_call4 Opcode = 0x99
DW_OP_call_ref Opcode = 0x9a
DW_OP_form_tls_address Opcode = 0x9b
DW_OP_call_frame_cfa Opcode = 0x9c
DW_OP_bit_piece Opcode = 0x9d
DW_OP_implicit_value Opcode = 0x9e
DW_OP_stack_value Opcode = 0x9f
)
var opcodeName = map[Opcode]string{
DW_OP_addr: "DW_OP_addr",
DW_OP_deref: "DW_OP_deref",
DW_OP_const1u: "DW_OP_const1u",
DW_OP_const1s: "DW_OP_const1s",
DW_OP_const2u: "DW_OP_const2u",
DW_OP_const2s: "DW_OP_const2s",
DW_OP_const4u: "DW_OP_const4u",
DW_OP_const4s: "DW_OP_const4s",
DW_OP_const8u: "DW_OP_const8u",
DW_OP_const8s: "DW_OP_const8s",
DW_OP_constu: "DW_OP_constu",
DW_OP_consts: "DW_OP_consts",
DW_OP_dup: "DW_OP_dup",
DW_OP_drop: "DW_OP_drop",
DW_OP_over: "DW_OP_over",
DW_OP_pick: "DW_OP_pick",
DW_OP_swap: "DW_OP_swap",
DW_OP_rot: "DW_OP_rot",
DW_OP_xderef: "DW_OP_xderef",
DW_OP_abs: "DW_OP_abs",
DW_OP_and: "DW_OP_and",
DW_OP_div: "DW_OP_div",
DW_OP_minus: "DW_OP_minus",
DW_OP_mod: "DW_OP_mod",
DW_OP_mul: "DW_OP_mul",
DW_OP_neg: "DW_OP_neg",
DW_OP_not: "DW_OP_not",
DW_OP_or: "DW_OP_or",
DW_OP_plus: "DW_OP_plus",
DW_OP_plus_uconst: "DW_OP_plus_uconst",
DW_OP_shl: "DW_OP_shl",
DW_OP_shr: "DW_OP_shr",
DW_OP_shra: "DW_OP_shra",
DW_OP_xor: "DW_OP_xor",
DW_OP_bra: "DW_OP_bra",
DW_OP_eq: "DW_OP_eq",
DW_OP_ge: "DW_OP_ge",
DW_OP_gt: "DW_OP_gt",
DW_OP_le: "DW_OP_le",
DW_OP_lt: "DW_OP_lt",
DW_OP_ne: "DW_OP_ne",
DW_OP_skip: "DW_OP_skip",
DW_OP_lit0: "DW_OP_lit0",
DW_OP_lit1: "DW_OP_lit1",
DW_OP_lit2: "DW_OP_lit2",
DW_OP_lit3: "DW_OP_lit3",
DW_OP_lit4: "DW_OP_lit4",
DW_OP_lit5: "DW_OP_lit5",
DW_OP_lit6: "DW_OP_lit6",
DW_OP_lit7: "DW_OP_lit7",
DW_OP_lit8: "DW_OP_lit8",
DW_OP_lit9: "DW_OP_lit9",
DW_OP_lit10: "DW_OP_lit10",
DW_OP_lit11: "DW_OP_lit11",
DW_OP_lit12: "DW_OP_lit12",
DW_OP_lit13: "DW_OP_lit13",
DW_OP_lit14: "DW_OP_lit14",
DW_OP_lit15: "DW_OP_lit15",
DW_OP_lit16: "DW_OP_lit16",
DW_OP_lit17: "DW_OP_lit17",
DW_OP_lit18: "DW_OP_lit18",
DW_OP_lit19: "DW_OP_lit19",
DW_OP_lit20: "DW_OP_lit20",
DW_OP_lit21: "DW_OP_lit21",
DW_OP_lit22: "DW_OP_lit22",
DW_OP_lit23: "DW_OP_lit23",
DW_OP_lit24: "DW_OP_lit24",
DW_OP_lit25: "DW_OP_lit25",
DW_OP_lit26: "DW_OP_lit26",
DW_OP_lit27: "DW_OP_lit27",
DW_OP_lit28: "DW_OP_lit28",
DW_OP_lit29: "DW_OP_lit29",
DW_OP_lit30: "DW_OP_lit30",
DW_OP_lit31: "DW_OP_lit31",
DW_OP_reg0: "DW_OP_reg0",
DW_OP_reg1: "DW_OP_reg1",
DW_OP_reg2: "DW_OP_reg2",
DW_OP_reg3: "DW_OP_reg3",
DW_OP_reg4: "DW_OP_reg4",
DW_OP_reg5: "DW_OP_reg5",
DW_OP_reg6: "DW_OP_reg6",
DW_OP_reg7: "DW_OP_reg7",
DW_OP_reg8: "DW_OP_reg8",
DW_OP_reg9: "DW_OP_reg9",
DW_OP_reg10: "DW_OP_reg10",
DW_OP_reg11: "DW_OP_reg11",
DW_OP_reg12: "DW_OP_reg12",
DW_OP_reg13: "DW_OP_reg13",
DW_OP_reg14: "DW_OP_reg14",
DW_OP_reg15: "DW_OP_reg15",
DW_OP_reg16: "DW_OP_reg16",
DW_OP_reg17: "DW_OP_reg17",
DW_OP_reg18: "DW_OP_reg18",
DW_OP_reg19: "DW_OP_reg19",
DW_OP_reg20: "DW_OP_reg20",
DW_OP_reg21: "DW_OP_reg21",
DW_OP_reg22: "DW_OP_reg22",
DW_OP_reg23: "DW_OP_reg23",
DW_OP_reg24: "DW_OP_reg24",
DW_OP_reg25: "DW_OP_reg25",
DW_OP_reg26: "DW_OP_reg26",
DW_OP_reg27: "DW_OP_reg27",
DW_OP_reg28: "DW_OP_reg28",
DW_OP_reg29: "DW_OP_reg29",
DW_OP_reg30: "DW_OP_reg30",
DW_OP_reg31: "DW_OP_reg31",
DW_OP_breg0: "DW_OP_breg0",
DW_OP_breg1: "DW_OP_breg1",
DW_OP_breg2: "DW_OP_breg2",
DW_OP_breg3: "DW_OP_breg3",
DW_OP_breg4: "DW_OP_breg4",
DW_OP_breg5: "DW_OP_breg5",
DW_OP_breg6: "DW_OP_breg6",
DW_OP_breg7: "DW_OP_breg7",
DW_OP_breg8: "DW_OP_breg8",
DW_OP_breg9: "DW_OP_breg9",
DW_OP_breg10: "DW_OP_breg10",
DW_OP_breg11: "DW_OP_breg11",
DW_OP_breg12: "DW_OP_breg12",
DW_OP_breg13: "DW_OP_breg13",
DW_OP_breg14: "DW_OP_breg14",
DW_OP_breg15: "DW_OP_breg15",
DW_OP_breg16: "DW_OP_breg16",
DW_OP_breg17: "DW_OP_breg17",
DW_OP_breg18: "DW_OP_breg18",
DW_OP_breg19: "DW_OP_breg19",
DW_OP_breg20: "DW_OP_breg20",
DW_OP_breg21: "DW_OP_breg21",
DW_OP_breg22: "DW_OP_breg22",
DW_OP_breg23: "DW_OP_breg23",
DW_OP_breg24: "DW_OP_breg24",
DW_OP_breg25: "DW_OP_breg25",
DW_OP_breg26: "DW_OP_breg26",
DW_OP_breg27: "DW_OP_breg27",
DW_OP_breg28: "DW_OP_breg28",
DW_OP_breg29: "DW_OP_breg29",
DW_OP_breg30: "DW_OP_breg30",
DW_OP_breg31: "DW_OP_breg31",
DW_OP_regx: "DW_OP_regx",
DW_OP_fbreg: "DW_OP_fbreg",
DW_OP_bregx: "DW_OP_bregx",
DW_OP_piece: "DW_OP_piece",
DW_OP_deref_size: "DW_OP_deref_size",
DW_OP_xderef_size: "DW_OP_xderef_size",
DW_OP_nop: "DW_OP_nop",
DW_OP_push_object_address: "DW_OP_push_object_address",
DW_OP_call2: "DW_OP_call2",
DW_OP_call4: "DW_OP_call4",
DW_OP_call_ref: "DW_OP_call_ref",
DW_OP_form_tls_address: "DW_OP_form_tls_address",
DW_OP_call_frame_cfa: "DW_OP_call_frame_cfa",
DW_OP_bit_piece: "DW_OP_bit_piece",
DW_OP_implicit_value: "DW_OP_implicit_value",
DW_OP_stack_value: "DW_OP_stack_value",
}
var opcodeArgs = map[Opcode]string{
DW_OP_addr: "8",
DW_OP_deref: "",
DW_OP_const1u: "1",
DW_OP_const1s: "1",
DW_OP_const2u: "2",
DW_OP_const2s: "2",
DW_OP_const4u: "4",
DW_OP_const4s: "4",
DW_OP_const8u: "8",
DW_OP_const8s: "8",
DW_OP_constu: "u",
DW_OP_consts: "s",
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: "u",
DW_OP_shl: "",
DW_OP_shr: "",
DW_OP_shra: "",
DW_OP_xor: "",
DW_OP_bra: "2",
DW_OP_eq: "",
DW_OP_ge: "",
DW_OP_gt: "",
DW_OP_le: "",
DW_OP_lt: "",
DW_OP_ne: "",
DW_OP_skip: "2",
DW_OP_lit0: "",
DW_OP_lit1: "",
DW_OP_lit2: "",
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: "s",
DW_OP_breg1: "s",
DW_OP_breg2: "s",
DW_OP_breg3: "s",
DW_OP_breg4: "s",
DW_OP_breg5: "s",
DW_OP_breg6: "s",
DW_OP_breg7: "s",
DW_OP_breg8: "s",
DW_OP_breg9: "s",
DW_OP_breg10: "s",
DW_OP_breg11: "s",
DW_OP_breg12: "s",
DW_OP_breg13: "s",
DW_OP_breg14: "s",
DW_OP_breg15: "s",
DW_OP_breg16: "s",
DW_OP_breg17: "s",
DW_OP_breg18: "s",
DW_OP_breg19: "s",
DW_OP_breg20: "s",
DW_OP_breg21: "s",
DW_OP_breg22: "s",
DW_OP_breg23: "s",
DW_OP_breg24: "s",
DW_OP_breg25: "s",
DW_OP_breg26: "s",
DW_OP_breg27: "s",
DW_OP_breg28: "s",
DW_OP_breg29: "s",
DW_OP_breg30: "s",
DW_OP_breg31: "s",
DW_OP_regx: "s",
DW_OP_fbreg: "s",
DW_OP_bregx: "us",
DW_OP_piece: "u",
DW_OP_deref_size: "1",
DW_OP_xderef_size: "1",
DW_OP_nop: "",
DW_OP_push_object_address: "",
DW_OP_call2: "2",
DW_OP_call4: "4",
DW_OP_call_ref: "4",
DW_OP_form_tls_address: "",
DW_OP_call_frame_cfa: "",
DW_OP_bit_piece: "uu",
DW_OP_implicit_value: "B",
DW_OP_stack_value: "",
}
var oplut = map[Opcode]stackfn{
DW_OP_addr: addr,
DW_OP_consts: consts,
DW_OP_plus: plus,
DW_OP_plus_uconst: plusuconsts,
DW_OP_reg0: register,
DW_OP_reg1: register,
DW_OP_reg2: register,
DW_OP_reg3: register,
DW_OP_reg4: register,
DW_OP_reg5: register,
DW_OP_reg6: register,
DW_OP_reg7: register,
DW_OP_reg8: register,
DW_OP_reg9: register,
DW_OP_reg10: register,
DW_OP_reg11: register,
DW_OP_reg12: register,
DW_OP_reg13: register,
DW_OP_reg14: register,
DW_OP_reg15: register,
DW_OP_reg16: register,
DW_OP_reg17: register,
DW_OP_reg18: register,
DW_OP_reg19: register,
DW_OP_reg20: register,
DW_OP_reg21: register,
DW_OP_reg22: register,
DW_OP_reg23: register,
DW_OP_reg24: register,
DW_OP_reg25: register,
DW_OP_reg26: register,
DW_OP_reg27: register,
DW_OP_reg28: register,
DW_OP_reg29: register,
DW_OP_reg30: register,
DW_OP_reg31: register,
DW_OP_regx: register,
DW_OP_fbreg: framebase,
DW_OP_piece: piece,
DW_OP_call_frame_cfa: callframecfa,
}

View File

@ -0,0 +1,175 @@
// This file is used by scripts/gen-opcodes.go to generate
// pkg/dwarf/op/opcodes.go
// Lines starting with // are comments and will be discarded.
// Non empty lines contain the following tab separated fields:
//
// <opcode name> <opcode code> <arguments> <function name>
//
// With the last column, <function name>, being optional.
//
// The arguments field should contain a string with one character for each
// argument of the opcode:
//
// s signed variable length integer
// u unsigned variable length integer
// 1 one byte unsigned integer
// 2 two bytes unsigned integer
// 4 four bytes unsigned integer
// 8 eight bytes unsigned integer
// B an unsigned variable length integer 'n' followed by n a block of n bytes
DW_OP_addr 0x03 "8" addr
DW_OP_deref 0x06 ""
DW_OP_const1u 0x08 "1"
DW_OP_const1s 0x09 "1"
DW_OP_const2u 0x0a "2"
DW_OP_const2s 0x0b "2"
DW_OP_const4u 0x0c "4"
DW_OP_const4s 0x0d "4"
DW_OP_const8u 0x0e "8"
DW_OP_const8s 0x0f "8"
DW_OP_constu 0x10 "u"
DW_OP_consts 0x11 "s" consts
DW_OP_dup 0x12 ""
DW_OP_drop 0x13 ""
DW_OP_over 0x14 ""
DW_OP_pick 0x15 ""
DW_OP_swap 0x16 ""
DW_OP_rot 0x17 ""
DW_OP_xderef 0x18 ""
DW_OP_abs 0x19 ""
DW_OP_and 0x1a ""
DW_OP_div 0x1b ""
DW_OP_minus 0x1c ""
DW_OP_mod 0x1d ""
DW_OP_mul 0x1e ""
DW_OP_neg 0x1f ""
DW_OP_not 0x20 ""
DW_OP_or 0x21 ""
DW_OP_plus 0x22 "" plus
DW_OP_plus_uconst 0x23 "u" plusuconsts
DW_OP_shl 0x24 ""
DW_OP_shr 0x25 ""
DW_OP_shra 0x26 ""
DW_OP_xor 0x27 ""
DW_OP_bra 0x28 "2"
DW_OP_eq 0x29 ""
DW_OP_ge 0x2a ""
DW_OP_gt 0x2b ""
DW_OP_le 0x2c ""
DW_OP_lt 0x2d ""
DW_OP_ne 0x2e ""
DW_OP_skip 0x2f "2"
DW_OP_lit0 0x30 ""
DW_OP_lit1 0x31 ""
DW_OP_lit2 0x32 ""
DW_OP_lit3 0x33 ""
DW_OP_lit4 0x34 ""
DW_OP_lit5 0x35 ""
DW_OP_lit6 0x36 ""
DW_OP_lit7 0x37 ""
DW_OP_lit8 0x38 ""
DW_OP_lit9 0x39 ""
DW_OP_lit10 0x3a ""
DW_OP_lit11 0x3b ""
DW_OP_lit12 0x3c ""
DW_OP_lit13 0x3d ""
DW_OP_lit14 0x3e ""
DW_OP_lit15 0x3f ""
DW_OP_lit16 0x40 ""
DW_OP_lit17 0x41 ""
DW_OP_lit18 0x42 ""
DW_OP_lit19 0x43 ""
DW_OP_lit20 0x44 ""
DW_OP_lit21 0x45 ""
DW_OP_lit22 0x46 ""
DW_OP_lit23 0x47 ""
DW_OP_lit24 0x48 ""
DW_OP_lit25 0x49 ""
DW_OP_lit26 0x4a ""
DW_OP_lit27 0x4b ""
DW_OP_lit28 0x4c ""
DW_OP_lit29 0x4d ""
DW_OP_lit30 0x4e ""
DW_OP_lit31 0x4f ""
DW_OP_reg0 0x50 "" register
DW_OP_reg1 0x51 "" register
DW_OP_reg2 0x52 "" register
DW_OP_reg3 0x53 "" register
DW_OP_reg4 0x54 "" register
DW_OP_reg5 0x55 "" register
DW_OP_reg6 0x56 "" register
DW_OP_reg7 0x57 "" register
DW_OP_reg8 0x58 "" register
DW_OP_reg9 0x59 "" register
DW_OP_reg10 0x5a "" register
DW_OP_reg11 0x5b "" register
DW_OP_reg12 0x5c "" register
DW_OP_reg13 0x5d "" register
DW_OP_reg14 0x5e "" register
DW_OP_reg15 0x5f "" register
DW_OP_reg16 0x60 "" register
DW_OP_reg17 0x61 "" register
DW_OP_reg18 0x62 "" register
DW_OP_reg19 0x63 "" register
DW_OP_reg20 0x64 "" register
DW_OP_reg21 0x65 "" register
DW_OP_reg22 0x66 "" register
DW_OP_reg23 0x67 "" register
DW_OP_reg24 0x68 "" register
DW_OP_reg25 0x69 "" register
DW_OP_reg26 0x6a "" register
DW_OP_reg27 0x6b "" register
DW_OP_reg28 0x6c "" register
DW_OP_reg29 0x6d "" register
DW_OP_reg30 0x6e "" register
DW_OP_reg31 0x6f "" register
DW_OP_breg0 0x70 "s"
DW_OP_breg1 0x71 "s"
DW_OP_breg2 0x72 "s"
DW_OP_breg3 0x73 "s"
DW_OP_breg4 0x74 "s"
DW_OP_breg5 0x75 "s"
DW_OP_breg6 0x76 "s"
DW_OP_breg7 0x77 "s"
DW_OP_breg8 0x78 "s"
DW_OP_breg9 0x79 "s"
DW_OP_breg10 0x7a "s"
DW_OP_breg11 0x7b "s"
DW_OP_breg12 0x7c "s"
DW_OP_breg13 0x7d "s"
DW_OP_breg14 0x7e "s"
DW_OP_breg15 0x7f "s"
DW_OP_breg16 0x80 "s"
DW_OP_breg17 0x81 "s"
DW_OP_breg18 0x82 "s"
DW_OP_breg19 0x83 "s"
DW_OP_breg20 0x84 "s"
DW_OP_breg21 0x85 "s"
DW_OP_breg22 0x86 "s"
DW_OP_breg23 0x87 "s"
DW_OP_breg24 0x88 "s"
DW_OP_breg25 0x89 "s"
DW_OP_breg26 0x8a "s"
DW_OP_breg27 0x8b "s"
DW_OP_breg28 0x8c "s"
DW_OP_breg29 0x8d "s"
DW_OP_breg30 0x8e "s"
DW_OP_breg31 0x8f "s"
DW_OP_regx 0x90 "s" register
DW_OP_fbreg 0x91 "s" framebase
DW_OP_bregx 0x92 "us"
DW_OP_piece 0x93 "u" piece
DW_OP_deref_size 0x94 "1"
DW_OP_xderef_size 0x95 "1"
DW_OP_nop 0x96 ""
DW_OP_push_object_address 0x97 ""
DW_OP_call2 0x98 "2"
DW_OP_call4 0x99 "4"
DW_OP_call_ref 0x9a "4"
DW_OP_form_tls_address 0x9b ""
DW_OP_call_frame_cfa 0x9c "" callframecfa
DW_OP_bit_piece 0x9d "uu"
DW_OP_implicit_value 0x9e "B"
DW_OP_stack_value 0x9f ""

102
vendor/github.com/go-delve/delve/pkg/dwarf/op/regs.go generated vendored Normal file
View File

@ -0,0 +1,102 @@
package op
import (
"bytes"
"encoding/binary"
)
type DwarfRegisters struct {
StaticBase uint64
CFA int64
FrameBase int64
ObjBase int64
Regs []*DwarfRegister
ByteOrder binary.ByteOrder
PCRegNum uint64
SPRegNum uint64
BPRegNum uint64
}
type DwarfRegister struct {
Uint64Val uint64
Bytes []byte
}
// Uint64Val returns the uint64 value of register idx.
func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
reg := regs.Reg(idx)
if reg == nil {
return 0
}
return regs.Regs[idx].Uint64Val
}
// Bytes returns the bytes value of register idx, nil if the register is not
// defined.
func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
reg := regs.Reg(idx)
if reg == nil {
return nil
}
if reg.Bytes == nil {
var buf bytes.Buffer
binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
reg.Bytes = buf.Bytes()
}
return reg.Bytes
}
// Reg returns register idx or nil if the register is not defined.
func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
if idx >= uint64(len(regs.Regs)) {
return nil
}
return regs.Regs[idx]
}
func (regs *DwarfRegisters) PC() uint64 {
return regs.Uint64Val(regs.PCRegNum)
}
func (regs *DwarfRegisters) SP() uint64 {
return regs.Uint64Val(regs.SPRegNum)
}
func (regs *DwarfRegisters) BP() uint64 {
return regs.Uint64Val(regs.BPRegNum)
}
// AddReg adds register idx to regs.
func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
if idx >= uint64(len(regs.Regs)) {
newRegs := make([]*DwarfRegister, idx+1)
copy(newRegs, regs.Regs)
regs.Regs = newRegs
}
regs.Regs[idx] = reg
}
func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
return &DwarfRegister{Uint64Val: v}
}
func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
var v uint64
switch len(bytes) {
case 1:
v = uint64(bytes[0])
case 2:
x := binary.LittleEndian.Uint16(bytes)
v = uint64(x)
case 4:
x := binary.LittleEndian.Uint32(bytes)
v = uint64(x)
default:
if len(bytes) >= 8 {
v = binary.LittleEndian.Uint64(bytes[:8])
}
}
return &DwarfRegister{Uint64Val: v, Bytes: bytes}
}

View File

@ -0,0 +1,446 @@
package reader
import (
"debug/dwarf"
"errors"
"fmt"
"github.com/go-delve/delve/pkg/dwarf/op"
)
type Reader struct {
*dwarf.Reader
depth int
}
// New returns a reader for the specified dwarf data.
func New(data *dwarf.Data) *Reader {
return &Reader{data.Reader(), 0}
}
// Seek moves the reader to an arbitrary offset.
func (reader *Reader) Seek(off dwarf.Offset) {
reader.depth = 0
reader.Reader.Seek(off)
}
// SeekToEntry moves the reader to an arbitrary entry.
func (reader *Reader) SeekToEntry(entry *dwarf.Entry) error {
reader.Seek(entry.Offset)
// Consume the current entry so .Next works as intended
_, err := reader.Next()
return err
}
// SeekToFunctionEntry moves the reader to the function that includes the
// specified program counter.
func (reader *Reader) SeekToFunction(pc RelAddr) (*dwarf.Entry, error) {
reader.Seek(0)
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
if entry.Tag != dwarf.TagSubprogram {
continue
}
lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64)
if !ok {
continue
}
highpc, ok := entry.Val(dwarf.AttrHighpc).(uint64)
if !ok {
continue
}
if lowpc <= uint64(pc) && highpc > uint64(pc) {
return entry, nil
}
}
return nil, fmt.Errorf("unable to find function context")
}
// Returns the address for the named entry.
func (reader *Reader) AddrFor(name string, staticBase uint64) (uint64, error) {
entry, err := reader.FindEntryNamed(name, false)
if err != nil {
return 0, err
}
instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
if !ok {
return 0, fmt.Errorf("type assertion failed")
}
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instructions)
if err != nil {
return 0, err
}
return uint64(addr), nil
}
// Returns the address for the named struct member. Expects the reader to be at the parent entry
// or one of the parents children, thus does not seek to parent by itself.
func (reader *Reader) AddrForMember(member string, initialInstructions []byte) (uint64, error) {
for {
entry, err := reader.NextMemberVariable()
if err != nil {
return 0, err
}
if entry == nil {
return 0, fmt.Errorf("nil entry for member named %s", member)
}
name, ok := entry.Val(dwarf.AttrName).(string)
if !ok || name != member {
continue
}
instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte)
if !ok {
continue
}
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{}, append(initialInstructions, instructions...))
return uint64(addr), err
}
}
var TypeNotFoundErr = errors.New("no type entry found, use 'types' for a list of valid types")
// SeekToType moves the reader to the type specified by the entry,
// optionally resolving typedefs and pointer types. If the reader is set
// to a struct type the NextMemberVariable call can be used to walk all member data.
func (reader *Reader) SeekToType(entry *dwarf.Entry, resolveTypedefs bool, resolvePointerTypes bool) (*dwarf.Entry, error) {
offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset)
if !ok {
return nil, fmt.Errorf("entry does not have a type attribute")
}
// Seek to the first type offset
reader.Seek(offset)
// Walk the types to the base
for typeEntry, err := reader.Next(); typeEntry != nil; typeEntry, err = reader.Next() {
if err != nil {
return nil, err
}
if typeEntry.Tag == dwarf.TagTypedef && !resolveTypedefs {
return typeEntry, nil
}
if typeEntry.Tag == dwarf.TagPointerType && !resolvePointerTypes {
return typeEntry, nil
}
offset, ok = typeEntry.Val(dwarf.AttrType).(dwarf.Offset)
if !ok {
return typeEntry, nil
}
reader.Seek(offset)
}
return nil, TypeNotFoundErr
}
func (reader *Reader) NextType() (*dwarf.Entry, error) {
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
switch entry.Tag {
case dwarf.TagArrayType, dwarf.TagBaseType, dwarf.TagClassType, dwarf.TagStructType, dwarf.TagUnionType, dwarf.TagConstType, dwarf.TagVolatileType, dwarf.TagRestrictType, dwarf.TagEnumerationType, dwarf.TagPointerType, dwarf.TagSubroutineType, dwarf.TagTypedef, dwarf.TagUnspecifiedType:
return entry, nil
}
}
return nil, nil
}
// SeekToTypeNamed moves the reader to the type specified by the name.
// If the reader is set to a struct type the NextMemberVariable call
// can be used to walk all member data.
func (reader *Reader) SeekToTypeNamed(name string) (*dwarf.Entry, error) {
// Walk the types to the base
for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() {
if err != nil {
return nil, err
}
n, ok := entry.Val(dwarf.AttrName).(string)
if !ok {
continue
}
if n == name {
return entry, nil
}
}
return nil, TypeNotFoundErr
}
// Finds the entry for 'name'.
func (reader *Reader) FindEntryNamed(name string, member bool) (*dwarf.Entry, error) {
depth := 1
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
if entry.Children {
depth++
}
if entry.Tag == 0 {
depth--
if depth <= 0 {
return nil, fmt.Errorf("could not find symbol value for %s", name)
}
}
if member {
if entry.Tag != dwarf.TagMember {
continue
}
} else {
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagStructType {
continue
}
}
n, ok := entry.Val(dwarf.AttrName).(string)
if !ok || n != name {
continue
}
return entry, nil
}
return nil, fmt.Errorf("could not find symbol value for %s", name)
}
func (reader *Reader) InstructionsForEntryNamed(name string, member bool) ([]byte, error) {
entry, err := reader.FindEntryNamed(name, member)
if err != nil {
return nil, err
}
var attr dwarf.Attr
if member {
attr = dwarf.AttrDataMemberLoc
} else {
attr = dwarf.AttrLocation
}
instr, ok := entry.Val(attr).([]byte)
if !ok {
return nil, errors.New("invalid typecast for Dwarf instructions")
}
return instr, nil
}
func (reader *Reader) InstructionsForEntry(entry *dwarf.Entry) ([]byte, error) {
if entry.Tag == dwarf.TagMember {
instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte)
if !ok {
return nil, fmt.Errorf("member data has no data member location attribute")
}
// clone slice to prevent stomping on the dwarf data
return append([]byte{}, instructions...), nil
}
// non-member
instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
if !ok {
return nil, fmt.Errorf("entry has no location attribute")
}
// clone slice to prevent stomping on the dwarf data
return append([]byte{}, instructions...), nil
}
// NextMemberVariable moves the reader to the next debug entry that describes a member variable and returns the entry.
func (reader *Reader) NextMemberVariable() (*dwarf.Entry, error) {
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
// All member variables will be at the same depth
reader.SkipChildren()
// End of the current depth
if entry.Tag == 0 {
break
}
if entry.Tag == dwarf.TagMember {
return entry, nil
}
}
// No more items
return nil, nil
}
// NextPackageVariable moves the reader to the next debug entry that describes a package variable.
// Any TagVariable entry that is not inside a sub prgram entry and is marked external is considered a package variable.
func (reader *Reader) NextPackageVariable() (*dwarf.Entry, error) {
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
if entry.Tag == dwarf.TagVariable {
ext, ok := entry.Val(dwarf.AttrExternal).(bool)
if ok && ext {
return entry, nil
}
}
// Ignore everything inside sub programs
if entry.Tag == dwarf.TagSubprogram {
reader.SkipChildren()
}
}
// No more items
return nil, nil
}
func (reader *Reader) NextCompileUnit() (*dwarf.Entry, error) {
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
if err != nil {
return nil, err
}
if entry.Tag == dwarf.TagCompileUnit {
return entry, nil
}
}
return nil, nil
}
// Entry represents a debug_info entry.
// When calling Val, if the entry does not have the specified attribute, the
// entry specified by DW_AT_abstract_origin will be searched recursively.
type Entry interface {
Val(dwarf.Attr) interface{}
}
type compositeEntry []*dwarf.Entry
func (ce compositeEntry) Val(attr dwarf.Attr) interface{} {
for _, e := range ce {
if r := e.Val(attr); r != nil {
return r
}
}
return nil
}
// LoadAbstractOrigin loads the entry corresponding to the
// DW_AT_abstract_origin of entry and returns a combination of entry and its
// abstract origin.
func LoadAbstractOrigin(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.Offset) {
ao, ok := entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
if !ok {
return entry, entry.Offset
}
r := []*dwarf.Entry{entry}
for {
aordr.Seek(ao)
e, _ := aordr.Next()
if e == nil {
break
}
r = append(r, e)
ao, ok = e.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
if !ok {
break
}
}
return compositeEntry(r), entry.Offset
}
// InlineStackReader provides a way to read the stack of inlined calls at a
// specified PC address.
type InlineStackReader struct {
dwarf *dwarf.Data
reader *dwarf.Reader
entry *dwarf.Entry
depth int
pc uint64
err error
}
// InlineStack returns an InlineStackReader for the specified function and
// PC address.
// If pc is 0 then all inlined calls will be returned.
func InlineStack(dwarf *dwarf.Data, fnoff dwarf.Offset, pc RelAddr) *InlineStackReader {
reader := dwarf.Reader()
reader.Seek(fnoff)
return &InlineStackReader{dwarf: dwarf, reader: reader, entry: nil, depth: 0, pc: uint64(pc)}
}
// Next reads next inlined call in the stack, returns false if there aren't any.
func (irdr *InlineStackReader) Next() bool {
if irdr.err != nil {
return false
}
for {
irdr.entry, irdr.err = irdr.reader.Next()
if irdr.entry == nil || irdr.err != nil {
return false
}
switch irdr.entry.Tag {
case 0:
irdr.depth--
if irdr.depth == 0 {
return false
}
case dwarf.TagLexDwarfBlock, dwarf.TagSubprogram, dwarf.TagInlinedSubroutine:
var recur bool
if irdr.pc != 0 {
recur, irdr.err = entryRangesContains(irdr.dwarf, irdr.entry, irdr.pc)
} else {
recur = true
}
if recur {
irdr.depth++
if irdr.entry.Tag == dwarf.TagInlinedSubroutine {
return true
}
} else {
if irdr.depth == 0 {
return false
}
irdr.reader.SkipChildren()
}
default:
irdr.reader.SkipChildren()
}
}
}
// Entry returns the DIE for the current inlined call.
func (irdr *InlineStackReader) Entry() *dwarf.Entry {
return irdr.entry
}
// Err returns an error, if any was encountered.
func (irdr *InlineStackReader) Err() error {
return irdr.err
}
// SkipChildren skips all children of the current inlined call.
func (irdr *InlineStackReader) SkipChildren() {
irdr.reader.SkipChildren()
}

View File

@ -0,0 +1,114 @@
package reader
import (
"errors"
"debug/dwarf"
)
// RelAddr is an address relative to the static base. For normal executables
// this is just a normal memory address, for PIE it's a relative address.
type RelAddr uint64
func ToRelAddr(addr uint64, staticBase uint64) RelAddr {
return RelAddr(addr - staticBase)
}
// VariableReader provides a way of reading the local variables and formal
// parameters of a function that are visible at the specified PC address.
type VariableReader struct {
dwarf *dwarf.Data
reader *dwarf.Reader
entry *dwarf.Entry
depth int
onlyVisible bool
pc uint64
line int
err error
}
// Variables returns a VariableReader for the function or lexical block at off.
// If onlyVisible is true only variables visible at pc will be returned by
// the VariableReader.
func Variables(dwarf *dwarf.Data, off dwarf.Offset, pc RelAddr, line int, onlyVisible bool) *VariableReader {
reader := dwarf.Reader()
reader.Seek(off)
return &VariableReader{dwarf: dwarf, reader: reader, entry: nil, depth: 0, onlyVisible: onlyVisible, pc: uint64(pc), line: line, err: nil}
}
// Next reads the next variable entry, returns false if there aren't any.
func (vrdr *VariableReader) Next() bool {
if vrdr.err != nil {
return false
}
for {
vrdr.entry, vrdr.err = vrdr.reader.Next()
if vrdr.entry == nil || vrdr.err != nil {
return false
}
switch vrdr.entry.Tag {
case 0:
vrdr.depth--
if vrdr.depth == 0 {
return false
}
case dwarf.TagLexDwarfBlock, dwarf.TagSubprogram, dwarf.TagInlinedSubroutine:
recur := true
if vrdr.onlyVisible {
recur, vrdr.err = entryRangesContains(vrdr.dwarf, vrdr.entry, vrdr.pc)
if vrdr.err != nil {
return false
}
}
if recur && vrdr.entry.Children {
vrdr.depth++
} else {
if vrdr.depth == 0 {
return false
}
vrdr.reader.SkipChildren()
}
default:
if vrdr.depth == 0 {
vrdr.err = errors.New("offset was not lexical block or subprogram")
return false
}
if declLine, ok := vrdr.entry.Val(dwarf.AttrDeclLine).(int64); !ok || vrdr.line >= int(declLine) {
return true
}
}
}
}
func entryRangesContains(dwarf *dwarf.Data, entry *dwarf.Entry, pc uint64) (bool, error) {
rngs, err := dwarf.Ranges(entry)
if err != nil {
return false, err
}
for _, rng := range rngs {
if pc >= rng[0] && pc < rng[1] {
return true, nil
}
}
return false, nil
}
// Entry returns the current variable entry.
func (vrdr *VariableReader) Entry() *dwarf.Entry {
return vrdr.entry
}
// Depth returns the depth of the current scope
func (vrdr *VariableReader) Depth() int {
return vrdr.depth
}
// Err returns the error if there was one.
func (vrdr *VariableReader) Err() error {
return vrdr.err
}

151
vendor/github.com/go-delve/delve/pkg/dwarf/util/buf.go generated vendored Normal file
View File

@ -0,0 +1,151 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Buffered reading and decoding of DWARF data streams.
package util
import (
"debug/dwarf"
"fmt"
)
// Data buffer being decoded.
type buf struct {
dwarf *dwarf.Data
format dataFormat
name string
off dwarf.Offset
data []byte
Err error
}
// Data format, other than byte order. This affects the handling of
// certain field formats.
type dataFormat interface {
// DWARF version number. Zero means unknown.
version() int
// 64-bit DWARF format?
dwarf64() (dwarf64 bool, isKnown bool)
// Size of an address, in bytes. Zero means unknown.
addrsize() int
}
// Some parts of DWARF have no data format, e.g., abbrevs.
type UnknownFormat struct{}
func (u UnknownFormat) version() int {
return 0
}
func (u UnknownFormat) dwarf64() (bool, bool) {
return false, false
}
func (u UnknownFormat) addrsize() int {
return 0
}
func MakeBuf(d *dwarf.Data, format dataFormat, name string, off dwarf.Offset, data []byte) buf {
return buf{d, format, name, off, data, nil}
}
func (b *buf) slice(length int) buf {
n := *b
data := b.data
b.skip(length) // Will validate length.
n.data = data[:length]
return n
}
func (b *buf) Uint8() uint8 {
if len(b.data) < 1 {
b.error("underflow")
return 0
}
val := b.data[0]
b.data = b.data[1:]
b.off++
return val
}
func (b *buf) bytes(n int) []byte {
if len(b.data) < n {
b.error("underflow")
return nil
}
data := b.data[0:n]
b.data = b.data[n:]
b.off += dwarf.Offset(n)
return data
}
func (b *buf) skip(n int) { b.bytes(n) }
// string returns the NUL-terminated (C-like) string at the start of the buffer.
// The terminal NUL is discarded.
func (b *buf) string() string {
for i := 0; i < len(b.data); i++ {
if b.data[i] == 0 {
s := string(b.data[0:i])
b.data = b.data[i+1:]
b.off += dwarf.Offset(i + 1)
return s
}
}
b.error("underflow")
return ""
}
// Read a varint, which is 7 bits per byte, little endian.
// the 0x80 bit means read another byte.
func (b *buf) Varint() (c uint64, bits uint) {
for i := 0; i < len(b.data); i++ {
byte := b.data[i]
c |= uint64(byte&0x7F) << bits
bits += 7
if byte&0x80 == 0 {
b.off += dwarf.Offset(i + 1)
b.data = b.data[i+1:]
return c, bits
}
}
return 0, 0
}
// Unsigned int is just a varint.
func (b *buf) Uint() uint64 {
x, _ := b.Varint()
return x
}
// Signed int is a sign-extended varint.
func (b *buf) Int() int64 {
ux, bits := b.Varint()
x := int64(ux)
if x&(1<<(bits-1)) != 0 {
x |= -1 << bits
}
return x
}
// AssertEmpty checks that everything has been read from b.
func (b *buf) AssertEmpty() {
if len(b.data) == 0 {
return
}
if len(b.data) > 5 {
b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5]))
}
b.error(fmt.Sprintf("unexpected extra data: %x", b.data))
}
func (b *buf) error(s string) {
if b.Err == nil {
b.data = nil
b.Err = dwarf.DecodeError{b.name, b.off, s}
}
}

126
vendor/github.com/go-delve/delve/pkg/dwarf/util/util.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
package util
import (
"bytes"
"io"
)
// The Little Endian Base 128 format is defined in the DWARF v4 standard,
// section 7.6, page 161 and following.
// DecodeULEB128 decodes an unsigned Little Endian Base 128
// represented number.
func DecodeULEB128(buf *bytes.Buffer) (uint64, uint32) {
var (
result uint64
shift uint64
length uint32
)
if buf.Len() == 0 {
return 0, 0
}
for {
b, err := buf.ReadByte()
if err != nil {
panic("Could not parse ULEB128 value")
}
length++
result |= uint64((uint(b) & 0x7f) << shift)
// If high order bit is 1.
if b&0x80 == 0 {
break
}
shift += 7
}
return result, length
}
// DecodeSLEB128 decodes a signed Little Endian Base 128
// represented number.
func DecodeSLEB128(buf *bytes.Buffer) (int64, uint32) {
var (
b byte
err error
result int64
shift uint64
length uint32
)
if buf.Len() == 0 {
return 0, 0
}
for {
b, err = buf.ReadByte()
if err != nil {
panic("Could not parse SLEB128 value")
}
length++
result |= int64((int64(b) & 0x7f) << shift)
shift += 7
if b&0x80 == 0 {
break
}
}
if (shift < 8*uint64(length)) && (b&0x40 > 0) {
result |= -(1 << shift)
}
return result, length
}
// EncodeULEB128 encodes x to the unsigned Little Endian Base 128 format
// into out.
func EncodeULEB128(out io.ByteWriter, x uint64) {
for {
b := byte(x & 0x7f)
x = x >> 7
if x != 0 {
b = b | 0x80
}
out.WriteByte(b)
if x == 0 {
break
}
}
}
// EncodeSLEB128 encodes x to the signed Little Endian Base 128 format
// into out.
func EncodeSLEB128(out io.ByteWriter, x int64) {
for {
b := byte(x & 0x7f)
x >>= 7
signb := b & 0x40
last := false
if (x == 0 && signb == 0) || (x == -1 && signb != 0) {
last = true
} else {
b = b | 0x80
}
out.WriteByte(b)
if last {
break
}
}
}
func ParseString(data *bytes.Buffer) (string, uint32) {
str, err := data.ReadString(0x0)
if err != nil {
panic("Could not parse string")
}
return str[:len(str)-1], uint32(len(str))
}