更换功能单元 [英] Replace function units

查看:242
本文介绍了更换功能单元的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为大型Delphi代码库编写单元测试基础设施。我想将SysUtils.FileExists中的纯函数的调用链接到MockSysUtils.FileExists。



创建具有相同接口的SysUtils单元不被欣赏通过编译器。



我在想的是在运行时挂钩我的模拟功能。这是可能现在吗?



其他任何建议?



请问,



Peter

解决方案

运行时更换功能很困难,但通常在技术上是可能的。 所有您需要做的是:




  • 拿出有问题的功能的地址

  • 拆卸前5个字节(以检查RET指令 - 非常小的例程可能会与另一个例程相抵触,阻止您更换)

  • 更改其页面保护(使用 VirtualProtect )可写入

  • 使用JMP rel32指令重写前5个字节(即E9

  • 实现您的版本功能正常,确保它具有与您嘲笑的功能相同的参数和调用约定



更简单的方法要链接到不同版本的SysUtils.pas。这将需要您重新编译依赖于SysUtils.pas的RTL和VCL中的所有单元,但它可能比上述功能文件格式更容易。



最简单的方法是语言级别,您不必直接依赖于SysUtils(因此可以在较高级别切换),或者您修改使用声明有条件地引用不同的单位。


I am writing a unit test infrastructure for a large Delphi code base. I would like to link calls to pure functions in SysUtils.FileExists for example to a "MockSysUtils.FileExists" instead.

Creating a SysUtils unit with the same interface is not appreciated by the compiler.

What I am thinking of is to hook in my mock function at runtime. Is this possible nowadays?

Any other suggestions?

Regards,

Peter

解决方案

Replacing a function at runtime is difficult but usually technically possible. "All" you need to do is:

  • take the address of the function in question
  • disassemble the first 5 bytes or so (to check for a RET instruction - very small routines may abut another routine, preventing you from replacing it)
  • change its page protection (with VirtualProtect) to be writable
  • rewrite the first 5 bytes with a JMP rel32 instruction (i.e. E9 <offset-to-your-func>)
  • implement your version function as normal, making sure it has the same arguments and calling convention as the function you are mocking

An easier approach would be to link against a different version of SysUtils.pas. That will require you to also recompile all the units in the RTL and VCL that depend on SysUtils.pas, but it is likely quite a bit easier than the function intrumentation approach described above.

The easiest approach is the language-level one, where either you don't directly rely on SysUtils at all (and so can switch at a higher level), or you modify the uses declaration to conditionally refer to a different unit.

这篇关于更换功能单元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