github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/frame/entries.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 frame
    23  
    24  import (
    25  	"encoding/binary"
    26  	"fmt"
    27  	"sort"
    28  )
    29  
    30  
    31  
    32  type CommonInformationEntry struct {
    33  	Length                uint32
    34  	CIE_id                uint32
    35  	Version               uint8
    36  	Augmentation          string
    37  	CodeAlignmentFactor   uint64
    38  	DataAlignmentFactor   int64
    39  	ReturnAddressRegister uint64
    40  	InitialInstructions   []byte
    41  	staticBase            uint64
    42  
    43  	
    44  	ptrEncAddr ptrEnc
    45  }
    46  
    47  
    48  
    49  type FrameDescriptionEntry struct {
    50  	Length       uint32
    51  	CIE          *CommonInformationEntry
    52  	Instructions []byte
    53  	begin, size  uint64
    54  	order        binary.ByteOrder
    55  }
    56  
    57  
    58  
    59  func (fde *FrameDescriptionEntry) Cover(addr uint64) bool {
    60  	return (addr - fde.begin) < fde.size
    61  }
    62  
    63  
    64  func (fde *FrameDescriptionEntry) Begin() uint64 {
    65  	return fde.begin
    66  }
    67  
    68  
    69  func (fde *FrameDescriptionEntry) End() uint64 {
    70  	return fde.begin + fde.size
    71  }
    72  
    73  
    74  func (fde *FrameDescriptionEntry) Translate(delta uint64) {
    75  	fde.begin += delta
    76  }
    77  
    78  
    79  func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
    80  	return executeDwarfProgramUntilPC(fde, pc)
    81  }
    82  
    83  type FrameDescriptionEntries []*FrameDescriptionEntry
    84  
    85  func newFrameIndex() FrameDescriptionEntries {
    86  	return make(FrameDescriptionEntries, 0, 1000)
    87  }
    88  
    89  
    90  type ErrNoFDEForPC struct {
    91  	PC uint64
    92  }
    93  
    94  func (err *ErrNoFDEForPC) Error() string {
    95  	return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
    96  }
    97  
    98  
    99  func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
   100  	idx := sort.Search(len(fdes), func(i int) bool {
   101  		return fdes[i].Cover(pc) || fdes[i].Begin() >= pc
   102  	})
   103  	if idx == len(fdes) || !fdes[idx].Cover(pc) {
   104  		return nil, &ErrNoFDEForPC{pc}
   105  	}
   106  	return fdes[idx], nil
   107  }
   108  
   109  
   110  func (fdes FrameDescriptionEntries) Append(otherFDEs FrameDescriptionEntries) FrameDescriptionEntries {
   111  	r := append(fdes, otherFDEs...)
   112  	sort.SliceStable(r, func(i, j int) bool {
   113  		return r[i].Begin() < r[j].Begin()
   114  	})
   115  	
   116  	uniqFDEs := fdes[:0]
   117  	for _, fde := range fdes {
   118  		if len(uniqFDEs) > 0 {
   119  			last := uniqFDEs[len(uniqFDEs)-1]
   120  			if last.Begin() == fde.Begin() && last.End() == fde.End() {
   121  				continue
   122  			}
   123  		}
   124  		uniqFDEs = append(uniqFDEs, fde)
   125  	}
   126  	return r
   127  }
   128  
   129  
   130  
   131  
   132  
   133  
   134  
   135  type ptrEnc uint8
   136  
   137  const (
   138  	ptrEncAbs    ptrEnc = 0x00 
   139  	ptrEncOmit   ptrEnc = 0xff 
   140  	ptrEncUleb   ptrEnc = 0x01 
   141  	ptrEncUdata2 ptrEnc = 0x02 
   142  	ptrEncUdata4 ptrEnc = 0x03 
   143  	ptrEncUdata8 ptrEnc = 0x04 
   144  	ptrEncSigned ptrEnc = 0x08 
   145  	ptrEncSleb   ptrEnc = 0x09 
   146  	ptrEncSdata2 ptrEnc = 0x0a 
   147  	ptrEncSdata4 ptrEnc = 0x0b 
   148  	ptrEncSdata8 ptrEnc = 0x0c 
   149  
   150  	ptrEncPCRel    ptrEnc = 0x10 
   151  	ptrEncTextRel  ptrEnc = 0x20 
   152  	ptrEncDataRel  ptrEnc = 0x30 
   153  	ptrEncFuncRel  ptrEnc = 0x40 
   154  	ptrEncAligned  ptrEnc = 0x50 
   155  	ptrEncIndirect ptrEnc = 0x80 
   156  )
   157  
   158  
   159  func (ptrEnc ptrEnc) Supported() bool {
   160  	if ptrEnc != ptrEncOmit {
   161  		szenc := ptrEnc & 0x0f
   162  		if ((szenc > ptrEncUdata8) && (szenc < ptrEncSigned)) || (szenc > ptrEncSdata8) {
   163  			
   164  			return false
   165  		}
   166  		if ptrEnc&0xf0 != ptrEncPCRel {
   167  			
   168  			return false
   169  		}
   170  	}
   171  	return true
   172  }