From 012c6e8c70d9a5e1125eda1e51bc19b3aed0f88b Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Mon, 9 Jun 2014 17:19:44 -0500 Subject: [PATCH] Implement decoding of SLEB128 numbers --- dwarf/frame.go | 34 +++++++++++++++++++++++++++++++++- dwarf/frame_test.go | 11 ++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/dwarf/frame.go b/dwarf/frame.go index 31bafb8a..4cd959cc 100644 --- a/dwarf/frame.go +++ b/dwarf/frame.go @@ -106,7 +106,7 @@ func decodeULEB128(buf *bytes.Buffer) (uint64, uint32) { for { b, err := buf.ReadByte() if err != nil { - panic("Could not parse LEB128 value") + panic("Could not parse ULEB128 value") } length++ @@ -123,6 +123,38 @@ func decodeULEB128(buf *bytes.Buffer) (uint64, uint32) { return result, length } +// decodeSLEB128 decodes an 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 + ) + + 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 +} + func cieEntry(data []byte) bool { return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff}) } diff --git a/dwarf/frame_test.go b/dwarf/frame_test.go index 93b9a5cf..26e7b2b4 100644 --- a/dwarf/frame_test.go +++ b/dwarf/frame_test.go @@ -32,7 +32,7 @@ func grabDebugFrameSection(fp string, t *testing.T) []byte { return data } -func TestdecodeULEB128(t *testing.T) { +func TestDecodeULEB128(t *testing.T) { var leb128 = bytes.NewBuffer([]byte{0xE5, 0x8E, 0x26}) n, c := decodeULEB128(leb128) @@ -41,6 +41,15 @@ func TestdecodeULEB128(t *testing.T) { } } +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 TestParseString(t *testing.T) { bstr := bytes.NewBuffer([]byte{'h', 'i', 0x0, 0xFF, 0xCC}) str, _ := parseString(bstr)