github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/util/util.go (about) 1 // The MIT License (MIT) 2 3 // Copyright (c) 2014 Derek Parker 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 package util 23 24 import ( 25 "bytes" 26 "debug/dwarf" 27 "encoding/binary" 28 "fmt" 29 "io" 30 ) 31 32 33 34 type ByteReaderWithLen interface { 35 io.ByteReader 36 io.Reader 37 Len() int 38 } 39 40 41 42 43 44 45 func DecodeULEB128(buf ByteReaderWithLen) (uint64, uint32) { 46 var ( 47 result uint64 48 shift uint64 49 length uint32 50 ) 51 52 if buf.Len() == 0 { 53 return 0, 0 54 } 55 56 for { 57 b, err := buf.ReadByte() 58 if err != nil { 59 panic("Could not parse ULEB128 value") 60 } 61 length++ 62 63 result |= uint64((uint(b) & 0x7f) << shift) 64 65 66 if b&0x80 == 0 { 67 break 68 } 69 70 shift += 7 71 } 72 73 return result, length 74 } 75 76 77 78 func DecodeSLEB128(buf ByteReaderWithLen) (int64, uint32) { 79 var ( 80 b byte 81 err error 82 result int64 83 shift uint64 84 length uint32 85 ) 86 87 if buf.Len() == 0 { 88 return 0, 0 89 } 90 91 for { 92 b, err = buf.ReadByte() 93 if err != nil { 94 panic("Could not parse SLEB128 value") 95 } 96 length++ 97 98 result |= int64((int64(b) & 0x7f) << shift) 99 shift += 7 100 if b&0x80 == 0 { 101 break 102 } 103 } 104 105 if (shift < 8*uint64(length)) && (b&0x40 > 0) { 106 result |= -(1 << shift) 107 } 108 109 return result, length 110 } 111 112 113 114 func EncodeULEB128(out io.ByteWriter, x uint64) { 115 for { 116 b := byte(x & 0x7f) 117 x = x >> 7 118 if x != 0 { 119 b = b | 0x80 120 } 121 out.WriteByte(b) 122 if x == 0 { 123 break 124 } 125 } 126 } 127 128 129 130 func EncodeSLEB128(out io.ByteWriter, x int64) { 131 for { 132 b := byte(x & 0x7f) 133 x >>= 7 134 135 signb := b & 0x40 136 137 last := false 138 if (x == 0 && signb == 0) || (x == -1 && signb != 0) { 139 last = true 140 } else { 141 b = b | 0x80 142 } 143 out.WriteByte(b) 144 145 if last { 146 break 147 } 148 } 149 } 150 151 152 func ParseString(data *bytes.Buffer) (string, error) { 153 str, err := data.ReadString(0x0) 154 if err != nil { 155 return "", err 156 } 157 158 return str[:len(str)-1], nil 159 } 160 161 162 func ReadUintRaw(reader io.Reader, order binary.ByteOrder, ptrSize int) (uint64, error) { 163 switch ptrSize { 164 case 2: 165 var n uint16 166 if err := binary.Read(reader, order, &n); err != nil { 167 return 0, err 168 } 169 return uint64(n), nil 170 case 4: 171 var n uint32 172 if err := binary.Read(reader, order, &n); err != nil { 173 return 0, err 174 } 175 return uint64(n), nil 176 case 8: 177 var n uint64 178 if err := binary.Read(reader, order, &n); err != nil { 179 return 0, err 180 } 181 return n, nil 182 } 183 return 0, fmt.Errorf("pointer size %d not supported", ptrSize) 184 } 185 186 187 func WriteUint(writer io.Writer, order binary.ByteOrder, ptrSize int, data uint64) error { 188 switch ptrSize { 189 case 4: 190 return binary.Write(writer, order, uint32(data)) 191 case 8: 192 return binary.Write(writer, order, data) 193 } 194 return fmt.Errorf("pointer size %d not supported", ptrSize) 195 } 196 197 198 func ReadDwarfLengthVersion(data []byte) (length uint64, dwarf64 bool, version uint8, byteOrder binary.ByteOrder) { 199 if len(data) < 4 { 200 return 0, false, 0, binary.LittleEndian 201 } 202 203 lengthfield := binary.LittleEndian.Uint32(data) 204 voff := 4 205 if lengthfield == ^uint32(0) { 206 dwarf64 = true 207 voff = 12 208 } 209 210 if voff+1 >= len(data) { 211 return 0, false, 0, binary.LittleEndian 212 } 213 214 byteOrder = binary.LittleEndian 215 x, y := data[voff], data[voff+1] 216 switch { 217 default: 218 fallthrough 219 case x == 0 && y == 0: 220 version = 0 221 byteOrder = binary.LittleEndian 222 case x == 0: 223 version = y 224 byteOrder = binary.BigEndian 225 case y == 0: 226 version = x 227 byteOrder = binary.LittleEndian 228 } 229 230 if dwarf64 { 231 length = byteOrder.Uint64(data[4:]) 232 } else { 233 length = uint64(byteOrder.Uint32(data)) 234 } 235 236 return length, dwarf64, version, byteOrder 237 } 238 239 const ( 240 _DW_UT_compile = 0x1 + iota 241 _DW_UT_type 242 _DW_UT_partial 243 _DW_UT_skeleton 244 _DW_UT_split_compile 245 _DW_UT_split_type 246 ) 247 248 249 func ReadUnitVersions(data []byte) map[dwarf.Offset]uint8 { 250 r := make(map[dwarf.Offset]uint8) 251 off := dwarf.Offset(0) 252 for len(data) > 0 { 253 length, dwarf64, version, _ := ReadDwarfLengthVersion(data) 254 255 data = data[4:] 256 off += 4 257 secoffsz := 4 258 if dwarf64 { 259 off += 8 260 secoffsz = 8 261 data = data[8:] 262 } 263 264 var headerSize int 265 266 switch version { 267 case 2, 3, 4: 268 headerSize = 3 + secoffsz 269 default: 270 unitType := data[2] 271 272 switch unitType { 273 case _DW_UT_compile, _DW_UT_partial: 274 headerSize = 5 + secoffsz 275 276 case _DW_UT_skeleton, _DW_UT_split_compile: 277 headerSize = 4 + secoffsz + 8 278 279 case _DW_UT_type, _DW_UT_split_type: 280 headerSize = 4 + secoffsz + 8 + secoffsz 281 } 282 } 283 284 r[off+dwarf.Offset(headerSize)] = version 285 286 data = data[length:] 287 off += dwarf.Offset(length) 288 } 289 return r 290 }