github.com/neilgarb/delve@v1.9.2-nobreaks/pkg/dwarf/loclist/dwarf5_loclist.go (about) 1 package loclist 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 8 "github.com/go-delve/delve/pkg/dwarf/godwarf" 9 "github.com/go-delve/delve/pkg/dwarf/util" 10 ) 11 12 // Dwarf5Reader parses and presents DWARF loclist information for DWARF version 5 and later. 13 // See DWARFv5 section 7.29 page 243 and following. 14 type Dwarf5Reader struct { 15 byteOrder binary.ByteOrder 16 ptrSz int 17 data []byte 18 } 19 20 func NewDwarf5Reader(data []byte) *Dwarf5Reader { 21 if len(data) == 0 { 22 return nil 23 } 24 r := &Dwarf5Reader{data: data} 25 26 _, dwarf64, _, byteOrder := util.ReadDwarfLengthVersion(data) 27 r.byteOrder = byteOrder 28 29 data = data[6:] 30 if dwarf64 { 31 data = data[8:] 32 } 33 34 addrSz := data[0] 35 segSelSz := data[1] 36 r.ptrSz = int(addrSz + segSelSz) 37 38 // Not read: 39 // - offset_entry_count (4 bytes) 40 // - offset table (offset_entry_count*4 or offset_entry_count*8 if dwarf64 is set) 41 42 return r 43 } 44 45 func (rdr *Dwarf5Reader) Empty() bool { 46 return rdr == nil 47 } 48 49 // Find returns the loclist entry for the specified PC address, inside the 50 // loclist stating at off. Base is the base address of the compile unit and 51 // staticBase is the static base at which the image is loaded. 52 func (rdr *Dwarf5Reader) Find(off int, staticBase, base, pc uint64, debugAddr *godwarf.DebugAddr) (*Entry, error) { 53 it := &loclistsIterator{rdr: rdr, debugAddr: debugAddr, buf: bytes.NewBuffer(rdr.data), base: base, staticBase: staticBase} 54 it.buf.Next(off) 55 56 for it.next() { 57 if !it.onRange { 58 continue 59 } 60 if it.start <= pc && pc < it.end { 61 return &Entry{it.start, it.end, it.instr}, nil 62 } 63 } 64 65 if it.err != nil { 66 return nil, it.err 67 } 68 69 if it.defaultInstr != nil { 70 return &Entry{pc, pc + 1, it.defaultInstr}, nil 71 } 72 73 return nil, nil 74 } 75 76 type loclistsIterator struct { 77 rdr *Dwarf5Reader 78 debugAddr *godwarf.DebugAddr 79 buf *bytes.Buffer 80 staticBase uint64 81 base uint64 // base for offsets in the list 82 83 onRange bool 84 atEnd bool 85 start, end uint64 86 instr []byte 87 defaultInstr []byte 88 err error 89 } 90 91 const ( 92 _DW_LLE_end_of_list uint8 = 0x0 93 _DW_LLE_base_addressx uint8 = 0x1 94 _DW_LLE_startx_endx uint8 = 0x2 95 _DW_LLE_startx_length uint8 = 0x3 96 _DW_LLE_offset_pair uint8 = 0x4 97 _DW_LLE_default_location uint8 = 0x5 98 _DW_LLE_base_address uint8 = 0x6 99 _DW_LLE_start_end uint8 = 0x7 100 _DW_LLE_start_length uint8 = 0x8 101 ) 102 103 func (it *loclistsIterator) next() bool { 104 if it.err != nil || it.atEnd { 105 return false 106 } 107 opcode, err := it.buf.ReadByte() 108 if err != nil { 109 it.err = err 110 return false 111 } 112 switch opcode { 113 case _DW_LLE_end_of_list: 114 it.atEnd = true 115 it.onRange = false 116 return false 117 118 case _DW_LLE_base_addressx: 119 baseIdx, _ := util.DecodeULEB128(it.buf) 120 if err != nil { 121 it.err = err 122 return false 123 } 124 it.base, it.err = it.debugAddr.Get(baseIdx) 125 it.base += it.staticBase 126 it.onRange = false 127 128 case _DW_LLE_startx_endx: 129 startIdx, _ := util.DecodeULEB128(it.buf) 130 endIdx, _ := util.DecodeULEB128(it.buf) 131 it.readInstr() 132 133 it.start, it.err = it.debugAddr.Get(startIdx) 134 if it.err == nil { 135 it.end, it.err = it.debugAddr.Get(endIdx) 136 } 137 it.onRange = true 138 139 case _DW_LLE_startx_length: 140 startIdx, _ := util.DecodeULEB128(it.buf) 141 length, _ := util.DecodeULEB128(it.buf) 142 it.readInstr() 143 144 it.start, it.err = it.debugAddr.Get(startIdx) 145 it.end = it.start + length 146 it.onRange = true 147 148 case _DW_LLE_offset_pair: 149 off1, _ := util.DecodeULEB128(it.buf) 150 off2, _ := util.DecodeULEB128(it.buf) 151 it.readInstr() 152 153 it.start = it.base + off1 154 it.end = it.base + off2 155 it.onRange = true 156 157 case _DW_LLE_default_location: 158 it.readInstr() 159 it.defaultInstr = it.instr 160 it.onRange = false 161 162 case _DW_LLE_base_address: 163 it.base, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 164 it.base += it.staticBase 165 it.onRange = false 166 167 case _DW_LLE_start_end: 168 it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 169 it.end, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 170 it.readInstr() 171 it.onRange = true 172 173 case _DW_LLE_start_length: 174 it.start, it.err = util.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz) 175 length, _ := util.DecodeULEB128(it.buf) 176 it.readInstr() 177 it.end = it.start + length 178 it.onRange = true 179 180 default: 181 it.err = fmt.Errorf("unknown opcode %#x at %#x", opcode, len(it.rdr.data)-it.buf.Len()) 182 it.onRange = false 183 it.atEnd = true 184 return false 185 } 186 187 return true 188 } 189 190 func (it *loclistsIterator) readInstr() { 191 length, _ := util.DecodeULEB128(it.buf) 192 it.instr = it.buf.Next(int(length)) 193 }