github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/obj/x86/seh.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE.assembler file. 4 5 package x86 6 7 import ( 8 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj" 9 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi" 10 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/src" 11 "encoding/base64" 12 "fmt" 13 "math" 14 ) 15 16 type sehbuf struct { 17 ctxt *obj.Link 18 data []byte 19 off int 20 } 21 22 func newsehbuf(ctxt *obj.Link, nodes uint8) sehbuf { 23 24 25 26 size := 8 + nodes*2 27 if nodes%2 != 0 { 28 size += 2 29 } 30 return sehbuf{ctxt, make([]byte, size), 0} 31 } 32 33 func (b *sehbuf) write8(v uint8) { 34 b.data[b.off] = v 35 b.off++ 36 } 37 38 func (b *sehbuf) write32(v uint32) { 39 b.ctxt.Arch.ByteOrder.PutUint32(b.data[b.off:], v) 40 b.off += 4 41 } 42 43 func (b *sehbuf) writecode(op, value uint8) { 44 b.write8(value<<4 | op) 45 } 46 47 48 func populateSeh(ctxt *obj.Link, s *obj.LSym) (sehsym *obj.LSym) { 49 if s.NoFrame() { 50 return 51 } 52 53 54 55 56 57 58 59 60 61 62 var pushbp *obj.Prog 63 for p := s.Func().Text; p != nil; p = p.Link { 64 if p.As == APUSHQ && p.From.Type == obj.TYPE_REG && p.From.Reg == REG_BP { 65 pushbp = p 66 break 67 } 68 if p.Pos.Xlogue() == src.PosPrologueEnd { 69 break 70 } 71 } 72 if pushbp == nil { 73 ctxt.Diag("missing frame pointer instruction: PUSHQ BP") 74 return 75 } 76 77 78 movbp := pushbp.Link 79 if movbp == nil { 80 ctxt.Diag("missing frame pointer instruction: MOVQ SP, BP") 81 return 82 } 83 if !(movbp.As == AMOVQ && movbp.From.Type == obj.TYPE_REG && movbp.From.Reg == REG_SP && 84 movbp.To.Type == obj.TYPE_REG && movbp.To.Reg == REG_BP && movbp.From.Offset == 0) { 85 ctxt.Diag("unexpected frame pointer instruction\n%v", movbp) 86 return 87 } 88 if movbp.Link.Pc > math.MaxUint8 { 89 90 91 92 93 return 94 } 95 96 97 98 99 const ( 100 UWOP_PUSH_NONVOL = 0 101 UWOP_SET_FPREG = 3 102 SEH_REG_BP = 5 103 ) 104 105 106 107 108 nodes := uint8(2) 109 buf := newsehbuf(ctxt, nodes) 110 buf.write8(1) 111 buf.write8(uint8(movbp.Link.Pc)) 112 buf.write8(nodes) 113 buf.write8(SEH_REG_BP) 114 115 116 buf.write8(uint8(movbp.Link.Pc)) 117 buf.writecode(UWOP_SET_FPREG, 0) 118 119 buf.write8(uint8(pushbp.Link.Pc)) 120 buf.writecode(UWOP_PUSH_NONVOL, SEH_REG_BP) 121 122 123 124 buf.write32(0) 125 126 127 128 129 130 hash := base64.StdEncoding.EncodeToString(buf.data) 131 symname := fmt.Sprintf("%d.%s", len(buf.data), hash) 132 return ctxt.LookupInit("go:sehuw."+symname, func(s *obj.LSym) { 133 s.WriteBytes(ctxt, 0, buf.data) 134 s.Type = objabi.SSEHUNWINDINFO 135 s.Set(obj.AttrDuplicateOK, true) 136 s.Set(obj.AttrLocal, true) 137 138 139 140 }) 141 }