github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/loclist/dwarf5_loclist.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 loclist 23 24 import ( 25 "bytes" 26 "encoding/binary" 27 "fmt" 28 29 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf" 30 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/util" 31 ) 32 33 34 35 type Dwarf5Reader struct { 36 byteOrder binary.ByteOrder 37 ptrSz int 38 data []byte 39 } 40 41 func NewDwarf5Reader(data []byte) *Dwarf5Reader { 42 if len(data) == 0 { 43 return nil 44 } 45 r := &Dwarf5Reader{data: data} 46 47 _, dwarf64, _, byteOrder := util.ReadDwarfLengthVersion(data) 48 r.byteOrder = byteOrder 49 50 data = data[6:] 51 if dwarf64 { 52 data = data[8:] 53 } 54 55 addrSz := data[0] 56 segSelSz := data[1] 57 r.ptrSz = int(addrSz + segSelSz) 58 59 60 61 62 63 return r 64 } 65 66 func (rdr *Dwarf5Reader) Empty() bool { 67 return rdr == nil 68 } 69 70 71 72 73 func (rdr *Dwarf5Reader) Find(off int, staticBase, base, pc uint64, debugAddr *godwarf.DebugAddr) (*Entry, error) { 74 it := &loclistsIterator{rdr: rdr, debugAddr: debugAddr, buf: bytes.NewBuffer(rdr.data), base: base, staticBase: staticBase} 75 it.buf.Next(off) 76 77 for it.next() { 78 if !it.onRange { 79 continue 80 } 81 if it.start <= pc && pc < it.end { 82 return &Entry{it.start, it.end, it.instr}, nil 83 } 84 } 85 86 if it.err != nil { 87 return nil, it.err 88 } 89 90 if it.defaultInstr != nil { 91 return &Entry{pc, pc + 1, it.defaultInstr}, nil 92 } 93 94 return nil, nil 95 } 96 97 type loclistsIterator struct { 98 rdr *Dwarf5Reader 99 debugAddr *godwarf.DebugAddr 100 buf *bytes.Buffer 101 staticBase uint64 102 base uint64 103 104 onRange bool 105 atEnd bool 106 start, end uint64 107 instr []byte 108 defaultInstr []byte 109 err error 110 } 111 112 const ( 113 _DW_LLE_end_of_list uint8 = 0x0 114 _DW_LLE_base_addressx uint8 = 0x1 115 _DW_LLE_startx_endx uint8 = 0x2 116 _DW_LLE_startx_length uint8 = 0x3 117 _DW_LLE_offset_pair uint8 = 0x4 118 _DW_LLE_default_location uint8 = 0x5 119 _DW_LLE_base_address uint8 = 0x6 120 _DW_LLE_start_end uint8 = 0x7 121 _DW_LLE_start_length uint8 = 0x8 122 ) 123 124 func (it *loclistsIterator) next() bool { 125 if it.err != nil || it.atEnd { 126 return false 127 } 128 opcode, err := it.buf.ReadByte() 129 if err != nil { 130 it.err = err 131 return false 132 } 133 switch opcode { 134 case _DW_LLE_end_of_list: 135 it.atEnd = true 136 it.onRange = false 137 return false 138 139 case _DW_LLE_base_addressx: 140 baseIdx, _ := util.DecodeULEB128(it.buf) 141 if err != nil { 142 it.err = err 143 return false 144 } 145 it.base, it.err = it.debugAddr.Get(baseIdx) 146 it.base += it.staticBase 147 it.onRange = false 148 149 case _DW_LLE_startx_endx: 150 startIdx, _ := util.DecodeULEB128(it.buf) 151 endIdx, _ := util.DecodeULEB128(it.buf) 152 it.readInstr() 153 154 it.start, it.err = it.debugAddr.Get(startIdx) 155 if it.err == nil { 156 it.end, it.err = it.debugAddr.Get(endIdx) 157 } 158 it.onRange = true 159 160 case _DW_LLE_startx_length: 161 startIdx, _ := util.DecodeULEB128(it.buf) 162 length, _ := util.DecodeULEB128(it.buf) 163 it.readInstr() 164 165 it.start, it.err = it.debugAddr.Get(startIdx) 166 it.end = it.start + length 167 it.onRange = true 168 169 case _DW_LLE_offset_pair: 170 off1, _ := util.DecodeULEB128(it.buf) 171 off2, _ := util.DecodeULEB128(it.buf) 172 it.readInstr() 173 174 it.start = it.base + off1 175 it.end = it.base + off2 176 it.onRange = true 177 178 case _DW_LLE_default_location: 179 it.readInstr() 180 it.defaultInstr = it.instr 181 it.onRange = false 182 183 case _DW_LLE_base_address: 184 it.base, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 185 it.base += it.staticBase 186 it.onRange = false 187 188 case _DW_LLE_start_end: 189 it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 190 it.end, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 191 it.readInstr() 192 it.onRange = true 193 194 case _DW_LLE_start_length: 195 it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 196 length, _ := util.DecodeULEB128(it.buf) 197 it.readInstr() 198 it.end = it.start + length 199 it.onRange = true 200 201 default: 202 it.err = fmt.Errorf("unknown opcode %#x at %#x", opcode, len(it.rdr.data)-it.buf.Len()) 203 it.onRange = false 204 it.atEnd = true 205 return false 206 } 207 208 return true 209 } 210 211 func (it *loclistsIterator) readInstr() { 212 length, _ := util.DecodeULEB128(it.buf) 213 it.instr = it.buf.Next(int(length)) 214 }