proc/dwarf: LEB128 encode/decode in separate pkg (#3235)

This commit is contained in:
Oleksandr Redko 2023-01-10 22:29:58 +02:00 committed by GitHub
parent 3847b7a199
commit 13143680f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 314 additions and 242 deletions

@ -6,7 +6,7 @@ import (
"encoding/binary"
"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,
@ -229,19 +229,19 @@ func (b *Builder) makeAbbrevTable() []byte {
var abbrev bytes.Buffer
for i := range b.abbrevs {
util.EncodeULEB128(&abbrev, uint64(i+1))
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].tag))
leb128.EncodeUnsigned(&abbrev, uint64(i+1))
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].tag))
if b.abbrevs[i].children {
abbrev.WriteByte(0x01)
} else {
abbrev.WriteByte(0x00)
}
for j := range b.abbrevs[i].attr {
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].attr[j]))
util.EncodeULEB128(&abbrev, uint64(b.abbrevs[i].form[j]))
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].attr[j]))
leb128.EncodeUnsigned(&abbrev, uint64(b.abbrevs[i].form[j]))
}
util.EncodeULEB128(&abbrev, 0)
util.EncodeULEB128(&abbrev, 0)
leb128.EncodeUnsigned(&abbrev, 0)
leb128.EncodeUnsigned(&abbrev, 0)
}
return abbrev.Bytes()

@ -3,8 +3,8 @@ package dwarfbuilder
import (
"bytes"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/util"
)
// LocEntry represents one entry of debug_loc.
@ -23,9 +23,9 @@ func LocationBlock(args ...interface{}) []byte {
case op.Opcode:
buf.WriteByte(byte(x))
case int:
util.EncodeSLEB128(&buf, int64(x))
leb128.EncodeSigned(&buf, int64(x))
case uint:
util.EncodeULEB128(&buf, uint64(x))
leb128.EncodeUnsigned(&buf, uint64(x))
default:
panic("unsupported value type")
}

@ -9,6 +9,7 @@ import (
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"github.com/go-delve/delve/pkg/dwarf/util"
)
@ -123,10 +124,10 @@ func parseFDE(ctx *parseContext) parsefunc {
ctx.entries = append(ctx.entries, ctx.frame)
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
// size followed by 'size' bytes.
n, _ := util.DecodeULEB128(reader)
n, _ := leb128.DecodeUnsigned(reader)
reader.Seek(int64(n), io.SeekCurrent)
}
@ -165,23 +166,23 @@ func parseCIE(ctx *parseContext) parsefunc {
}
// parse code alignment factor
ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
ctx.common.CodeAlignmentFactor, _ = leb128.DecodeUnsigned(buf)
// parse data alignment factor
ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
ctx.common.DataAlignmentFactor, _ = leb128.DecodeSigned(buf)
// parse return address register
if ctx.parsingEHFrame() && ctx.common.Version == 1 {
b, _ := buf.ReadByte()
ctx.common.ReturnAddressRegister = uint64(b)
} else {
ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
ctx.common.ReturnAddressRegister, _ = leb128.DecodeUnsigned(buf)
}
ctx.common.ptrEncAddr = ptrEncAbs
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++ {
switch ctx.common.Augmentation[i] {
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
// mapped to when the executable file containing the eh_frame section being
// 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 {
return 0
}
@ -242,7 +243,7 @@ func (ctx *parseContext) readEncodedPtr(addr uint64, buf util.ByteReaderWithLen,
case ptrEncAbs, ptrEncSigned:
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, ctx.ptrSize)
case ptrEncUleb:
ptr, _ = util.DecodeULEB128(buf)
ptr, _ = leb128.DecodeUnsigned(buf)
case ptrEncUdata2:
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 2)
case ptrEncSdata2:
@ -256,7 +257,7 @@ func (ctx *parseContext) readEncodedPtr(addr uint64, buf util.ByteReaderWithLen,
case ptrEncUdata8, ptrEncSdata8:
ptr, _ = util.ReadUintRaw(buf, binary.LittleEndian, 8)
case ptrEncSleb:
n, _ := util.DecodeSLEB128(buf)
n, _ := leb128.DecodeSigned(buf)
ptr = uint64(n)
}

