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 }