1// Copyright 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Buffered reading and decoding of DWARF data streams. 16 17package dwarf 18 19import ( 20 "encoding/binary" 21 "fmt" 22 "strconv" 23) 24 25// Data buffer being decoded. 26type buf struct { 27 dwarf *Data 28 order binary.ByteOrder 29 format dataFormat 30 name string 31 off Offset 32 data []byte 33 err error 34} 35 36// Data format, other than byte order. This affects the handling of 37// certain field formats. 38type dataFormat interface { 39 // DWARF version number. Zero means unknown. 40 version() int 41 42 // 64-bit DWARF format? 43 dwarf64() (dwarf64 bool, isKnown bool) 44 45 // Size of an address, in bytes. Zero means unknown. 46 addrsize() int 47} 48 49// Some parts of DWARF have no data format, e.g., abbrevs. 50type unknownFormat struct{} 51 52func (u unknownFormat) version() int { 53 return 0 54} 55 56func (u unknownFormat) dwarf64() (bool, bool) { 57 return false, false 58} 59 60func (u unknownFormat) addrsize() int { 61 return 0 62} 63 64func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf { 65 return buf{d, d.order, format, name, off, data, nil} 66} 67 68func (b *buf) slice(length int) buf { 69 n := *b 70 data := b.data 71 b.skip(length) // Will validate length. 72 n.data = data[:length] 73 return n 74} 75 76func (b *buf) uint8() uint8 { 77 if len(b.data) < 1 { 78 b.error("underflow") 79 return 0 80 } 81 val := b.data[0] 82 b.data = b.data[1:] 83 b.off++ 84 return val 85} 86 87func (b *buf) bytes(n int) []byte { 88 if len(b.data) < n { 89 b.error("underflow") 90 return nil 91 } 92 data := b.data[0:n] 93 b.data = b.data[n:] 94 b.off += Offset(n) 95 return data 96} 97 98func (b *buf) skip(n int) { b.bytes(n) } 99 100// string returns the NUL-terminated (C-like) string at the start of the buffer. 101// The terminal NUL is discarded. 102func (b *buf) string() string { 103 for i := 0; i < len(b.data); i++ { 104 if b.data[i] == 0 { 105 s := string(b.data[0:i]) 106 b.data = b.data[i+1:] 107 b.off += Offset(i + 1) 108 return s 109 } 110 } 111 b.error("underflow") 112 return "" 113} 114 115func (b *buf) uint16() uint16 { 116 a := b.bytes(2) 117 if a == nil { 118 return 0 119 } 120 return b.order.Uint16(a) 121} 122 123func (b *buf) uint32() uint32 { 124 a := b.bytes(4) 125 if a == nil { 126 return 0 127 } 128 return b.order.Uint32(a) 129} 130 131func (b *buf) uint64() uint64 { 132 a := b.bytes(8) 133 if a == nil { 134 return 0 135 } 136 return b.order.Uint64(a) 137} 138 139// Read a varint, which is 7 bits per byte, little endian. 140// the 0x80 bit means read another byte. 141func (b *buf) varint() (c uint64, bits uint) { 142 for i := 0; i < len(b.data); i++ { 143 byte := b.data[i] 144 c |= uint64(byte&0x7F) << bits 145 bits += 7 146 if byte&0x80 == 0 { 147 b.off += Offset(i + 1) 148 b.data = b.data[i+1:] 149 return c, bits 150 } 151 } 152 return 0, 0 153} 154 155// Unsigned int is just a varint. 156func (b *buf) uint() uint64 { 157 x, _ := b.varint() 158 return x 159} 160 161// Signed int is a sign-extended varint. 162func (b *buf) int() int64 { 163 ux, bits := b.varint() 164 x := int64(ux) 165 if x&(1<<(bits-1)) != 0 { 166 x |= -1 << bits 167 } 168 return x 169} 170 171// Address-sized uint. 172func (b *buf) addr() uint64 { 173 switch b.format.addrsize() { 174 case 1: 175 return uint64(b.uint8()) 176 case 2: 177 return uint64(b.uint16()) 178 case 4: 179 return uint64(b.uint32()) 180 case 8: 181 return uint64(b.uint64()) 182 } 183 b.error("unknown address size") 184 return 0 185} 186 187// assertEmpty checks that everything has been read from b. 188func (b *buf) assertEmpty() { 189 if len(b.data) == 0 { 190 return 191 } 192 if len(b.data) > 5 { 193 b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5])) 194 } 195 b.error(fmt.Sprintf("unexpected extra data: %x", b.data)) 196} 197 198func (b *buf) error(s string) { 199 if b.err == nil { 200 b.data = nil 201 b.err = DecodeError{b.name, b.off, s} 202 } 203} 204 205type DecodeError struct { 206 Name string 207 Offset Offset 208 Err string 209} 210 211func (e DecodeError) Error() string { 212 return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err 213} 214