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  }