github.com/tencent/goom@v1.0.1/internal/patch/guard.go (about)

     1  // Package patch 生成指令跳转(到代理函数)并替换.text 区内存
     2  package patch
     3  
     4  import (
     5  	"fmt"
     6  
     7  	"github.com/tencent/goom/internal/bytecode"
     8  	"github.com/tencent/goom/internal/bytecode/memory"
     9  	"github.com/tencent/goom/internal/logger"
    10  )
    11  
    12  // Guard 代理执行控制句柄, 可通过此对象进行代理还原
    13  type Guard struct {
    14  	origin       uintptr // 被 patch 的函数
    15  	originBytes  []byte  // 原始字节码
    16  	jumpBytes    []byte  // 跳转指令字节
    17  	fixOriginPtr uintptr // 修复的函数指针
    18  	applied      bool    // 是否已经被应用
    19  }
    20  
    21  // Apply 执行
    22  func (g *Guard) Apply() {
    23  	lock()
    24  	defer unlock()
    25  
    26  	g.applied = true
    27  	// 执行函数调用地址替换(延迟执行)
    28  	if err := memory.WriteTo(g.origin, g.jumpBytes); err != nil {
    29  		logger.Errorf("Apply to 0x%x error: %s", g.origin, err)
    30  	}
    31  	bytecode.PrintInst(fmt.Sprintf("apply copy to 0x%x", g.origin), g.origin, 30, logger.DebugLevel)
    32  }
    33  
    34  // Unpatch 取消代理,还原指令码
    35  // 外部调用请使用 PatchGuard.UnpatchWithLock()
    36  func (g *Guard) Unpatch() {
    37  	if g != nil && g.applied {
    38  		if err := memory.WriteTo(g.origin, g.originBytes); err != nil {
    39  			logger.Errorf("Unpatch to 0x%x error: %s", g.origin, err)
    40  		}
    41  		bytecode.PrintInst(fmt.Sprintf("unpatch copy to 0x%x", g.origin), g.origin, 20, logger.DebugLevel)
    42  	}
    43  }
    44  
    45  // UnpatchWithLock 外部调用需要加锁
    46  func (g *Guard) UnpatchWithLock() {
    47  	lock()
    48  	defer unlock()
    49  	g.Unpatch()
    50  }
    51  
    52  // Restore 重新应用代理
    53  func (g *Guard) Restore() {
    54  	lock()
    55  	defer unlock()
    56  	if g != nil && g.applied {
    57  		if err := memory.WriteTo(g.origin, g.jumpBytes); err != nil {
    58  			logger.Errorf("Restore to 0x%x error: %s", g.origin, err)
    59  		}
    60  		bytecode.PrintInst(fmt.Sprintf("unpatch copy to 0x%x", g.origin), g.origin, 20, logger.DebugLevel)
    61  	}
    62  }
    63  
    64  // FixOriginFunc 获取应用代理后的原函数地址(和代理前的原函数地址不一样)
    65  func (g *Guard) FixOriginFunc() uintptr {
    66  	return g.fixOriginPtr
    67  }