效能优化实践:C/C++单元测试万能插桩工具

本文介绍了如何通过修改机器指令实现C/C++单元测试中的插桩,不受语法和编译器限制,能对全局函数、成员函数、静态成员函数、虚函数及系统库函数进行插桩,实现全面的测试覆盖。文中提供了不同类型的插桩示例,并讨论了使用限制和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

研发效能是一个涉及面很广的话题,它涵盖了软件交付的整个生命周期,涉及产品、架构、开发、测试、运维,每个环节都可能影响顺畅、高质量地持续有效交付。在腾讯安全平台部实际研发与测试工作中我们发现,代码插桩隔离是单元测试工作中的一个强需求,然而业界现有 C/C++插桩工具由于使用上的局限性,运行效率和体验仍有很大改善空间。本文介绍了团队基于研效优化实践而自研的动态插桩工具,旨在实现单元测试的轻量化运行,提高代码覆盖率,从而助力研发团队的效能提升。

问题&思路

目前存在的 C/C++插桩工具,基本上都有各种使用上的局限,比如流行的 gmock,只能对 C++的虚函数进行插桩替换,针对非虚函数,则需要先对被测代码进行改造;同时对于系统接口,C 风格的第三方库代码,也无能为力。

如果可以绕开编译器,直接从底层入手,比如做机器指令修改,则可以不受语法及编译器的束缚,直接达到目的,这样在使用中就 几乎不受限制

原理

C/C++语言编译后的可执行体,其实就是一个个的函数实现,每个函数的开头就是它的入口。一个函数 A 调用另一个函数 B,就是代码在执行过程中,控制流从函数 A 的某处跳到了函数 B 的开头,所以如果想用一个新的函数 C 取代函数 B,可以在函数 B 的开头用机器码的形式写入如下等价逻辑:

MOVQ ADDRESS_OF_C %RAX //将函数C的地址放到寄存器RAX
JMPQ *RAX           //无条件跳转到RAX所指向的位置

这样,当控制流从函数 A 进入函数 B 的开始位置的时候,即会执行上述代码,从而直接跳转到 C 的开头处。其最终效果,是所有对函数 B 的调用,都如同直接调用了函数 C。

基于上述原理,被插桩的代码包括第三方库,如 MySql、其他同事未完成的模块、甚至是操作系统的 API 接口,如 read、select 等

同时,桩函数不仅可以模拟原函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值