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  }