github.com/undoio/delve@v1.9.0/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 // remove duplicates 95 uniqFDEs := fdes[:0] 96 for _, fde := range fdes { 97 if len(uniqFDEs) > 0 { 98 last := uniqFDEs[len(uniqFDEs)-1] 99 if last.Begin() == fde.Begin() && last.End() == fde.End() { 100 continue 101 } 102 } 103 uniqFDEs = append(uniqFDEs, fde) 104 } 105 return r 106 } 107 108 // ptrEnc represents a pointer encoding value, used during eh_frame decoding 109 // to determine how pointers were encoded. 110 // Least significant 4 (0xf) bytes encode the size as well as its 111 // signed-ness, most significant 4 bytes (0xf0 == ptrEncFlagsMask) are flags 112 // describing how the value should be interpreted (absolute, relative...) 113 // See https://www.airs.com/blog/archives/460. 114 type ptrEnc uint8 115 116 const ( 117 ptrEncAbs ptrEnc = 0x00 // pointer-sized unsigned integer 118 ptrEncOmit ptrEnc = 0xff // omitted 119 ptrEncUleb ptrEnc = 0x01 // ULEB128 120 ptrEncUdata2 ptrEnc = 0x02 // 2 bytes 121 ptrEncUdata4 ptrEnc = 0x03 // 4 bytes 122 ptrEncUdata8 ptrEnc = 0x04 // 8 bytes 123 ptrEncSigned ptrEnc = 0x08 // pointer-sized signed integer 124 ptrEncSleb ptrEnc = 0x09 // SLEB128 125 ptrEncSdata2 ptrEnc = 0x0a // 2 bytes, signed 126 ptrEncSdata4 ptrEnc = 0x0b // 4 bytes, signed 127 ptrEncSdata8 ptrEnc = 0x0c // 8 bytes, signed 128 129 ptrEncFlagsMask ptrEnc = 0xf0 130 131 ptrEncPCRel ptrEnc = 0x10 // value is relative to the memory address where it appears 132 ptrEncTextRel ptrEnc = 0x20 // value is relative to the address of the text section 133 ptrEncDataRel ptrEnc = 0x30 // value is relative to the address of the data section 134 ptrEncFuncRel ptrEnc = 0x40 // value is relative to the start of the function 135 ptrEncAligned ptrEnc = 0x50 // value should be aligned 136 ptrEncIndirect ptrEnc = 0x80 // value is an address where the real value of the pointer is stored 137 138 ptrEncSupportedFlags = ptrEncPCRel 139 ) 140 141 // Supported returns true if this pointer encoding is supported. 142 func (ptrEnc ptrEnc) Supported() bool { 143 if ptrEnc != ptrEncOmit { 144 szenc := ptrEnc & 0x0f 145 if ((szenc > ptrEncUdata8) && (szenc < ptrEncSigned)) || (szenc > ptrEncSdata8) { 146 // These values aren't defined at the moment 147 return false 148 } 149 if (ptrEnc&ptrEncFlagsMask)&^ptrEncSupportedFlags != 0 { 150 // Currently only the PC relative flag is supported 151 return false 152 } 153 } 154 return true 155 }