From 1f4580cd21e2d87a3851c408b08b93f9fd5c6569 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Fri, 6 Jun 2014 16:05:26 -0500 Subject: [PATCH] Fix: burn bytes for CIE pointer Also change function sig to be shorter --- dwarf/frame.go | 130 ++++++++++++++++++++++++++------------------ dwarf/frame_test.go | 8 +-- 2 files changed, 80 insertions(+), 58 deletions(-) diff --git a/dwarf/frame.go b/dwarf/frame.go index 8108bf64..a49931f8 100644 --- a/dwarf/frame.go +++ b/dwarf/frame.go @@ -9,7 +9,13 @@ import ( "unicode/utf8" ) -type parsefunc func(*bytes.Buffer, CommonEntries, uint32) (parsefunc, CommonEntries, uint32) +type parsefunc func(*parseContext) (parsefunc, *parseContext) + +type parseContext struct { + Buf *bytes.Buffer + Entries CommonEntries + Length uint32 +} type CommonEntries []*CommonInformationEntry @@ -75,14 +81,15 @@ func Parse(data []byte) CommonEntries { var ( length uint32 entries CommonEntries - reader = bytes.NewBuffer(data) + buf = bytes.NewBuffer(data) + pctx = &parseContext{Buf: buf, Entries: entries, Length: length} ) - for fn := parseLength; reader.Len() != 0; { - fn, entries, length = fn(reader, entries, length) + for fn := parseLength; buf.Len() != 0; { + fn, pctx = fn(pctx) } - return entries + return pctx.Entries } // DecodeLEB128 decodes a Little Endian Base 128 @@ -118,126 +125,141 @@ func cieEntry(data []byte) bool { return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff}) } -func parseLength(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { - binary.Read(reader, binary.LittleEndian, &length) +func parseLength(ctx *parseContext) (parsefunc, *parseContext) { + binary.Read(ctx.Buf, binary.LittleEndian, &ctx.Length) - if cieEntry(reader.Bytes()[0:4]) { - return parseCIEID, append(entries, &CommonInformationEntry{Length: length}), length + if cieEntry(ctx.Buf.Bytes()[0:4]) { + ctx.Entries = append(ctx.Entries, &CommonInformationEntry{Length: ctx.Length}) + return parseCIEID, ctx } - entry := entries[len(entries)-1] - entry.FrameDescriptorEntries = append(entry.FrameDescriptorEntries, &FrameDescriptorEntry{Length: length, CIE_pointer: entry}) + entry := ctx.Entries[len(ctx.Entries)-1] + entry.FrameDescriptorEntries = append(entry.FrameDescriptorEntries, &FrameDescriptorEntry{Length: ctx.Length, CIE_pointer: entry}) - return parseInitialLocation, entries, length + // We aren't reading the CIE pointer from this section so just move the cursor past it. + ctx.Buf.Next(4) + + return parseInitialLocation, ctx } -func parseInitialLocation(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseInitialLocation(ctx *parseContext) (parsefunc, *parseContext) { var ( - frameEntries = entries[len(entries)-1].FrameDescriptorEntries + frameEntries = ctx.Entries[len(ctx.Entries)-1].FrameDescriptorEntries frame = frameEntries[len(frameEntries)-1] ) - binary.Read(reader, binary.LittleEndian, &frame.InitialLocation) + binary.Read(ctx.Buf, binary.LittleEndian, &frame.InitialLocation) + ctx.Length -= 4 - return parseAddressRange, entries, length - 4 + return parseAddressRange, ctx } -func parseAddressRange(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseAddressRange(ctx *parseContext) (parsefunc, *parseContext) { var ( - frameEntries = entries[len(entries)-1].FrameDescriptorEntries + frameEntries = ctx.Entries[len(ctx.Entries)-1].FrameDescriptorEntries frame = frameEntries[len(frameEntries)-1] ) - binary.Read(reader, binary.LittleEndian, &frame.AddressRange) + binary.Read(ctx.Buf, binary.LittleEndian, &frame.AddressRange) + ctx.Length -= 4 - return parseFrameInstructions, entries, length - 4 + return parseFrameInstructions, ctx } -func parseFrameInstructions(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseFrameInstructions(ctx *parseContext) (parsefunc, *parseContext) { var ( // The rest of this entry consists of the instructions // so we can just grab all of the data from the buffer // cursor to length. - buf = make([]byte, length) - frameEntries = entries[len(entries)-1].FrameDescriptorEntries + buf = make([]byte, ctx.Length) + frameEntries = ctx.Entries[len(ctx.Entries)-1].FrameDescriptorEntries frame = frameEntries[len(frameEntries)-1] ) - binary.Read(reader, binary.LittleEndian, &buf) + binary.Read(ctx.Buf, binary.LittleEndian, &buf) frame.Instructions = buf + ctx.Length = 0 - return parseLength, entries, 0 + return parseLength, ctx } -func parseCIEID(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { - var entry = entries[len(entries)-1] +func parseCIEID(ctx *parseContext) (parsefunc, *parseContext) { + var entry = ctx.Entries[len(ctx.Entries)-1] - binary.Read(reader, binary.LittleEndian, &entry.CIE_id) + binary.Read(ctx.Buf, binary.LittleEndian, &entry.CIE_id) + ctx.Length -= 4 - return parseVersion, entries, length - 4 + return parseVersion, ctx } -func parseVersion(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { - entry := entries[len(entries)-1] +func parseVersion(ctx *parseContext) (parsefunc, *parseContext) { + entry := ctx.Entries[len(ctx.Entries)-1] - binary.Read(reader, binary.LittleEndian, &entry.Version) + binary.Read(ctx.Buf, binary.LittleEndian, &entry.Version) + ctx.Length -= 1 - return parseAugmentation, entries, length - 1 + return parseAugmentation, ctx } -func parseAugmentation(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseAugmentation(ctx *parseContext) (parsefunc, *parseContext) { var ( - entry = entries[len(entries)-1] - str, c = parseString(reader) + entry = ctx.Entries[len(ctx.Entries)-1] + str, c = parseString(ctx.Buf) ) entry.Augmentation = str - return parseCodeAlignmentFactor, entries, length - c + ctx.Length -= c + + return parseCodeAlignmentFactor, ctx } -func parseCodeAlignmentFactor(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseCodeAlignmentFactor(ctx *parseContext) (parsefunc, *parseContext) { var ( - entry = entries[len(entries)-1] - caf, c = DecodeLEB128(reader) + entry = ctx.Entries[len(ctx.Entries)-1] + caf, c = DecodeLEB128(ctx.Buf) ) entry.CodeAlignmentFactor = caf + ctx.Length -= c - return parseDataAlignmentFactor, entries, length - c + return parseDataAlignmentFactor, ctx } -func parseDataAlignmentFactor(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseDataAlignmentFactor(ctx *parseContext) (parsefunc, *parseContext) { var ( - entry = entries[len(entries)-1] - daf, c = DecodeLEB128(reader) + entry = ctx.Entries[len(ctx.Entries)-1] + daf, c = DecodeLEB128(ctx.Buf) ) entry.DataAlignmentFactor = daf + ctx.Length -= c - return parseReturnAddressRegister, entries, length - c + return parseReturnAddressRegister, ctx } -func parseReturnAddressRegister(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { - entry := entries[len(entries)-1] +func parseReturnAddressRegister(ctx *parseContext) (parsefunc, *parseContext) { + entry := ctx.Entries[len(ctx.Entries)-1] - binary.Read(reader, binary.LittleEndian, &entry.ReturnAddressRegister) + binary.Read(ctx.Buf, binary.LittleEndian, &entry.ReturnAddressRegister) + ctx.Length -= 1 - return parseInitialInstructions, entries, length - 1 + return parseInitialInstructions, ctx } -func parseInitialInstructions(reader *bytes.Buffer, entries CommonEntries, length uint32) (parsefunc, CommonEntries, uint32) { +func parseInitialInstructions(ctx *parseContext) (parsefunc, *parseContext) { var ( // The rest of this entry consists of the instructions // so we can just grab all of the data from the buffer // cursor to length. - buf = make([]byte, length) - entry = entries[len(entries)-1] + buf = make([]byte, ctx.Length) + entry = ctx.Entries[len(ctx.Entries)-1] ) - binary.Read(reader, binary.LittleEndian, &buf) + binary.Read(ctx.Buf, binary.LittleEndian, &buf) entry.InitialInstructions = buf + ctx.Length = 0 - return parseLength, entries, 0 + return parseLength, ctx } func parseString(data *bytes.Buffer) (string, uint32) { diff --git a/dwarf/frame_test.go b/dwarf/frame_test.go index 4e3e3a29..1b7d5f0f 100644 --- a/dwarf/frame_test.go +++ b/dwarf/frame_test.go @@ -88,11 +88,11 @@ func TestParse(t *testing.T) { t.Fatal("Frame entry does not point to parent CIE") } - if fe.InitialLocation != 0x400c0000000000 { - t.Fatal("Initial location not parsed correctly") + if fe.InitialLocation != 0x400c00 { + t.Fatalf("Initial location not parsed correctly, got %#v", fe.InitialLocation) } - if fe.AddressRange != 0xbc00000000 { - t.Fatal("Address range not parsed correctly") + if fe.AddressRange != 0x2b { + t.Fatalf("Address range not parsed correctly %#v\n%#v", fe.AddressRange, data[15:48]) } }