proc/dwarf: LEB128 encode/decode in separate pkg (#3235)
This commit is contained in:
parent
3847b7a199
commit
13143680f7
@ -6,7 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Form represents a DWARF form kind (see Figure 20, page 160 and following,
|
// Form represents a DWARF form kind (see Figure 20, page 160 and following,
|
||||||
@ -229,19 +229,19 @@ func (b *Builder) makeAbbrevTable() []byte {
|
|||||||
var abbrev bytes.Buffer
|
var abbrev bytes.Buffer
|
||||||
|
|
||||||
for i := range b.abbrevs {
|
for i := range b.abbrevs {
|
||||||
util.EncodeULEB128(&abbrev, uint64(i+1))
|
leb128.EncodeUnsigned(&abbrev, uint64(i+1))
|
||||||
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].tag))
|
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].tag))
|
||||||
if b.abbrevs[i].children {
|
if b.abbrevs[i].children {
|
||||||
abbrev.WriteByte(0x01)
|
abbrev.WriteByte(0x01)
|
||||||
} else {
|
} else {
|
||||||
abbrev.WriteByte(0x00)
|
abbrev.WriteByte(0x00)
|
||||||
}
|
}
|
||||||
for j := range b.abbrevs[i].attr {
|
for j := range b.abbrevs[i].attr {
|
||||||
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].attr[j]))
|
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].attr[j]))
|
||||||
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].form[j]))
|
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].form[j]))
|
||||||
}
|
}
|
||||||
util.EncodeULEB128(&abbrev, 0)
|
leb128.EncodeUnsigned(&abbrev, 0)
|
||||||
util.EncodeULEB128(&abbrev, 0)
|
leb128.EncodeUnsigned(&abbrev, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return abbrev.Bytes()
|
return abbrev.Bytes()
|
||||||
|
@ -3,8 +3,8 @@ package dwarfbuilder
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LocEntry represents one entry of debug_loc.
|
// LocEntry represents one entry of debug_loc.
|
||||||
@ -23,9 +23,9 @@ func LocationBlock(args ...interface{}) []byte {
|
|||||||
case op.Opcode:
|
case op.Opcode:
|
||||||
buf.WriteByte(byte(x))
|
buf.WriteByte(byte(x))
|
||||||
case int:
|
case int:
|
||||||
util.EncodeSLEB128(&buf, int64(x))
|
leb128.EncodeSigned(&buf, int64(x))
|
||||||
case uint:
|
case uint:
|
||||||
util.EncodeULEB128(&buf, uint64(x))
|
leb128.EncodeUnsigned(&buf, uint64(x))
|
||||||
default:
|
default:
|
||||||
panic("unsupported value type")
|
panic("unsupported value type")
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -123,10 +124,10 @@ func parseFDE(ctx *parseContext) parsefunc {
|
|||||||
ctx.entries = append(ctx.entries, ctx.frame)
|
ctx.entries = append(ctx.entries, ctx.frame)
|
||||||
|
|
||||||
if ctx.parsingEHFrame() && len(ctx.frame.CIE.Augmentation) > 0 {
|
if ctx.parsingEHFrame() && len(ctx.frame.CIE.Augmentation) > 0 {
|
||||||
// If we are parsing a .eh_frame and we saw an agumentation string then we
|
// If we are parsing a .eh_frame and we saw an augmentation string then we
|
||||||
// need to read the augmentation data, which are encoded as a ULEB128
|
// need to read the augmentation data, which are encoded as a ULEB128
|
||||||
// size followed by 'size' bytes.
|
// size followed by 'size' bytes.
|
||||||
n, _ := util.DecodeULEB128(reader)
|
n, _ := leb128.DecodeUnsigned(reader)
|
||||||
reader.Seek(int64(n), io.SeekCurrent)
|
reader.Seek(int64(n), io.SeekCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,23 +166,23 @@ func parseCIE(ctx *parseContext) parsefunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse code alignment factor
|
// parse code alignment factor
|
||||||
ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
|
ctx.common.CodeAlignmentFactor, _ = leb128.DecodeUnsigned(buf)
|
||||||
|
|
||||||
// parse data alignment factor
|
// parse data alignment factor
|
||||||
ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
|
ctx.common.DataAlignmentFactor, _ = leb128.DecodeSigned(buf)
|
||||||
|
|
||||||
// parse return address register
|
// parse return address register
|
||||||
if ctx.parsingEHFrame() && ctx.common.Version == 1 {
|
if ctx.parsingEHFrame() && ctx.common.Version == 1 {
|
||||||
b, _ := buf.ReadByte()
|
b, _ := buf.ReadByte()
|
||||||
ctx.common.ReturnAddressRegister = uint64(b)
|
ctx.common.ReturnAddressRegister = uint64(b)
|
||||||
} else {
|
} else {
|
||||||
ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
|
ctx.common.ReturnAddressRegister, _ = leb128.DecodeUnsigned(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.common.ptrEncAddr = ptrEncAbs
|
ctx.common.ptrEncAddr = ptrEncAbs
|
||||||
|
|
||||||
if ctx.parsingEHFrame() && len(ctx.common.Augmentation) > 0 {
|
if ctx.parsingEHFrame() && len(ctx.common.Augmentation) > 0 {
|
||||||
_, _ = util.DecodeULEB128(buf) // augmentation data length
|
_, _ = leb128.DecodeUnsigned(buf) // augmentation data length
|
||||||
for i := 1; i < len(ctx.common.Augmentation); i++ {
|
for i := 1; i < len(ctx.common.Augmentation); i++ {
|
||||||
switch ctx.common.Augmentation[i] {
|
switch ctx.common.Augmentation[i] {
|
||||||
case 'L':
|
case 'L':
|
||||||
@ -231,7 +232,7 @@ func parseCIE(ctx *parseContext) parsefunc {
|
|||||||
// The parameter addr is the address that the current byte of 'buf' will be
|
// The parameter addr is the address that the current byte of 'buf' will be
|
||||||
// mapped to when the executable file containing the eh_frame section being
|
// mapped to when the executable file containing the eh_frame section being
|
||||||
// parse is loaded in memory.
|
// parse is loaded in memory.
|
||||||
func (ctx *parseContext) readEncodedPtr(addr uint64, buf util.ByteReaderWithLen, ptrEnc ptrEnc) uint64 {
|
func (ctx *parseContext) readEncodedPtr(addr uint64, buf leb128.Reader, ptrEnc ptrEnc) uint64 {
|
||||||
if ptrEnc == ptrEncOmit {
|
if ptrEnc == ptrEncOmit {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -242,7 +243,7 @@ func (ctx *parseContext) readEncodedPtr(addr uint64, buf util.ByteReaderWithLen,
|
|||||||
case ptrEncAbs, ptrEncSigned:
|
case ptrEncAbs, ptrEncSigned:
|
||||||
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, ctx.ptrSize)
|
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, ctx.ptrSize)
|
||||||
case ptrEncUleb:
|
case ptrEncUleb:
|
||||||
ptr, _ = util.DecodeULEB128(buf)
|
ptr, _ = leb128.DecodeUnsigned(buf)
|
||||||
case ptrEncUdata2:
|
case ptrEncUdata2:
|
||||||
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 2)
|
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 2)
|
||||||
case ptrEncSdata2:
|
case ptrEncSdata2:
|
||||||
@ -256,7 +257,7 @@ func (ctx *parseContext) readEncodedPtr(addr uint64, buf util.ByteReaderWithLen,
|
|||||||
case ptrEncUdata8, ptrEncSdata8:
|
case ptrEncUdata8, ptrEncSdata8:
|
||||||
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 8)
|
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 8)
|
||||||
case ptrEncSleb:
|
case ptrEncSleb:
|
||||||
n, _ := util.DecodeSLEB128(buf)
|
n, _ := leb128.DecodeSigned(buf)
|
||||||
ptr = uint64(n)
|
ptr = uint64(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DWRule wrapper of rule defined for register values.
|
// DWRule wrapper of rule defined for register values.
|
||||||
@ -254,7 +254,7 @@ func offset(frame *FrameContext) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
reg = b & low_6_offset
|
reg = b & low_6_offset
|
||||||
offset, _ = util.DecodeULEB128(frame.buf)
|
offset, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
|
frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
|
||||||
@ -284,26 +284,26 @@ func setloc(frame *FrameContext) {
|
|||||||
|
|
||||||
func offsetextended(frame *FrameContext) {
|
func offsetextended(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ = util.DecodeULEB128(frame.buf)
|
offset, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
|
frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undefined(frame *FrameContext) {
|
func undefined(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
|
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
|
||||||
}
|
}
|
||||||
|
|
||||||
func samevalue(frame *FrameContext) {
|
func samevalue(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
frame.Regs[reg] = DWRule{Rule: RuleSameVal}
|
frame.Regs[reg] = DWRule{Rule: RuleSameVal}
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(frame *FrameContext) {
|
func register(frame *FrameContext) {
|
||||||
reg1, _ := util.DecodeULEB128(frame.buf)
|
reg1, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
reg2, _ := util.DecodeULEB128(frame.buf)
|
reg2, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
|
frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ func restorestate(frame *FrameContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func restoreextended(frame *FrameContext) {
|
func restoreextended(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
|
|
||||||
oldrule, ok := frame.initialRegs[reg]
|
oldrule, ok := frame.initialRegs[reg]
|
||||||
if ok {
|
if ok {
|
||||||
@ -327,8 +327,8 @@ func restoreextended(frame *FrameContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defcfa(frame *FrameContext) {
|
func defcfa(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ := util.DecodeULEB128(frame.buf)
|
offset, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
|
|
||||||
frame.CFA.Rule = RuleCFA
|
frame.CFA.Rule = RuleCFA
|
||||||
frame.CFA.Reg = reg
|
frame.CFA.Reg = reg
|
||||||
@ -336,18 +336,18 @@ func defcfa(frame *FrameContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defcfaregister(frame *FrameContext) {
|
func defcfaregister(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
frame.CFA.Reg = reg
|
frame.CFA.Reg = reg
|
||||||
}
|
}
|
||||||
|
|
||||||
func defcfaoffset(frame *FrameContext) {
|
func defcfaoffset(frame *FrameContext) {
|
||||||
offset, _ := util.DecodeULEB128(frame.buf)
|
offset, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
frame.CFA.Offset = int64(offset)
|
frame.CFA.Offset = int64(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func defcfasf(frame *FrameContext) {
|
func defcfasf(frame *FrameContext) {
|
||||||
reg, _ := util.DecodeULEB128(frame.buf)
|
reg, _ := leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ := util.DecodeSLEB128(frame.buf)
|
offset, _ := leb128.DecodeSigned(frame.buf)
|
||||||
|
|
||||||
frame.CFA.Rule = RuleCFA
|
frame.CFA.Rule = RuleCFA
|
||||||
frame.CFA.Reg = reg
|
frame.CFA.Reg = reg
|
||||||
@ -355,14 +355,14 @@ func defcfasf(frame *FrameContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defcfaoffsetsf(frame *FrameContext) {
|
func defcfaoffsetsf(frame *FrameContext) {
|
||||||
offset, _ := util.DecodeSLEB128(frame.buf)
|
offset, _ := leb128.DecodeSigned(frame.buf)
|
||||||
offset *= frame.dataAlignment
|
offset *= frame.dataAlignment
|
||||||
frame.CFA.Offset = offset
|
frame.CFA.Offset = offset
|
||||||
}
|
}
|
||||||
|
|
||||||
func defcfaexpression(frame *FrameContext) {
|
func defcfaexpression(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
l, _ = util.DecodeULEB128(frame.buf)
|
l, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
expr = frame.buf.Next(int(l))
|
expr = frame.buf.Next(int(l))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -372,8 +372,8 @@ func defcfaexpression(frame *FrameContext) {
|
|||||||
|
|
||||||
func expression(frame *FrameContext) {
|
func expression(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
l, _ = util.DecodeULEB128(frame.buf)
|
l, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
expr = frame.buf.Next(int(l))
|
expr = frame.buf.Next(int(l))
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -382,8 +382,8 @@ func expression(frame *FrameContext) {
|
|||||||
|
|
||||||
func offsetextendedsf(frame *FrameContext) {
|
func offsetextendedsf(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ = util.DecodeSLEB128(frame.buf)
|
offset, _ = leb128.DecodeSigned(frame.buf)
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset}
|
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset}
|
||||||
@ -391,8 +391,8 @@ func offsetextendedsf(frame *FrameContext) {
|
|||||||
|
|
||||||
func valoffset(frame *FrameContext) {
|
func valoffset(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ = util.DecodeULEB128(frame.buf)
|
offset, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
|
frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
|
||||||
@ -400,8 +400,8 @@ func valoffset(frame *FrameContext) {
|
|||||||
|
|
||||||
func valoffsetsf(frame *FrameContext) {
|
func valoffsetsf(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
offset, _ = util.DecodeSLEB128(frame.buf)
|
offset, _ = leb128.DecodeSigned(frame.buf)
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
|
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
|
||||||
@ -409,8 +409,8 @@ func valoffsetsf(frame *FrameContext) {
|
|||||||
|
|
||||||
func valexpression(frame *FrameContext) {
|
func valexpression(frame *FrameContext) {
|
||||||
var (
|
var (
|
||||||
reg, _ = util.DecodeULEB128(frame.buf)
|
reg, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
l, _ = util.DecodeULEB128(frame.buf)
|
l, _ = leb128.DecodeUnsigned(frame.buf)
|
||||||
expr = frame.buf.Next(int(l))
|
expr = frame.buf.Next(int(l))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
82
pkg/dwarf/leb128/decode.go
Normal file
82
pkg/dwarf/leb128/decode.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package leb128
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reader is a io.ByteReader with a Len method. This interface is
|
||||||
|
// satisfied by both bytes.Buffer and bytes.Reader.
|
||||||
|
type Reader interface {
|
||||||
|
io.ByteReader
|
||||||
|
io.Reader
|
||||||
|
Len() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeUnsigned decodes an unsigned Little Endian Base 128
|
||||||
|
// represented number.
|
||||||
|
func DecodeUnsigned(buf Reader) (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
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeSigned decodes a signed Little Endian Base 128
|
||||||
|
// represented number.
|
||||||
|
func DecodeSigned(buf Reader) (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
|
||||||
|
}
|
28
pkg/dwarf/leb128/decode_test.go
Normal file
28
pkg/dwarf/leb128/decode_test.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package leb128
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeUnsigned(t *testing.T) {
|
||||||
|
leb128 := bytes.NewBuffer([]byte{0xE5, 0x8E, 0x26})
|
||||||
|
|
||||||
|
n, c := DecodeUnsigned(leb128)
|
||||||
|
if n != 624485 {
|
||||||
|
t.Fatal("Number was not decoded properly, got: ", n, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c != 3 {
|
||||||
|
t.Fatal("Count not returned correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeSigned(t *testing.T) {
|
||||||
|
sleb128 := bytes.NewBuffer([]byte{0x9b, 0xf1, 0x59})
|
||||||
|
|
||||||
|
n, c := DecodeSigned(sleb128)
|
||||||
|
if n != -624485 {
|
||||||
|
t.Fatal("Number was not decoded properly, got: ", n, c)
|
||||||
|
}
|
||||||
|
}
|
4
pkg/dwarf/leb128/doc.go
Normal file
4
pkg/dwarf/leb128/doc.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Package leb128 provides encoders and decoders for The Little Endian Base 128 format.
|
||||||
|
// The Little Endian Base 128 format is defined in the DWARF v4 standard,
|
||||||
|
// section 7.6, page 161 and following.
|
||||||
|
package leb128
|
42
pkg/dwarf/leb128/encode.go
Normal file
42
pkg/dwarf/leb128/encode.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package leb128
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EncodeUnsigned encodes x to the unsigned Little Endian Base 128 format.
|
||||||
|
func EncodeUnsigned(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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeSigned encodes x to the signed Little Endian Base 128 format.
|
||||||
|
func EncodeSigned(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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
pkg/dwarf/leb128/encode_test.go
Normal file
42
pkg/dwarf/leb128/encode_test.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package leb128
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncodeUnsigned(t *testing.T) {
|
||||||
|
tc := []uint64{0x00, 0x7f, 0x80, 0x8f, 0xffff, 0xfffffff7}
|
||||||
|
for i := range tc {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
EncodeUnsigned(&buf, tc[i])
|
||||||
|
enc := append([]byte{}, buf.Bytes()...)
|
||||||
|
buf.Write([]byte{0x1, 0x2, 0x3})
|
||||||
|
out, c := DecodeUnsigned(&buf)
|
||||||
|
t.Logf("input %x output %x encoded %x", tc[i], out, enc)
|
||||||
|
if c != uint32(len(enc)) {
|
||||||
|
t.Errorf("wrong encode")
|
||||||
|
}
|
||||||
|
if out != tc[i] {
|
||||||
|
t.Errorf("wrong encode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeSigned(t *testing.T) {
|
||||||
|
tc := []int64{2, -2, 127, -127, 128, -128, 129, -129}
|
||||||
|
for i := range tc {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
EncodeSigned(&buf, tc[i])
|
||||||
|
enc := append([]byte{}, buf.Bytes()...)
|
||||||
|
buf.Write([]byte{0x1, 0x2, 0x3})
|
||||||
|
out, c := DecodeSigned(&buf)
|
||||||
|
t.Logf("input %x output %x encoded %x", tc[i], out, enc)
|
||||||
|
if c != uint32(len(enc)) {
|
||||||
|
t.Errorf("wrong encode")
|
||||||
|
}
|
||||||
|
if out != tc[i] {
|
||||||
|
t.Errorf("wrong encode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ func parseIncludeDirs5(info *DebugLineInfo, buf *bytes.Buffer) bool {
|
|||||||
if dirEntryFormReader == nil {
|
if dirEntryFormReader == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
dirCount, _ := util.DecodeULEB128(buf)
|
dirCount, _ := leb128.DecodeUnsigned(buf)
|
||||||
info.IncludeDirs = make([]string, 0, dirCount)
|
info.IncludeDirs = make([]string, 0, dirCount)
|
||||||
for i := uint64(0); i < dirCount; i++ {
|
for i := uint64(0); i < dirCount; i++ {
|
||||||
dirEntryFormReader.reset()
|
dirEntryFormReader.reset()
|
||||||
@ -242,9 +243,9 @@ func readFileEntry(info *DebugLineInfo, buf *bytes.Buffer, exitOnEmptyPath bool)
|
|||||||
entry.Path = strings.ReplaceAll(entry.Path, "\\", "/")
|
entry.Path = strings.ReplaceAll(entry.Path, "\\", "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.DirIdx, _ = util.DecodeULEB128(buf)
|
entry.DirIdx, _ = leb128.DecodeUnsigned(buf)
|
||||||
entry.LastModTime, _ = util.DecodeULEB128(buf)
|
entry.LastModTime, _ = leb128.DecodeUnsigned(buf)
|
||||||
entry.Length, _ = util.DecodeULEB128(buf)
|
entry.Length, _ = leb128.DecodeUnsigned(buf)
|
||||||
if !pathIsAbs(entry.Path) {
|
if !pathIsAbs(entry.Path) {
|
||||||
if entry.DirIdx < uint64(len(info.IncludeDirs)) {
|
if entry.DirIdx < uint64(len(info.IncludeDirs)) {
|
||||||
entry.Path = path.Join(info.IncludeDirs[entry.DirIdx], entry.Path)
|
entry.Path = path.Join(info.IncludeDirs[entry.DirIdx], entry.Path)
|
||||||
@ -276,7 +277,7 @@ func parseFileEntries5(info *DebugLineInfo, buf *bytes.Buffer) bool {
|
|||||||
if fileEntryFormReader == nil {
|
if fileEntryFormReader == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fileCount, _ := util.DecodeULEB128(buf)
|
fileCount, _ := leb128.DecodeUnsigned(buf)
|
||||||
info.FileNames = make([]*FileEntry, 0, fileCount)
|
info.FileNames = make([]*FileEntry, 0, fileCount)
|
||||||
for i := 0; i < int(fileCount); i++ {
|
for i := 0; i < int(fileCount); i++ {
|
||||||
var (
|
var (
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,8 +71,8 @@ func readEntryFormat(buf *bytes.Buffer, logf func(string, ...interface{})) *form
|
|||||||
formCodes: make([]uint64, count),
|
formCodes: make([]uint64, count),
|
||||||
}
|
}
|
||||||
for i := range r.contentTypes {
|
for i := range r.contentTypes {
|
||||||
r.contentTypes[i], _ = util.DecodeULEB128(buf)
|
r.contentTypes[i], _ = leb128.DecodeUnsigned(buf)
|
||||||
r.formCodes[i], _ = util.DecodeULEB128(buf)
|
r.formCodes[i], _ = leb128.DecodeUnsigned(buf)
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -94,7 +95,7 @@ func (rdr *formReader) next(buf *bytes.Buffer) bool {
|
|||||||
|
|
||||||
switch rdr.formCode {
|
switch rdr.formCode {
|
||||||
case _DW_FORM_block:
|
case _DW_FORM_block:
|
||||||
n, _ := util.DecodeULEB128(buf)
|
n, _ := leb128.DecodeUnsigned(buf)
|
||||||
rdr.readBlock(buf, n)
|
rdr.readBlock(buf, n)
|
||||||
|
|
||||||
case _DW_FORM_block1:
|
case _DW_FORM_block1:
|
||||||
@ -150,10 +151,10 @@ func (rdr *formReader) next(buf *bytes.Buffer) bool {
|
|||||||
rdr.readBlock(buf, 16)
|
rdr.readBlock(buf, 16)
|
||||||
|
|
||||||
case _DW_FORM_sdata:
|
case _DW_FORM_sdata:
|
||||||
rdr.i64, _ = util.DecodeSLEB128(buf)
|
rdr.i64, _ = leb128.DecodeSigned(buf)
|
||||||
|
|
||||||
case _DW_FORM_udata, _DW_FORM_strx:
|
case _DW_FORM_udata, _DW_FORM_strx:
|
||||||
rdr.u64, _ = util.DecodeULEB128(buf)
|
rdr.u64, _ = leb128.DecodeUnsigned(buf)
|
||||||
|
|
||||||
case _DW_FORM_string:
|
case _DW_FORM_string:
|
||||||
rdr.str, _ = util.ParseString(buf)
|
rdr.str, _ = util.ParseString(buf)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -409,7 +410,7 @@ func (sm *StateMachine) next() error {
|
|||||||
// in the prologue and do nothing with them
|
// in the prologue and do nothing with them
|
||||||
opnum := sm.dbl.Prologue.StdOpLengths[b-1]
|
opnum := sm.dbl.Prologue.StdOpLengths[b-1]
|
||||||
for i := 0; i < int(opnum); i++ {
|
for i := 0; i < int(opnum); i++ {
|
||||||
util.DecodeSLEB128(sm.buf)
|
leb128.DecodeSigned(sm.buf)
|
||||||
}
|
}
|
||||||
fmt.Printf("unknown opcode %d(0x%x), %d arguments, file %s, line %d, address 0x%x\n", b, b, opnum, sm.file, sm.line, sm.address)
|
fmt.Printf("unknown opcode %d(0x%x), %d arguments, file %s, line %d, address 0x%x\n", b, b, opnum, sm.file, sm.line, sm.address)
|
||||||
}
|
}
|
||||||
@ -432,7 +433,7 @@ func execSpecialOpcode(sm *StateMachine, instr byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func execExtendedOpcode(sm *StateMachine, buf *bytes.Buffer) {
|
func execExtendedOpcode(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
_, _ = util.DecodeULEB128(buf)
|
_, _ = leb128.DecodeUnsigned(buf)
|
||||||
b, _ := buf.ReadByte()
|
b, _ := buf.ReadByte()
|
||||||
if fn, ok := extendedopcodes[b]; ok {
|
if fn, ok := extendedopcodes[b]; ok {
|
||||||
fn(sm, buf)
|
fn(sm, buf)
|
||||||
@ -444,18 +445,18 @@ func copyfn(sm *StateMachine, buf *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func advancepc(sm *StateMachine, buf *bytes.Buffer) {
|
func advancepc(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
addr, _ := util.DecodeULEB128(buf)
|
addr, _ := leb128.DecodeUnsigned(buf)
|
||||||
sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength)
|
sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
func advanceline(sm *StateMachine, buf *bytes.Buffer) {
|
func advanceline(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
line, _ := util.DecodeSLEB128(buf)
|
line, _ := leb128.DecodeSigned(buf)
|
||||||
sm.line += int(line)
|
sm.line += int(line)
|
||||||
sm.lastDelta = int(line)
|
sm.lastDelta = int(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setfile(sm *StateMachine, buf *bytes.Buffer) {
|
func setfile(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
i, _ := util.DecodeULEB128(buf)
|
i, _ := leb128.DecodeUnsigned(buf)
|
||||||
if sm.dbl.Prologue.Version < 5 {
|
if sm.dbl.Prologue.Version < 5 {
|
||||||
// in DWARF v5 files are indexed starting from 0, in v4 and prior the index starts at 1
|
// in DWARF v5 files are indexed starting from 0, in v4 and prior the index starts at 1
|
||||||
i--
|
i--
|
||||||
@ -473,7 +474,7 @@ func setfile(sm *StateMachine, buf *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
|
func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
c, _ := util.DecodeULEB128(buf)
|
c, _ := leb128.DecodeUnsigned(buf)
|
||||||
sm.column = uint(c)
|
sm.column = uint(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +511,7 @@ func setaddress(sm *StateMachine, buf *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setdiscriminator(sm *StateMachine, buf *bytes.Buffer) {
|
func setdiscriminator(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
_, _ = util.DecodeULEB128(buf)
|
_, _ = leb128.DecodeUnsigned(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func definefile(sm *StateMachine, buf *bytes.Buffer) {
|
func definefile(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
@ -528,6 +529,6 @@ func epiloguebegin(sm *StateMachine, buf *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setisa(sm *StateMachine, buf *bytes.Buffer) {
|
func setisa(sm *StateMachine, buf *bytes.Buffer) {
|
||||||
c, _ := util.DecodeULEB128(buf)
|
c, _ := leb128.DecodeUnsigned(buf)
|
||||||
sm.isa = c
|
sm.isa = c
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -136,7 +137,7 @@ func TestMultipleSequences(t *testing.T) {
|
|||||||
|
|
||||||
write_DW_LNE_set_address := func(addr uint64) {
|
write_DW_LNE_set_address := func(addr uint64) {
|
||||||
instr.WriteByte(0)
|
instr.WriteByte(0)
|
||||||
util.EncodeULEB128(instr, 9) // 1 + ptr_size
|
leb128.EncodeUnsigned(instr, 9) // 1 + ptr_size
|
||||||
instr.WriteByte(DW_LINE_set_address)
|
instr.WriteByte(DW_LINE_set_address)
|
||||||
util.WriteUint(instr, binary.LittleEndian, ptrSize, addr)
|
util.WriteUint(instr, binary.LittleEndian, ptrSize, addr)
|
||||||
}
|
}
|
||||||
@ -147,17 +148,17 @@ func TestMultipleSequences(t *testing.T) {
|
|||||||
|
|
||||||
write_DW_LNS_advance_pc := func(off uint64) {
|
write_DW_LNS_advance_pc := func(off uint64) {
|
||||||
instr.WriteByte(DW_LNS_advance_pc)
|
instr.WriteByte(DW_LNS_advance_pc)
|
||||||
util.EncodeULEB128(instr, off)
|
leb128.EncodeUnsigned(instr, off)
|
||||||
}
|
}
|
||||||
|
|
||||||
write_DW_LNS_advance_line := func(off int64) {
|
write_DW_LNS_advance_line := func(off int64) {
|
||||||
instr.WriteByte(DW_LNS_advance_line)
|
instr.WriteByte(DW_LNS_advance_line)
|
||||||
util.EncodeSLEB128(instr, off)
|
leb128.EncodeSigned(instr, off)
|
||||||
}
|
}
|
||||||
|
|
||||||
write_DW_LNE_end_sequence := func() {
|
write_DW_LNE_end_sequence := func() {
|
||||||
instr.WriteByte(0)
|
instr.WriteByte(0)
|
||||||
util.EncodeULEB128(instr, 1)
|
leb128.EncodeUnsigned(instr, 1)
|
||||||
instr.WriteByte(DW_LINE_end_sequence)
|
instr.WriteByte(DW_LINE_end_sequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ func (it *loclistsIterator) next() bool {
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
case _DW_LLE_base_addressx:
|
case _DW_LLE_base_addressx:
|
||||||
baseIdx, _ := util.DecodeULEB128(it.buf)
|
baseIdx, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
it.err = err
|
it.err = err
|
||||||
return false
|
return false
|
||||||
@ -126,8 +127,8 @@ func (it *loclistsIterator) next() bool {
|
|||||||
it.onRange = false
|
it.onRange = false
|
||||||
|
|
||||||
case _DW_LLE_startx_endx:
|
case _DW_LLE_startx_endx:
|
||||||
startIdx, _ := util.DecodeULEB128(it.buf)
|
startIdx, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
endIdx, _ := util.DecodeULEB128(it.buf)
|
endIdx, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
it.readInstr()
|
it.readInstr()
|
||||||
|
|
||||||
it.start, it.err = it.debugAddr.Get(startIdx)
|
it.start, it.err = it.debugAddr.Get(startIdx)
|
||||||
@ -137,8 +138,8 @@ func (it *loclistsIterator) next() bool {
|
|||||||
it.onRange = true
|
it.onRange = true
|
||||||
|
|
||||||
case _DW_LLE_startx_length:
|
case _DW_LLE_startx_length:
|
||||||
startIdx, _ := util.DecodeULEB128(it.buf)
|
startIdx, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
length, _ := util.DecodeULEB128(it.buf)
|
length, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
it.readInstr()
|
it.readInstr()
|
||||||
|
|
||||||
it.start, it.err = it.debugAddr.Get(startIdx)
|
it.start, it.err = it.debugAddr.Get(startIdx)
|
||||||
@ -146,8 +147,8 @@ func (it *loclistsIterator) next() bool {
|
|||||||
it.onRange = true
|
it.onRange = true
|
||||||
|
|
||||||
case _DW_LLE_offset_pair:
|
case _DW_LLE_offset_pair:
|
||||||
off1, _ := util.DecodeULEB128(it.buf)
|
off1, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
off2, _ := util.DecodeULEB128(it.buf)
|
off2, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
it.readInstr()
|
it.readInstr()
|
||||||
|
|
||||||
it.start = it.base + off1
|
it.start = it.base + off1
|
||||||
@ -172,7 +173,7 @@ func (it *loclistsIterator) next() bool {
|
|||||||
|
|
||||||
case _DW_LLE_start_length:
|
case _DW_LLE_start_length:
|
||||||
it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
|
it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
|
||||||
length, _ := util.DecodeULEB128(it.buf)
|
length, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
it.readInstr()
|
it.readInstr()
|
||||||
it.end = it.start + length
|
it.end = it.start + length
|
||||||
it.onRange = true
|
it.onRange = true
|
||||||
@ -188,6 +189,6 @@ func (it *loclistsIterator) next() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *loclistsIterator) readInstr() {
|
func (it *loclistsIterator) readInstr() {
|
||||||
length, _ := util.DecodeULEB128(it.buf)
|
length, _ := leb128.DecodeUnsigned(it.buf)
|
||||||
it.instr = it.buf.Next(int(length))
|
it.instr = it.buf.Next(int(length))
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoclist5(t *testing.T) {
|
func TestLoclist5(t *testing.T) {
|
||||||
@ -14,7 +14,7 @@ func TestLoclist5(t *testing.T) {
|
|||||||
p32 := func(n uint32) { binary.Write(buf, binary.LittleEndian, n) }
|
p32 := func(n uint32) { binary.Write(buf, binary.LittleEndian, n) }
|
||||||
p16 := func(n uint16) { binary.Write(buf, binary.LittleEndian, n) }
|
p16 := func(n uint16) { binary.Write(buf, binary.LittleEndian, n) }
|
||||||
p8 := func(n uint8) { binary.Write(buf, binary.LittleEndian, n) }
|
p8 := func(n uint8) { binary.Write(buf, binary.LittleEndian, n) }
|
||||||
uleb := func(n uint64) { util.EncodeULEB128(buf, n) }
|
uleb := func(n uint64) { leb128.EncodeUnsigned(buf, n) }
|
||||||
|
|
||||||
p32(0x0) // length (use 0 because it is ignored)
|
p32(0x0) // length (use 0 because it is ignored)
|
||||||
p16(0x5) // version
|
p16(0x5) // version
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
"github.com/go-delve/delve/pkg/dwarf/util"
|
"github.com/go-delve/delve/pkg/dwarf/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -130,11 +131,11 @@ func PrettyPrint(out io.Writer, instructions []byte, regnumToName func(uint64) s
|
|||||||
var regnum uint64
|
var regnum uint64
|
||||||
switch arg {
|
switch arg {
|
||||||
case 's':
|
case 's':
|
||||||
n, _ := util.DecodeSLEB128(in)
|
n, _ := leb128.DecodeSigned(in)
|
||||||
regnum = uint64(n)
|
regnum = uint64(n)
|
||||||
fmt.Fprintf(out, "%#x ", n)
|
fmt.Fprintf(out, "%#x ", n)
|
||||||
case 'u':
|
case 'u':
|
||||||
n, _ := util.DecodeULEB128(in)
|
n, _ := leb128.DecodeUnsigned(in)
|
||||||
regnum = n
|
regnum = n
|
||||||
fmt.Fprintf(out, "%#x ", n)
|
fmt.Fprintf(out, "%#x ", n)
|
||||||
case '1':
|
case '1':
|
||||||
@ -154,7 +155,7 @@ func PrettyPrint(out io.Writer, instructions []byte, regnumToName func(uint64) s
|
|||||||
binary.Read(in, binary.LittleEndian, &x)
|
binary.Read(in, binary.LittleEndian, &x)
|
||||||
fmt.Fprintf(out, "%#x ", x)
|
fmt.Fprintf(out, "%#x ", x)
|
||||||
case 'B':
|
case 'B':
|
||||||
sz, _ := util.DecodeULEB128(in)
|
sz, _ := leb128.DecodeUnsigned(in)
|
||||||
data := make([]byte, sz)
|
data := make([]byte, sz)
|
||||||
sz2, _ := in.Read(data)
|
sz2, _ := in.Read(data)
|
||||||
data = data[:sz2]
|
data = data[:sz2]
|
||||||
@ -189,7 +190,7 @@ func (ctxt *context) closeLoc(opcode0 Opcode, piece Piece) error {
|
|||||||
|
|
||||||
switch opcode {
|
switch opcode {
|
||||||
case DW_OP_piece:
|
case DW_OP_piece:
|
||||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
|
||||||
piece.Size = int(sz)
|
piece.Size = int(sz)
|
||||||
ctxt.pieces = append(ctxt.pieces, piece)
|
ctxt.pieces = append(ctxt.pieces, piece)
|
||||||
return nil
|
return nil
|
||||||
@ -222,19 +223,19 @@ func addr(opcode Opcode, ctxt *context) error {
|
|||||||
|
|
||||||
func plusuconsts(opcode Opcode, ctxt *context) error {
|
func plusuconsts(opcode Opcode, ctxt *context) error {
|
||||||
slen := len(ctxt.stack)
|
slen := len(ctxt.stack)
|
||||||
num, _ := util.DecodeULEB128(ctxt.buf)
|
num, _ := leb128.DecodeUnsigned(ctxt.buf)
|
||||||
ctxt.stack[slen-1] = ctxt.stack[slen-1] + int64(num)
|
ctxt.stack[slen-1] = ctxt.stack[slen-1] + int64(num)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func consts(opcode Opcode, ctxt *context) error {
|
func consts(opcode Opcode, ctxt *context) error {
|
||||||
num, _ := util.DecodeSLEB128(ctxt.buf)
|
num, _ := leb128.DecodeSigned(ctxt.buf)
|
||||||
ctxt.stack = append(ctxt.stack, num)
|
ctxt.stack = append(ctxt.stack, num)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func framebase(opcode Opcode, ctxt *context) error {
|
func framebase(opcode Opcode, ctxt *context) error {
|
||||||
num, _ := util.DecodeSLEB128(ctxt.buf)
|
num, _ := leb128.DecodeSigned(ctxt.buf)
|
||||||
ctxt.stack = append(ctxt.stack, ctxt.FrameBase+num)
|
ctxt.stack = append(ctxt.stack, ctxt.FrameBase+num)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -242,7 +243,7 @@ func framebase(opcode Opcode, ctxt *context) error {
|
|||||||
func register(opcode Opcode, ctxt *context) error {
|
func register(opcode Opcode, ctxt *context) error {
|
||||||
var regnum uint64
|
var regnum uint64
|
||||||
if opcode == DW_OP_regx {
|
if opcode == DW_OP_regx {
|
||||||
regnum, _ = util.DecodeULEB128(ctxt.buf)
|
regnum, _ = leb128.DecodeUnsigned(ctxt.buf)
|
||||||
} else {
|
} else {
|
||||||
regnum = uint64(opcode - DW_OP_reg0)
|
regnum = uint64(opcode - DW_OP_reg0)
|
||||||
}
|
}
|
||||||
@ -252,11 +253,11 @@ func register(opcode Opcode, ctxt *context) error {
|
|||||||
func bregister(opcode Opcode, ctxt *context) error {
|
func bregister(opcode Opcode, ctxt *context) error {
|
||||||
var regnum uint64
|
var regnum uint64
|
||||||
if opcode == DW_OP_bregx {
|
if opcode == DW_OP_bregx {
|
||||||
regnum, _ = util.DecodeULEB128(ctxt.buf)
|
regnum, _ = leb128.DecodeUnsigned(ctxt.buf)
|
||||||
} else {
|
} else {
|
||||||
regnum = uint64(opcode - DW_OP_breg0)
|
regnum = uint64(opcode - DW_OP_breg0)
|
||||||
}
|
}
|
||||||
offset, _ := util.DecodeSLEB128(ctxt.buf)
|
offset, _ := leb128.DecodeSigned(ctxt.buf)
|
||||||
if ctxt.Reg(regnum) == nil {
|
if ctxt.Reg(regnum) == nil {
|
||||||
return fmt.Errorf("register %d not available", regnum)
|
return fmt.Errorf("register %d not available", regnum)
|
||||||
}
|
}
|
||||||
@ -265,7 +266,7 @@ func bregister(opcode Opcode, ctxt *context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func piece(opcode Opcode, ctxt *context) error {
|
func piece(opcode Opcode, ctxt *context) error {
|
||||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
|
||||||
|
|
||||||
if len(ctxt.stack) == 0 {
|
if len(ctxt.stack) == 0 {
|
||||||
// nothing on the stack means this piece is unavailable (padding,
|
// nothing on the stack means this piece is unavailable (padding,
|
||||||
@ -340,7 +341,7 @@ func constns(opcode Opcode, ctxt *context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func constu(opcode Opcode, ctxt *context) error {
|
func constu(opcode Opcode, ctxt *context) error {
|
||||||
num, _ := util.DecodeULEB128(ctxt.buf)
|
num, _ := leb128.DecodeUnsigned(ctxt.buf)
|
||||||
ctxt.stack = append(ctxt.stack, int64(num))
|
ctxt.stack = append(ctxt.stack, int64(num))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -516,7 +517,7 @@ func stackvalue(_ Opcode, ctxt *context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func implicitvalue(_ Opcode, ctxt *context) error {
|
func implicitvalue(_ Opcode, ctxt *context) error {
|
||||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
|
||||||
block := make([]byte, sz)
|
block := make([]byte, sz)
|
||||||
n, _ := ctxt.buf.Read(block)
|
n, _ := ctxt.buf.Read(block)
|
||||||
if uint64(n) != sz {
|
if uint64(n) != sz {
|
||||||
|
@ -6,125 +6,50 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/dwarf/leb128"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ByteReaderWithLen is a io.ByteReader with a Len method. This interface is
|
// ByteReaderWithLen is a io.ByteReader with a Len method. This interface is
|
||||||
// satisified by both bytes.Buffer and bytes.Reader.
|
// satisfied by both bytes.Buffer and bytes.Reader.
|
||||||
|
//
|
||||||
|
// Deprecated: use leb128.Reader.
|
||||||
type ByteReaderWithLen interface {
|
type ByteReaderWithLen interface {
|
||||||
io.ByteReader
|
io.ByteReader
|
||||||
io.Reader
|
io.Reader
|
||||||
Len() int
|
Len() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// DecodeULEB128 decodes an unsigned Little Endian Base 128
|
||||||
// represented number.
|
// represented number.
|
||||||
|
//
|
||||||
|
// Deprecated: use leb128.DecodeUnsigned.
|
||||||
func DecodeULEB128(buf ByteReaderWithLen) (uint64, uint32) {
|
func DecodeULEB128(buf ByteReaderWithLen) (uint64, uint32) {
|
||||||
var (
|
return leb128.DecodeUnsigned(buf)
|
||||||
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
|
// DecodeSLEB128 decodes a signed Little Endian Base 128
|
||||||
// represented number.
|
// represented number.
|
||||||
|
//
|
||||||
|
// Deprecated: use leb128.DecodeUnsigned.
|
||||||
func DecodeSLEB128(buf ByteReaderWithLen) (int64, uint32) {
|
func DecodeSLEB128(buf ByteReaderWithLen) (int64, uint32) {
|
||||||
var (
|
return leb128.DecodeSigned(buf)
|
||||||
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
|
// EncodeULEB128 encodes x to the unsigned Little Endian Base 128 format
|
||||||
// into out.
|
// into out.
|
||||||
|
//
|
||||||
|
// Deprecated: use leb128.EncodeUnsigned.
|
||||||
func EncodeULEB128(out io.ByteWriter, x uint64) {
|
func EncodeULEB128(out io.ByteWriter, x uint64) {
|
||||||
for {
|
leb128.EncodeUnsigned(out, x)
|
||||||
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
|
// EncodeSLEB128 encodes x to the signed Little Endian Base 128 format
|
||||||
// into out.
|
// into out.
|
||||||
|
//
|
||||||
|
// Deprecated: use leb128.EncodeSigned.
|
||||||
func EncodeSLEB128(out io.ByteWriter, x int64) {
|
func EncodeSLEB128(out io.ByteWriter, x int64) {
|
||||||
for {
|
leb128.EncodeSigned(out, x)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseString reads a null-terminated string from data.
|
// ParseString reads a null-terminated string from data.
|
||||||
|
@ -5,64 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDecodeULEB128(t *testing.T) {
|
|
||||||
var leb128 = bytes.NewBuffer([]byte{0xE5, 0x8E, 0x26})
|
|
||||||
|
|
||||||
n, c := DecodeULEB128(leb128)
|
|
||||||
if n != 624485 {
|
|
||||||
t.Fatal("Number was not decoded properly, got: ", n, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c != 3 {
|
|
||||||
t.Fatal("Count not returned correctly")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecodeSLEB128(t *testing.T) {
|
|
||||||
sleb128 := bytes.NewBuffer([]byte{0x9b, 0xf1, 0x59})
|
|
||||||
|
|
||||||
n, c := DecodeSLEB128(sleb128)
|
|
||||||
if n != -624485 {
|
|
||||||
t.Fatal("Number was not decoded properly, got: ", n, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncodeULEB128(t *testing.T) {
|
|
||||||
tc := []uint64{0x00, 0x7f, 0x80, 0x8f, 0xffff, 0xfffffff7}
|
|
||||||
for i := range tc {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
EncodeULEB128(&buf, tc[i])
|
|
||||||
enc := append([]byte{}, buf.Bytes()...)
|
|
||||||
buf.Write([]byte{0x1, 0x2, 0x3})
|
|
||||||
out, c := DecodeULEB128(&buf)
|
|
||||||
t.Logf("input %x output %x encoded %x", tc[i], out, enc)
|
|
||||||
if c != uint32(len(enc)) {
|
|
||||||
t.Errorf("wrong encode")
|
|
||||||
}
|
|
||||||
if out != tc[i] {
|
|
||||||
t.Errorf("wrong encode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncodeSLEB128(t *testing.T) {
|
|
||||||
tc := []int64{2, -2, 127, -127, 128, -128, 129, -129}
|
|
||||||
for i := range tc {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
EncodeSLEB128(&buf, tc[i])
|
|
||||||
enc := append([]byte{}, buf.Bytes()...)
|
|
||||||
buf.Write([]byte{0x1, 0x2, 0x3})
|
|
||||||
out, c := DecodeSLEB128(&buf)
|
|
||||||
t.Logf("input %x output %x encoded %x", tc[i], out, enc)
|
|
||||||
if c != uint32(len(enc)) {
|
|
||||||
t.Errorf("wrong encode")
|
|
||||||
}
|
|
||||||
if out != tc[i] {
|
|
||||||
t.Errorf("wrong encode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseString(t *testing.T) {
|
func TestParseString(t *testing.T) {
|
||||||
bstr := bytes.NewBuffer([]byte{'h', 'i', 0x0, 0xFF, 0xCC})
|
bstr := bytes.NewBuffer([]byte{'h', 'i', 0x0, 0xFF, 0xCC})
|
||||||
str, _ := ParseString(bstr)
|
str, _ := ParseString(bstr)
|
||||||
|
Loading…
Reference in New Issue
Block a user