github.com/bytedance/mockey@v1.2.10/internal/monkey/fn/copy_darwin_amd64.go (about)

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package fn
    18  
    19  import (
    20  	"unsafe"
    21  
    22  	"github.com/bytedance/mockey/internal/monkey/common"
    23  	"github.com/bytedance/mockey/internal/tool"
    24  	"golang.org/x/arch/x86/x86asm"
    25  )
    26  
    27  func copyCode(targetCode, oriCode []byte) {
    28  	var (
    29  		inst    x86asm.Inst // current code
    30  		n       int         // length of total codes
    31  		callIdx []int       // index list of call instruction
    32  		err     error
    33  	)
    34  	for inst.Op != x86asm.RET {
    35  		inst, err = x86asm.Decode(oriCode[n:], 64)
    36  		tool.Assert(err == nil, err)
    37  		tool.DebugPrintf("copyCode: inst: %v\n", inst)
    38  		if inst.Op == x86asm.CALL {
    39  			callIdx = append(callIdx, n)
    40  			tool.DebugPrintf("copyCode: call code: 0x%x\n", oriCode[n:n+5])
    41  		}
    42  		n += inst.Len
    43  	}
    44  	// copy function codes to the target
    45  	i := copy(targetCode, oriCode[:n])
    46  	tool.DebugPrintf("copyCode: oriCode len(%v), copied len(%v)\n", n, i)
    47  	// replace the relative call addresses
    48  	callOffset := int32(common.PtrOf(oriCode) - common.PtrOf(targetCode))
    49  	tool.DebugPrintf("copyCode: offset: %x\n", callOffset)
    50  	for _, idx := range callIdx {
    51  		*(*int32)(unsafe.Pointer(&targetCode[idx+1])) += callOffset
    52  	}
    53  }