github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/dwarf/frame/entries.go (about)

     1  package frame
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"sort"
     7  )
     8  
     9  // CommonInformationEntry represents a Common Information Entry in
    10  // the Dwarf .debug_frame section.
    11  type CommonInformationEntry struct {
    12  	Length                uint32
    13  	CIE_id                uint32
    14  	Version               uint8
    15  	Augmentation          string
    16  	CodeAlignmentFactor   uint64
    17  	DataAlignmentFactor   int64
    18  	ReturnAddressRegister uint64
    19  	InitialInstructions   []byte
    20  	staticBase            uint64
    21  
    22  	// eh_frame pointer encoding
    23  	ptrEncAddr ptrEnc
    24  }
    25  
    26  // FrameDescriptionEntry represents a Frame Descriptor Entry in the
    27  // Dwarf .debug_frame section.
    28  type FrameDescriptionEntry struct {
    29  	Length       uint32
    30  	CIE          *CommonInformationEntry
    31  	Instructions []byte
    32  	begin, size  uint64
    33  	order        binary.ByteOrder
    34  }
    35  
    36  // Cover returns whether or not the given address is within the
    37  // bounds of this frame.
    38  func (fde *FrameDescriptionEntry) Cover(addr uint64) bool {
    39  	return (addr - fde.begin) < fde.size
    40  }
    41  
    42  // Begin returns address of first location for this frame.
    43  func (fde *FrameDescriptionEntry) Begin() uint64 {
    44  	return fde.begin
    45  }
    46  
    47  // End returns address of last location for this frame.
    48  func (fde *FrameDescriptionEntry) End() uint64 {
    49  	return fde.begin + fde.size
    50  }
    51  
    52  // Translate moves the beginning of fde forward by delta.
    53  func (fde *FrameDescriptionEntry) Translate(delta uint64) {
    54  	fde.begin += delta
    55  }
    56  
    57  // EstablishFrame set up frame for the given PC.
    58  func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
    59  	return executeDwarfProgramUntilPC(fde, pc)
    60  }
    61  
    62  type FrameDescriptionEntries []*FrameDescriptionEntry
    63  
    64  func newFrameIndex() FrameDescriptionEntries {
    65  	return make(FrameDescriptionEntries, 0, 1000)
    66  }
    67  
    68  // ErrNoFDEForPC FDE for PC not found error
    69  type ErrNoFDEForPC struct {
    70  	PC uint64
    71  }
    72  
    73  func (err *ErrNoFDEForPC) Error() string {
    74  	return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
    75  }
    76  
    77  // FDEForPC returns the Frame Description Entry for the given PC.
    78  func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
    79  	idx := sort.Search(len(fdes), func(i int) bool {
    80  		return fdes[i].Cover(pc) || fdes[i].Begin() >= pc
    81  	})
    82  	if idx == len(fdes) || !fdes[idx].Cover(pc) {
    83  		return nil, &ErrNoFDEForPC{pc}
    84  	}
    85  	return fdes[idx], nil
    86  }
    87  
    88  // Append appends otherFDEs to fdes and returns the result.
    89  func (fdes FrameDescriptionEntries) Append(otherFDEs FrameDescriptionEntries) FrameDescriptionEntries {
    90  	r := append(fdes, otherFDEs...)
    91  	sort.SliceStable(r, func(i, j int) bool {
    92  		return r[i].Begin() < r[j].Begin()
    93  	})
    94  	if len(r) < 2 { // fast path, no duplicates
    95  		return r
    96  	}
    97  
    98  	// remove duplicates
    99  	slow := 1
   100  	for fast := 1; fast < len(r); fast++ {
   101  		if r[fast].Begin() != r[fast-1].Begin() || r[fast].End() != r[fast-1].End() {
   102  			if slow != fast {
   103  				r[slow] = r[fast]
   104  			}
   105  			slow++
   106  		}
   107  	}
   108  	return r[:slow]
   109  }
   110  
   111  // ptrEnc represents a pointer encoding value, used during eh_frame decoding
   112  // to determine how pointers were encoded.
   113  // Least significant 4 (0xf) bytes encode the size  as well as its
   114  // signed-ness,  most significant 4 bytes (0xf0 == ptrEncFlagsMask) are flags
   115  // describing how the value should be interpreted (absolute, relative...)
   116  // See https://www.airs.com/blog/archives/460.
   117  type ptrEnc uint8
   118  
   119  const (
   120  	ptrEncAbs    ptrEnc = 0x00 // pointer-sized unsigned integer
   121  	ptrEncOmit   ptrEnc = 0xff // omitted
   122  	ptrEncUleb   ptrEnc = 0x01 // ULEB128
   123  	ptrEncUdata2 ptrEnc = 0x02 // 2 bytes
   124  	ptrEncUdata4 ptrEnc = 0x03 // 4 bytes
   125  	ptrEncUdata8 ptrEnc = 0x04 // 8 bytes
   126  	ptrEncSigned ptrEnc = 0x08 // pointer-sized signed integer
   127  	ptrEncSleb   ptrEnc = 0x09 // SLEB128
   128  	ptrEncSdata2 ptrEnc = 0x0a // 2 bytes, signed
   129  	ptrEncSdata4 ptrEnc = 0x0b // 4 bytes, signed
   130  	ptrEncSdata8 ptrEnc = 0x0c // 8 bytes, signed
   131  
   132  	ptrEncFlagsMask ptrEnc = 0xf0
   133  
   134  	ptrEncPCRel    ptrEnc = 0x10 // value is relative to the memory address where it appears
   135  	ptrEncTextRel  ptrEnc = 0x20 // value is relative to the address of the text section
   136  	ptrEncDataRel  ptrEnc = 0x30 // value is relative to the address of the data section
   137  	ptrEncFuncRel  ptrEnc = 0x40 // value is relative to the start of the function
   138  	ptrEncAligned  ptrEnc = 0x50 // value should be aligned
   139  	ptrEncIndirect ptrEnc = 0x80 // value is an address where the real value of the pointer is stored
   140  
   141  	ptrEncSupportedFlags = ptrEncPCRel
   142  )
   143  
   144  // Supported returns true if this pointer encoding is supported.
   145  func (ptrEnc ptrEnc) Supported() bool {
   146  	if ptrEnc != ptrEncOmit {
   147  		szenc := ptrEnc & 0x0f
   148  		if ((szenc > ptrEncUdata8) && (szenc < ptrEncSigned)) || (szenc > ptrEncSdata8) {
   149  			// These values aren't defined at the moment
   150  			return false
   151  		}
   152  		if (ptrEnc&ptrEncFlagsMask)&^ptrEncSupportedFlags != 0 {
   153  			// Currently only the PC relative flag is supported
   154  			return false
   155  		}
   156  	}
   157  	return true
   158  }