github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/loclist/dwarf2_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 "encoding/binary" 26 27 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf" 28 ) 29 30 31 type Reader interface { 32 Find(off int, staticBase, base, pc uint64, debugAddr *godwarf.DebugAddr) (*Entry, error) 33 Empty() bool 34 } 35 36 37 type Dwarf2Reader struct { 38 data []byte 39 cur int 40 ptrSz int 41 } 42 43 44 func NewDwarf2Reader(data []byte, ptrSz int) *Dwarf2Reader { 45 return &Dwarf2Reader{data: data, ptrSz: ptrSz} 46 } 47 48 49 func (rdr *Dwarf2Reader) Empty() bool { 50 return rdr.data == nil 51 } 52 53 54 func (rdr *Dwarf2Reader) Seek(off int) { 55 rdr.cur = off 56 } 57 58 59 60 func (rdr *Dwarf2Reader) Next(e *Entry) bool { 61 e.LowPC = rdr.oneAddr() 62 e.HighPC = rdr.oneAddr() 63 64 if e.LowPC == 0 && e.HighPC == 0 { 65 return false 66 } 67 68 if e.BaseAddressSelection() { 69 e.Instr = nil 70 return true 71 } 72 73 instrlen := binary.LittleEndian.Uint16(rdr.read(2)) 74 e.Instr = rdr.read(int(instrlen)) 75 return true 76 } 77 78 79 80 81 func (rdr *Dwarf2Reader) Find(off int, staticBase, base, pc uint64, debugAddr *godwarf.DebugAddr) (*Entry, error) { 82 rdr.Seek(off) 83 var e Entry 84 for rdr.Next(&e) { 85 if e.BaseAddressSelection() { 86 base = e.HighPC + staticBase 87 continue 88 } 89 if pc >= e.LowPC+base && pc < e.HighPC+base { 90 return &e, nil 91 } 92 } 93 return nil, nil 94 } 95 96 func (rdr *Dwarf2Reader) read(sz int) []byte { 97 r := rdr.data[rdr.cur : rdr.cur+sz] 98 rdr.cur += sz 99 return r 100 } 101 102 func (rdr *Dwarf2Reader) oneAddr() uint64 { 103 switch rdr.ptrSz { 104 case 4: 105 addr := binary.LittleEndian.Uint32(rdr.read(rdr.ptrSz)) 106 if addr == ^uint32(0) { 107 return ^uint64(0) 108 } 109 return uint64(addr) 110 case 8: 111 addr := uint64(binary.LittleEndian.Uint64(rdr.read(rdr.ptrSz))) 112 return addr 113 default: 114 panic("bad address size") 115 } 116 } 117 118 119 type Entry struct { 120 LowPC, HighPC uint64 121 Instr []byte 122 } 123 124 125 126 func (e *Entry) BaseAddressSelection() bool { 127 return e.LowPC == ^uint64(0) 128 }