github.com/bytedance/mockey@v1.2.10/internal/monkey/fn/inject.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  	"reflect"
    21  	"unsafe"
    22  
    23  	"github.com/bytedance/mockey/internal/monkey/common"
    24  	"github.com/bytedance/mockey/internal/monkey/mem/prot"
    25  	"github.com/bytedance/mockey/internal/tool"
    26  )
    27  
    28  // InjectInto injects the raw codes into the target to make a new function. The target is the target function pointer.
    29  func InjectInto(target reflect.Value, fnCode []byte) {
    30  	vt := target.Type()
    31  	tool.Assert(vt.Kind() == reflect.Ptr, "target is not a pointer")
    32  	tool.Assert(vt.Elem().Kind() == reflect.Func, "target is not a function pointer")
    33  
    34  	// ensure the code is executable
    35  	err := prot.MProtectRX(fnCode)
    36  	tool.Assert(err == nil, "protect page failed")
    37  
    38  	// make a new function to receive the code
    39  	carrier := reflect.MakeFunc(vt.Elem(), nil)
    40  	type function struct {
    41  		_      uintptr
    42  		fnAddr *uintptr
    43  	}
    44  	*(*function)(unsafe.Pointer(&carrier)).fnAddr = common.PtrOf(fnCode)
    45  
    46  	// set the target with the new made function
    47  	target.Elem().Set(carrier)
    48  }