@ -5,7 +5,7 @@ import (
"encoding/binary"
"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.
@ -254,7 +254,7 @@ func offset(frame *FrameContext) {
var (
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}
@ -284,26 +284,26 @@ func setloc(frame *FrameContext) {
func offsetextended(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeULEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
offset, _ = leb128.DecodeUnsigned(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
}
func undefined(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
frame.Regs[reg] = DWRule{Rule: RuleUndefined}
}
func samevalue(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
frame.Regs[reg] = DWRule{Rule: RuleSameVal}
}
func register(frame *FrameContext) {
reg1, _ := util.DecodeULEB128(frame.buf)
reg2, _ := util.DecodeULEB128(frame.buf)
reg1, _ := leb128.DecodeUnsigned(frame.buf)
reg2, _ := leb128.DecodeUnsigned(frame.buf)
frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
}
@ -316,7 +316,7 @@ func restorestate(frame *FrameContext) {
}
func restoreextended(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
oldrule, ok := frame.initialRegs[reg]
if ok {
@ -327,8 +327,8 @@ func restoreextended(frame *FrameContext) {
}
func defcfa(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeULEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
offset, _ := leb128.DecodeUnsigned(frame.buf)
frame.CFA.Rule = RuleCFA
frame.CFA.Reg = reg
@ -336,18 +336,18 @@ func defcfa(frame *FrameContext) {
}
func defcfaregister(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
frame.CFA.Reg = reg
}
func defcfaoffset(frame *FrameContext) {
offset, _ := util.DecodeULEB128(frame.buf)
offset, _ := leb128.DecodeUnsigned(frame.buf)
frame.CFA.Offset = int64(offset)
}
func defcfasf(frame *FrameContext) {
reg, _ := util.DecodeULEB128(frame.buf)
offset, _ := util.DecodeSLEB128(frame.buf)
reg, _ := leb128.DecodeUnsigned(frame.buf)
offset, _ := leb128.DecodeSigned(frame.buf)
frame.CFA.Rule = RuleCFA
frame.CFA.Reg = reg
@ -355,14 +355,14 @@ func defcfasf(frame *FrameContext) {
}
func defcfaoffsetsf(frame *FrameContext) {
offset, _ := util.DecodeSLEB128(frame.buf)
offset, _ := leb128.DecodeSigned(frame.buf)
offset *= frame.dataAlignment
frame.CFA.Offset = offset
}
func defcfaexpression(frame *FrameContext) {
var (
l, _ = util.DecodeULEB128(frame.buf)
l, _ = leb128.DecodeUnsigned(frame.buf)
expr = frame.buf.Next(int(l))
)
@ -372,8 +372,8 @@ func defcfaexpression(frame *FrameContext) {
func expression(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
l, _ = util.DecodeULEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
l, _ = leb128.DecodeUnsigned(frame.buf)
expr = frame.buf.Next(int(l))
)
@ -382,8 +382,8 @@ func expression(frame *FrameContext) {
func offsetextendedsf(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeSLEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
offset, _ = leb128.DecodeSigned(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset}
@ -391,8 +391,8 @@ func offsetextendedsf(frame *FrameContext) {
func valoffset(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeULEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
offset, _ = leb128.DecodeUnsigned(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
@ -400,8 +400,8 @@ func valoffset(frame *FrameContext) {
func valoffsetsf(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
offset, _ = util.DecodeSLEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
offset, _ = leb128.DecodeSigned(frame.buf)
)
frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
@ -409,8 +409,8 @@ func valoffsetsf(frame *FrameContext) {
func valexpression(frame *FrameContext) {
var (
reg, _ = util.DecodeULEB128(frame.buf)
l, _ = util.DecodeULEB128(frame.buf)
reg, _ = leb128.DecodeUnsigned(frame.buf)
l, _ = leb128.DecodeUnsigned(frame.buf)
expr = frame.buf.Next(int(l))
)

@ -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
}

@ -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

@ -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

@ -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
}
}
}

@ -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"
"strings"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"github.com/go-delve/delve/pkg/dwarf/util"
)
@ -173,7 +174,7 @@ func parseIncludeDirs5(info *DebugLineInfo, buf *bytes.Buffer) bool {
if dirEntryFormReader == nil {
return false
}
dirCount, _ := util.DecodeULEB128(buf)
dirCount, _ := leb128.DecodeUnsigned(buf)
info.IncludeDirs = make([]string, 0, dirCount)
for i := uint64(0); i < dirCount; i++ {
dirEntryFormReader.reset()
@ -242,9 +243,9 @@ func readFileEntry(info *DebugLineInfo, buf *bytes.Buffer, exitOnEmptyPath bool)
entry.Path = strings.ReplaceAll(entry.Path, "\\", "/")
}
entry.DirIdx, _ = util.DecodeULEB128(buf)
entry.LastModTime, _ = util.DecodeULEB128(buf)
entry.Length, _ = util.DecodeULEB128(buf)
entry.DirIdx, _ = leb128.DecodeUnsigned(buf)
entry.LastModTime, _ = leb128.DecodeUnsigned(buf)
entry.Length, _ = leb128.DecodeUnsigned(buf)
if !pathIsAbs(entry.Path) {
if entry.DirIdx < uint64(len(info.IncludeDirs)) {
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 {
return false
}
fileCount, _ := util.DecodeULEB128(buf)
fileCount, _ := leb128.DecodeUnsigned(buf)
info.FileNames = make([]*FileEntry, 0, fileCount)
for i := 0; i < int(fileCount); i++ {
var (

@ -5,6 +5,7 @@ import (
"encoding/binary"
"errors"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"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),
}
for i := range r.contentTypes {
r.contentTypes[i], _ = util.DecodeULEB128(buf)
r.formCodes[i], _ = util.DecodeULEB128(buf)
r.contentTypes[i], _ = leb128.DecodeUnsigned(buf)
r.formCodes[i], _ = leb128.DecodeUnsigned(buf)
}
return r
}
@ -94,7 +95,7 @@ func (rdr *formReader) next(buf *bytes.Buffer) bool {
switch rdr.formCode {
case _DW_FORM_block:
n, _ := util.DecodeULEB128(buf)
n, _ := leb128.DecodeUnsigned(buf)
rdr.readBlock(buf, n)
case _DW_FORM_block1:
@ -150,10 +151,10 @@ func (rdr *formReader) next(buf *bytes.Buffer) bool {
rdr.readBlock(buf, 16)
case _DW_FORM_sdata:
rdr.i64, _ = util.DecodeSLEB128(buf)
rdr.i64, _ = leb128.DecodeSigned(buf)
case _DW_FORM_udata, _DW_FORM_strx:
rdr.u64, _ = util.DecodeULEB128(buf)
rdr.u64, _ = leb128.DecodeUnsigned(buf)
case _DW_FORM_string:
rdr.str, _ = util.ParseString(buf)

@ -7,6 +7,7 @@ import (
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"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
opnum := sm.dbl.Prologue.StdOpLengths[b-1]
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)
}
@ -432,7 +433,7 @@ func execSpecialOpcode(sm *StateMachine, instr byte) {
}
func execExtendedOpcode(sm *StateMachine, buf *bytes.Buffer) {
_, _ = util.DecodeULEB128(buf)
_, _ = leb128.DecodeUnsigned(buf)
b, _ := buf.ReadByte()
if fn, ok := extendedopcodes[b]; ok {
fn(sm, buf)
@ -444,18 +445,18 @@ func copyfn(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)
}
func advanceline(sm *StateMachine, buf *bytes.Buffer) {
line, _ := util.DecodeSLEB128(buf)
line, _ := leb128.DecodeSigned(buf)
sm.line += int(line)
sm.lastDelta = int(line)
}
func setfile(sm *StateMachine, buf *bytes.Buffer) {
i, _ := util.DecodeULEB128(buf)
i, _ := leb128.DecodeUnsigned(buf)
if sm.dbl.Prologue.Version < 5 {
// in DWARF v5 files are indexed starting from 0, in v4 and prior the index starts at 1
i--
@ -473,7 +474,7 @@ func setfile(sm *StateMachine, buf *bytes.Buffer) {
}
func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
c, _ := util.DecodeULEB128(buf)
c, _ := leb128.DecodeUnsigned(buf)
sm.column = uint(c)
}
@ -510,7 +511,7 @@ func setaddress(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) {
@ -528,6 +529,6 @@ func epiloguebegin(sm *StateMachine, buf *bytes.Buffer) {
}
func setisa(sm *StateMachine, buf *bytes.Buffer) {
c, _ := util.DecodeULEB128(buf)
c, _ := leb128.DecodeUnsigned(buf)
sm.isa = c
}

@ -13,6 +13,7 @@ import (
"runtime"
"testing"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"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) {
instr.WriteByte(0)
util.EncodeULEB128(instr, 9) // 1 + ptr_size
leb128.EncodeUnsigned(instr, 9) // 1 + ptr_size
instr.WriteByte(DW_LINE_set_address)
util.WriteUint(instr, binary.LittleEndian, ptrSize, addr)
}
@ -147,17 +148,17 @@ func TestMultipleSequences(t *testing.T) {
write_DW_LNS_advance_pc := func(off uint64) {
instr.WriteByte(DW_LNS_advance_pc)
util.EncodeULEB128(instr, off)
leb128.EncodeUnsigned(instr, off)
}
write_DW_LNS_advance_line := func(off int64) {
instr.WriteByte(DW_LNS_advance_line)
util.EncodeSLEB128(instr, off)
leb128.EncodeSigned(instr, off)
}
write_DW_LNE_end_sequence := func() {
instr.WriteByte(0)
util.EncodeULEB128(instr, 1)
leb128.EncodeUnsigned(instr, 1)
instr.WriteByte(DW_LINE_end_sequence)
}

@ -6,6 +6,7 @@ import (
"fmt"
"github.com/go-delve/delve/pkg/dwarf/godwarf"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"github.com/go-delve/delve/pkg/dwarf/util"
)
@ -116,7 +117,7 @@ func (it *loclistsIterator) next() bool {
return false
case _DW_LLE_base_addressx:
baseIdx, _ := util.DecodeULEB128(it.buf)
baseIdx, _ := leb128.DecodeUnsigned(it.buf)
if err != nil {
it.err = err
return false
@ -126,8 +127,8 @@ func (it *loclistsIterator) next() bool {
it.onRange = false
case _DW_LLE_startx_endx:
startIdx, _ := util.DecodeULEB128(it.buf)
endIdx, _ := util.DecodeULEB128(it.buf)
startIdx, _ := leb128.DecodeUnsigned(it.buf)
endIdx, _ := leb128.DecodeUnsigned(it.buf)
it.readInstr()
it.start, it.err = it.debugAddr.Get(startIdx)
@ -137,8 +138,8 @@ func (it *loclistsIterator) next() bool {
it.onRange = true
case _DW_LLE_startx_length:
startIdx, _ := util.DecodeULEB128(it.buf)
length, _ := util.DecodeULEB128(it.buf)
startIdx, _ := leb128.DecodeUnsigned(it.buf)
length, _ := leb128.DecodeUnsigned(it.buf)
it.readInstr()
it.start, it.err = it.debugAddr.Get(startIdx)
@ -146,8 +147,8 @@ func (it *loclistsIterator) next() bool {
it.onRange = true
case _DW_LLE_offset_pair:
off1, _ := util.DecodeULEB128(it.buf)
off2, _ := util.DecodeULEB128(it.buf)
off1, _ := leb128.DecodeUnsigned(it.buf)
off2, _ := leb128.DecodeUnsigned(it.buf)
it.readInstr()
it.start = it.base + off1
@ -172,7 +173,7 @@ func (it *loclistsIterator) next() bool {
case _DW_LLE_start_length:
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.end = it.start + length
it.onRange = true
@ -188,6 +189,6 @@ func (it *loclistsIterator) next() bool {
}
func (it *loclistsIterator) readInstr() {
length, _ := util.DecodeULEB128(it.buf)
length, _ := leb128.DecodeUnsigned(it.buf)
it.instr = it.buf.Next(int(length))
}

@ -5,7 +5,7 @@ import (
"encoding/binary"
"testing"
"github.com/go-delve/delve/pkg/dwarf/util"
"github.com/go-delve/delve/pkg/dwarf/leb128"
)
func TestLoclist5(t *testing.T) {
@ -14,7 +14,7 @@ func TestLoclist5(t *testing.T) {
p32 := func(n uint32) { 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) }
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)
p16(0x5) // version

@ -7,6 +7,7 @@ import (
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/leb128"
"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
switch arg {
case 's':
n, _ := util.DecodeSLEB128(in)
n, _ := leb128.DecodeSigned(in)
regnum = uint64(n)
fmt.Fprintf(out, "%#x ", n)
case 'u':
n, _ := util.DecodeULEB128(in)
n, _ := leb128.DecodeUnsigned(in)
regnum = n
fmt.Fprintf(out, "%#x ", n)
case '1':
@ -154,7 +155,7 @@ func PrettyPrint(out io.Writer, instructions []byte, regnumToName func(uint64) s
binary.Read(in, binary.LittleEndian, &x)
fmt.Fprintf(out, "%#x ", x)
case 'B':
sz, _ := util.DecodeULEB128(in)
sz, _ := leb128.DecodeUnsigned(in)
data := make([]byte, sz)
sz2, _ := in.Read(data)
data = data[:sz2]
@ -189,7 +190,7 @@ func (ctxt *context) closeLoc(opcode0 Opcode, piece Piece) error {
switch opcode {
case DW_OP_piece:
sz, _ := util.DecodeULEB128(ctxt.buf)
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
piece.Size = int(sz)
ctxt.pieces = append(ctxt.pieces, piece)
return nil
@ -222,19 +223,19 @@ func addr(opcode Opcode, ctxt *context) error {
func plusuconsts(opcode Opcode, ctxt *context) error {
slen := len(ctxt.stack)
num, _ := util.DecodeULEB128(ctxt.buf)
num, _ := leb128.DecodeUnsigned(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)
num, _ := leb128.DecodeSigned(ctxt.buf)
ctxt.stack = append(ctxt.stack, num)
return nil
}
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)
return nil
}
@ -242,7 +243,7 @@ func framebase(opcode Opcode, ctxt *context) error {
func register(opcode Opcode, ctxt *context) error {
var regnum uint64
if opcode == DW_OP_regx {
regnum, _ = util.DecodeULEB128(ctxt.buf)
regnum, _ = leb128.DecodeUnsigned(ctxt.buf)
} else {
regnum = uint64(opcode - DW_OP_reg0)
}
@ -252,11 +253,11 @@ func register(opcode Opcode, ctxt *context) error {
func bregister(opcode Opcode, ctxt *context) error {
var regnum uint64
if opcode == DW_OP_bregx {
regnum, _ = util.DecodeULEB128(ctxt.buf)
regnum, _ = leb128.DecodeUnsigned(ctxt.buf)
} else {
regnum = uint64(opcode - DW_OP_breg0)
}
offset, _ := util.DecodeSLEB128(ctxt.buf)
offset, _ := leb128.DecodeSigned(ctxt.buf)
if ctxt.Reg(regnum) == nil {
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 {
sz, _ := util.DecodeULEB128(ctxt.buf)
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
if len(ctxt.stack) == 0 {
// 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 {
num, _ := util.DecodeULEB128(ctxt.buf)
num, _ := leb128.DecodeUnsigned(ctxt.buf)
ctxt.stack = append(ctxt.stack, int64(num))
return nil
}
@ -516,7 +517,7 @@ func stackvalue(_ Opcode, ctxt *context) error {
}
func implicitvalue(_ Opcode, ctxt *context) error {
sz, _ := util.DecodeULEB128(ctxt.buf)
sz, _ := leb128.DecodeUnsigned(ctxt.buf)
block := make([]byte, sz)
n, _ := ctxt.buf.Read(block)
if uint64(n) != sz {

@ -6,125 +6,50 @@ import (
"encoding/binary"
"fmt"
"io"
"github.com/go-delve/delve/pkg/dwarf/leb128"
)
// 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 {
io.ByteReader
io.Reader
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
// represented number.
//
// Deprecated: use leb128.DecodeUnsigned.
func DecodeULEB128(buf ByteReaderWithLen) (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
return leb128.DecodeUnsigned(buf)
}
// DecodeSLEB128 decodes a signed Little Endian Base 128
// represented number.
//
// Deprecated: use leb128.DecodeUnsigned.
func DecodeSLEB128(buf ByteReaderWithLen) (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
return leb128.DecodeSigned(buf)
}
// EncodeULEB128 encodes x to the unsigned Little Endian Base 128 format
// into out.
//
// Deprecated: use leb128.EncodeUnsigned.
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
}
}
leb128.EncodeUnsigned(out, x)
}
// EncodeSLEB128 encodes x to the signed Little Endian Base 128 format
// into out.
//
// Deprecated: use leb128.EncodeSigned.
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
}
}
leb128.EncodeSigned(out, x)
}
// ParseString reads a null-terminated string from data.

@ -5,64 +5,6 @@ import (
"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) {
bstr := bytes.NewBuffer([]byte{'h', 'i', 0x0, 0xFF, 0xCC})
str, _ := ParseString(bstr)