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  }