Skip to content

MacOS m3 打桩失败bug #171

Open
Open
@liracle

Description

@liracle

环境

MacOS: 14.6
GO版本: go1.21.13 (也测试了go1.18版本也有问题)
M3芯片
gomonkey版本: v2.12.0

问题描述

在一个测试用例中对同一个函数进行打桩、取消、再打桩,后续的打桩可能会失败。以下为测试代码,可以直接拷贝执行验证的

type funcValue struct {
	_ uintptr
	p unsafe.Pointer
}

func getPointer(v reflect.Value) unsafe.Pointer {
	return (*funcValue)(unsafe.Pointer(&v)).p
}

func entryAddress(p uintptr, l int) []byte {
	return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: p, Len: l, Cap: l}))
}

func target() {
	fmt.Println("origin func invoked")
}

// func24Byte 此函数将函数对应的代码code前24个字节打印出来,方便观察打桩是否生效了
func func24Byte(fn interface{}) {
	v := reflect.ValueOf(fn)
	pp := *(*uintptr)(getPointer(v))
	addr := entryAddress(pp, 24)
	fmt.Printf("代码code:%x\n", addr)
}

func TestBBB(t *testing.T) {
	p := gomonkey.NewPatches()
	pause := true  // 控制每次打桩后是否需要sleep,sleep会影响打桩是否生效,sleep后打桩稳定生效,不sleep打桩不一定会生效
        // 输出原始函数
	fmt.Println("expect origin func:") 
	target()
	func24Byte(target) 

        // 第一次打桩
	p.ApplyFunc(target, func() {
		fmt.Println("double func invoked")
	})
	if pause {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("expect double func")
	target()
	func24Byte(target)

        // 恢复
	p.Reset()
	if pause {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("expect origin func")
	target()
	func24Byte(target)
	
        // 第二次打桩
	p2 := gomonkey.NewPatches()
	p2.ApplyFunc(target, func() {
		fmt.Println("three func invoked")
	})
	if pause {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("expect three func")
	target()
	func24Byte(target)

        // 恢复
	p2.Reset()
	if pause {
		time.Sleep(time.Millisecond)
	}
	fmt.Println("expect origin func")
	target()
	func24Byte(target)
}

当使用pause=true 执行测试时,测试完美执行,执行结果如下:
image
但是当运行pause=false时,测试结果如下:
image

我耗费两天观察这个问题,依然百思不得其解,为什么代码区字节码都被改写了,funcValue的调用依然不生效呢,辛苦各位大佬帮忙看下@agiledragon

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions