xgo: golang基于-toolexec实现猴子补丁

注: 转载请注明出处, 原文链接。

概述

在这篇博客中,我将详细介绍 xgo 的实现细节。

如果你不知道,xgo 项目位于 https://github.com/xhd2015/xgo。

它的作用很简单,就是在每个 Go 函数的开头添加拦截器,从而引入了所谓的 Trap 概念,然后在此基础上引入了其他功能,比如 MockPatchTrace

什么是 Trap?

Trap 是插入到函数体开头的一段代码。以一个名为 greet 的函数为例:

func greet(s string) string {
    return "hello " + s
}

经过xgo的处理后,编译器看到的代码将变为:

import "runtime"

func greet(s string) (r0 string){
    stop, post := runtime.__xgo_trap(greet, &s, &r0)
    if stop {
        return
    }
    defer post()
    return "hello " +s
}

这两者的差异可以通过下面的图表来可视化:
在这里插入图片描述

如图所示,一旦函数被调用,它的控制流首先转移到 Trap,然后一系列拦截器将根据其目的检查当前调用是否应该被Mock、修改、记录或停止。

这个想法很简单,但也引发了一些问题:

  • 编译器如何看到插桩后的代码?
  • import runtime 是什么?

这两个问题反映了 xgo 的两个基本部分:编译器插桩和运行时插桩。

让我们先看看第一个问题。

编译器如何看到插桩后的代码?

为了让编译器看到与其原始源代码不同的代码,中间必须发生某种事情。

有趣的是,go build 有一个名为-toolexec的标志:

$ go help build
...
-toolexec 'cmd args'
        a program to use to invoke toolchain programs like vet and asm.
        For example, instead of running asm, the go command will run
        'cmd args /path/to/asm <arguments for asm>'.
        The TOOLEXEC_IMPORTPATH environment variable will be set,
        matching 'go list -f {{.ImportPath}}' for the package being built.
...

如果你搜索 go toolexec,甚至有一个示例:https://go.dev/src/cmd/go/testdata/script/toolexec.txt。

简而言之,-toolexec 标志允许用户拦截 go 调用的每个 compilelink 命令,并根据需要执行某种插桩,如下图所示:
在这里插入图片描述
请注意,当你在 go build 中添加 -toolexec=my_tool 标志时,它不会直接调用 compile argslink args,而是将这些调用转发给 my_tool <cmd> args

因此,xgo 利用这个标志来拦截 compile 命令,将所有的编译转发到增强后的编译器。

然后,增强后的编译器将在每个函数中插入这些Trap调用,为运行时在实际调用之前捕获函数调用提供机会。

import runtime 是什么?

现在,编译器已经为我们添加了Trap调用,我们如何知道需要进行什么样的检查?

我们不能让每个包都依赖于 xgo,因为它们可能并不需要它。

好在 runtime 也被插桩了,将调用转发给 xgo。因为在 Go 中,每个包都隐式依赖于 runtime 包。控制流程如下图所示:
在这里插入图片描述

这实际上是一种依赖注入。这样一来,用户的代码就不必显式依赖xgo。

上述代码可以在 runtime/trap_runtime/xgo_trap.go 和 runtime/trap/trap.go 中找到。

为了使Trap可扩展,xgo 引入了一个名为 interceptor 的概念。它具有以下签名:

type Interceptor struct {
	Pre  func(ctx context.Context, f *core.FuncInfo, args core.Object, result core.Object) (data interface{}, err error)
	Post func(ctx context.Context, f *core.FuncInfo, args core.Object, result core.Object, data interface{}) error
}

一个 interceptor 由两个子函数组成,称为 PrePost

  • Pre 在函数逻辑之前调用,
  • Post 在函数逻辑之后使用 defer 语句调用。

总结

让我们总结一下我们所讨论的内容。

当你运行 xgo test ./ 时,它会执行以下操作:

  1. 找到 GOROOT,
  2. 将 GOROOT 复制到 ~/.xgo/go-instruments/GOROOT 以准备进行插桩,
  3. 对 ~/.xgo/go-instruments/GOROOT 进行补丁,包括编译器和运行时,
  4. 构建插桩的编译器,
  5. 使用额外的标志调用 go build:go build -toolexec=exec_tool ./
  6. exec_tool 然后将所有编译命令转发给插桩的编译器,
  7. 一旦所有编译完成,go 调用 link 生成可执行文件,你就得到了一个插桩的二进制文件!

优点和缺点

因此,xgo 从上述机制中获得了优点和缺点。
优点:

  • 并发安全:它不会替换需要修改全局地址的函数,因此每个 goroutine 可以设置自己的拦截器并单独删除它们,
  • 兼容性:它重写源代码而不是架构指令,因此与操作系统和架构无关,
  • 可扩展性:它提供了通用的拦截器,因此它的用途不仅限于模拟,你可以借鉴 GRPC 拦截器的所有用途,比如已经实现的追踪、缓存、日志记录等…

缺点:

  • 用户需要安装 xgo 才能启用陷阱功能。

感谢阅读,xgo的核心实现已经在上面全部介绍了。你对此有什么看法?请在这里留下评论,让我们一起讨论吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/526012.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python-面向对象编程

面向对象编程 面向对象&#xff0c;python中支持两种编程方式&#xff0c;来写代码&#xff0c;分别是&#xff1a;函数式编程和面向对象 函数式&#xff1a; # 定义函数&#xff0c;在函数中实现功能 def func():print("一个NB的功能")面向对象 calss FOO(object):d…

git提交代码时报错,提不了

问题 今天在换了新电脑&#xff0c;提交代码时报错 ✖ eslint --fix found some errors. Please fix them and try committing again. ✖ 21 problems (20 errors, 1 warning) husky > pre-commit hook failed (add --no-verify to bypass) 解决 通过 --no-verify 解决&…

JavaScript - 请你说一说对随机数的理解

难度级别:初级及以上 提问概率:40% 在前端开发中,随机数的应用场景非常多,而且也是一个常见的考点。例如网页登录的验证码,看似只有4个随机数字加字母的组合,其实这也是随机数的范畴;例如在抽奖算法中,可以用随机数确定用户中奖的概率…

解决电脑无故自动关机或重启的15种方法,总有一种适合你

序言 你的Windows PC是否在没有警告的情况下关闭或重新启动?这背后有几个潜在的原因。例如,它可能是软件/硬件冲突、过热或硬盘驱动器错误。本故障排除指南将概述在Windows 10/11中修复自动关闭和重新启动的多个解决方案。 如果你的计算机经常关闭,则必须在安全模式下启动…

如何实现异地公网环境访问本地部署的支付宝沙箱环境调试支付SDK

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Flutter如何集成到已有iOS工程上

大家好&#xff0c;我是咕噜铁蛋&#xff0c;今天我将和大家分享一个实用的技术教程——如何将Flutter集成到已有的iOS工程中。Flutter是Google推出的一款开源的移动UI框架&#xff0c;它允许开发者使用Dart语言来开发高性能、美观的原生应用&#xff0c;并支持iOS和Android两大…

DLDP简介

定义 设备链路检测协议DLDP&#xff08;Device Link Detection Protocol&#xff09;用来监控光纤或铜质双绞线&#xff08;例如超五类双绞线&#xff09;的链路状态。如果发现单向链路存在&#xff0c;DLDP协议会根据用户配置&#xff0c;自动关闭或通知用户手工关闭相关接口…

ai绘画软件有哪些?这几款宝藏AI绘图别错过

今天我要和你们分享一些令人兴奋的AI绘画软件。这些软件不仅能够让你的创作过程更加有趣&#xff0c;还能帮助你提升绘画技巧。快来看看吧&#xff01; 首先&#xff0c;我们来介绍一款备受推崇的软件——【爱制作AI】。 爱制作AI是国内专业的AI原创内容写作平台&#xff0c;结…

JavaScript - 你知道Ajax的原理吗?如何封装一个Ajax

难度级别:中高级及以上 提问概率:75% 想要实现Ajax,就需要创建它的核心通信对象XMLHttpRequest,通过核心对象的open方法与服务端建立连接,核心对象的send方法可以将请求所需数据发送给服务端,服务端接收到请求并做出响应,我们通过核心对象…

技术再度取得优势,人工智能兴起推动需求,美芯涨价收割市场,收割中国制造?...

独家首发 ------------- 分析机构指出一季度全球存储芯片涨价了15%左右&#xff0c;而近期三星半导体预测全球存储芯片的价格还将继续上涨&#xff0c;预计二季度至少上涨两成&#xff0c;显示出美系芯片在忍受了一年多的亏损之后再度联手涨价。 2022年中国存储芯片取得了重大进…

2024/4/2—力扣—最小高度树

代码实现&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* buildTree(int *nums, int l, int r) {if (l > r) {return NULL; // 递归出口}struct…

戴维贝拉×实在智能丨RPA助力商家线上线下一体化运营,关键指标可随时查看!

戴维贝拉&#xff08;dave&bella&#xff09;创立于2011年&#xff0c;是杭州日冠服饰有限公司旗下婴幼服饰品牌&#xff0c;至今已立足服装业10余年。2012年&#xff0c;戴维贝拉就已经成为电商销售国内前十的品牌。2021年双十一&#xff0c;戴维贝拉再次以傲人的战绩稳居…

GIS与数字孪生共舞,打造未来智慧场景

作为一名数字孪生资深用户&#xff0c;近日我深刻理解到GIS&#xff08;地理信息系统&#xff09;在构建数字孪生体中的关键作用。 数字孪生技术旨在构建现实世界的虚拟镜像&#xff0c;而GIS则是这一镜像中不可或缺的空间维度框架和导航灯塔。数字孪生的核心是通过数字化方式…

数据结构---绪论

一、绪论&#xff1a; 1.什么是数据&#xff1f; 数据是信息的载体&#xff0c;是描述客观事物属性的数&#xff0c;字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 数据元素--描述一个个体 数据元素&#xff0c;数据项&am…

开源AI程序员SWE-Agent的实现方法

1 引子 前几天&#xff0c;AI 编程机器人 Devin 引起了热议。传言称&#xff1a;程序员的饭碗就要丢了。这两天&#xff0c;一个类似功能的产品 SWE-Agent 开源&#xff0c;在 SWE-Bench 上实现了与 Devin 类似的效果。下面让我们来看看 AI 程序员的具体实现方法。 2 信息 地…

Redis(字典hash表)

字典也可以称为Map、关联数组、映射、符号表。字典表在C语言中没有实现&#xff0c;所以Redis知己实现了字典。 在字典中一个key对应一个value。key是唯一的。这些关联的键和值称为键值对。 ​ 字典的应用非常广泛&#xff0c;Redis数据库的底层实现就是字典&#xff0c;对数据…

vue+springboot多角色登录

①前端编写 将Homeview修改为manager Manager&#xff1a; <template><div><el-container><!-- 侧边栏 --><el-aside :width"asideWidth" style"min-height: 100vh; background-color: #001529"><div style"h…

程序汪10万接的垃圾回收小程序,开发2个月

本项目来自程序汪背后的私活小团队&#xff0c;开发了一个垃圾回收小程序里面涉及物联网&#xff0c;给粉丝分享一下解决方案&#xff0c;希望给想接私活的朋友一些经验参考 程序汪10万接的垃圾回收小程序&#xff0c;开发2个月 视频版本 在 B站【我是程序汪】 目录 一、项目构…

怎么用3D渲染效果图?

3D渲染效果图是一种通过计算机软件生成的三维图像&#xff0c;它模拟了物体在真实世界中的外观和感觉。这种图像通常用于展示建筑设计、室内设计、产品设计等项目的最终效果。通过3D渲染效果图&#xff0c;我们可以更直观地展示和展示我们的创意和想法。那么怎么用3D渲染效果图…

【javaWeb 原理篇】底层实现原理(快速学习配置原理,Bean管理)

Spring底层 配置优先级Bean管理获取beanBean的作用域第三方Bean SpringBoot原理起步依赖自动配置自动配置的原理自定义starter 配置优先级 Spring中的配置文件如果配置了相同的内容则根据配置优先级进行配置: application.properties>application.yml>application.yaml …