github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/debug/dwarf/buf.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Buffered reading and decoding of DWARF data streams. 6 7 package dwarf 8 9 import ( 10 "encoding/binary" 11 "strconv" 12 ) 13 14 // Data buffer being decoded. 15 type buf struct { 16 dwarf *Data 17 order binary.ByteOrder 18 format dataFormat 19 name string 20 off Offset 21 data []byte 22 err error 23 } 24 25 // Data format, other than byte order. This affects the handling of 26 // certain field formats. 27 type dataFormat interface { 28 // DWARF version number. Zero means unknown. 29 version() int 30 31 // 64-bit DWARF format? 32 dwarf64() (dwarf64 bool, isKnown bool) 33 34 // Size of an address, in bytes. Zero means unknown. 35 addrsize() int 36 } 37 38 // Some parts of DWARF have no data format, e.g., abbrevs. 39 type unknownFormat struct{} 40 41 func (u unknownFormat) version() int { 42 return 0 43 } 44 45 func (u unknownFormat) dwarf64() (bool, bool) { 46 return false, false 47 } 48 49 func (u unknownFormat) addrsize() int { 50 return 0 51 } 52 53 func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf { 54 return buf{d, d.order, format, name, off, data, nil} 55 } 56 57 func (b *buf) uint8() uint8 { 58 if len(b.data) < 1 { 59 b.error("underflow") 60 return 0 61 } 62 val := b.data[0] 63 b.data = b.data[1:] 64 b.off++ 65 return val 66 } 67 68 func (b *buf) bytes(n int) []byte { 69 if len(b.data) < n { 70 b.error("underflow") 71 return nil 72 } 73 data := b.data[0:n] 74 b.data = b.data[n:] 75 b.off += Offset(n) 76 return data 77 } 78 79 func (b *buf) skip(n int) { b.bytes(n) } 80 81 func (b *buf) string() string { 82 for i := 0; i < len(b.data); i++ { 83 if b.data[i] == 0 { 84 s := string(b.data[0:i]) 85 b.data = b.data[i+1:] 86 b.off += Offset(i + 1) 87 return s 88 } 89 } 90 b.error("underflow") 91 return "" 92 } 93 94 func (b *buf) uint16() uint16 { 95 a := b.bytes(2) 96 if a == nil { 97 return 0 98 } 99 return b.order.Uint16(a) 100 } 101 102 func (b *buf) uint32() uint32 { 103 a := b.bytes(4) 104 if a == nil { 105 return 0 106 } 107 return b.order.Uint32(a) 108 } 109 110 func (b *buf) uint64() uint64 { 111 a := b.bytes(8) 112 if a == nil { 113 return 0 114 } 115 return b.order.Uint64(a) 116 } 117 118 // Read a varint, which is 7 bits per byte, little endian. 119 // the 0x80 bit means read another byte. 120 func (b *buf) varint() (c uint64, bits uint) { 121 for i := 0; i < len(b.data); i++ { 122 byte := b.data[i] 123 c |= uint64(byte&0x7F) << bits 124 bits += 7 125 if byte&0x80 == 0 { 126 b.off += Offset(i + 1) 127 b.data = b.data[i+1:] 128 return c, bits 129 } 130 } 131 return 0, 0 132 } 133 134 // Unsigned int is just a varint. 135 func (b *buf) uint() uint64 { 136 x, _ := b.varint() 137 return x 138 } 139 140 // Signed int is a sign-extended varint. 141 func (b *buf) int() int64 { 142 ux, bits := b.varint() 143 x := int64(ux) 144 if x&(1<<(bits-1)) != 0 { 145 x |= -1 << bits 146 } 147 return x 148 } 149 150 // Address-sized uint. 151 func (b *buf) addr() uint64 { 152 switch b.format.addrsize() { 153 case 1: 154 return uint64(b.uint8()) 155 case 2: 156 return uint64(b.uint16()) 157 case 4: 158 return uint64(b.uint32()) 159 case 8: 160 return uint64(b.uint64()) 161 } 162 b.error("unknown address size") 163 return 0 164 } 165 166 func (b *buf) unitLength() (length Offset, dwarf64 bool) { 167 length = Offset(b.uint32()) 168 if length == 0xffffffff { 169 dwarf64 = true 170 length = Offset(b.uint64()) 171 } else if length >= 0xfffffff0 { 172 b.error("unit length has reserved value") 173 } 174 return 175 } 176 177 func (b *buf) error(s string) { 178 if b.err == nil { 179 b.data = nil 180 b.err = DecodeError{b.name, b.off, s} 181 } 182 } 183 184 type DecodeError struct { 185 Name string 186 Offset Offset 187 Err string 188 } 189 190 func (e DecodeError) Error() string { 191 return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err 192 }