【问题标题】:Is there a way to list which functions have changed between two executable binaries?有没有办法列出两个可执行二进制文件之间哪些函数发生了变化?
【发布时间】:2019-01-26 03:13:40
【问题描述】:

TLDR/摘要:有没有办法,给定两个可执行文件(都从 C++ 编译,存在调试信息,并且来自相同或几乎相同源代码)来仅列出与另一个不同的功能?

背景/动机:在每个 sprint 结束时,我们的工程团队都会将“英雄”构建交给我们的 QA 团队作为候选发布。然后,SQA 团队会花费几个人周的时间来测试候选发布版本,以确保其正常工作。 (他们已经尽可能多地自动化了测试,但是有些部分不容易自动化,因此人工测试/验证很费力)。不可避免地,他们会在候选发布版本中遇到一个或多个错误,此时会提交错误报告,工程部门会修复错误并生成新的候选发布版本。

此时,SQA 团队必须做出决定:他们是从头开始重新开始所有测试,还是假设新的候选发布版本与之前的发布候选版本相同,除了请求的修复 - 即程序的其他部分没有引入回归?

第一个选择(“从头开始”)更安全,但代价高昂,并且会导致严重的进度延误。第二种选择(“像以前一样继续测试,但使用新版本”)更快,但是如果在已经使用旧版本。

因此,当 SQA 向我询问有关此决定的建议时,我目前在两个构建日期之间执行“svn diff”,以准确检查两个构建之间的 C++ 代码更改,并使用它来估计风险级别不进行全面复试。然而,我们的一些 SQA 人员并不像我一样信任我们的构建过程,并且他们不愿意仅仅因为源代码几乎没有改变就意味着可执行文件几乎没有改变。 (即他们说“但是如果在构建机器上更改了我们不知道的某些设置怎么办?”;对此我只能诉诸他们对人类的信念,即没有人会做这样的事情)

因此,为了减轻 SQA 的担忧(以及我自己的担忧),如果我可以采用新的发布候选可执行文件并对其进行“差异”(与旧的/部分测试的发布候选可执行文件相比),这将非常有用) 并准确查看哪些功能不同,哪些功能保持不变。 (显然我可以使用 binary-diff 或 MD5 校验和来执行此操作,但这些只会告诉我两个可执行文件不同;他们不会告诉我哪些功能不同,这是我真正想知道的——例如,在我修复了 About-box 中的错字之后,可执行文件中的 core-business-logic 功能相对于之前的测试没有改变)

我意识到这个问题的答案可能是特定于操作系统的;但是我们在 Linux、MacOS/X 和 Linux 下编译,因此欢迎对这三个操作系统中的任何一个提供任何见解。

【问题讨论】:

  • 查看新旧差异的方法是通过源代码的差异。听起来您需要花一些时间来教育您的 SQA 员工。可执行代码的差异只会显示二进制差异;无法查看更改了哪些功能。链接器可以通过许多不同的方式重新排列二进制内容(例如,增量构建将使用一些填充来允许发生较小的更改而无需重新构建整个二进制内容)。
  • 像 svn 这样的工具似乎有助于跟踪更改。
  • 我的意思是二进制可执行文件的差异不会向您显示任何有用的信息。例如,您可以使用链接器的映射文件来查看地址的大小和变化,但它所显示的内容远少于源代码的 svn 差异,而且它所显示的内容对 SQA 没有任何用处不了解源代码更改及其影响的员工。我想你在这里叫错树了。
  • 主要是我想要做的是验证事情没有改变。就在源代码级别进行操作而言,我 90% 同意这一点,这是我的惯常做法——但是当 SQA 质疑源代码 -> 可执行转换的可靠性时,我希望有一个更好的反驳论点而不是“你只需要相信编译器是一致的”,因为即使对我来说,这也是一种信仰的飞跃。
  • @smac89 我没有被“告知”做任何事情;这是我自己要解决的问题——即,这是我检查我对源代码的更改是否仅导致对我预期的二进制文件的更改,或者是否有其他(不相关的,可能不需要的)更改的一种方式也悄悄进来了。目前我只能假设新的可执行文件只包含我想要的更改,仅此而已;如果我成功了,我将能够验证事实是否如此。 (至于一种新的测试方法,那会很棒,但有时这是不可能的)

标签: c++ diff executable


【解决方案1】:

这个问题的答案似乎是不,不存在任何此类工具(至少,不存在于反恶意软件社区之外)。

因此,为了看看它是否可以完成,我编写了一个简单的概念验证executable_diff 实用程序,它或多或少地完成了我正在寻找的工作。它在 Linux 和 MacOS/X 下运行,当被调用时,它通过反汇编程序(MacOS/X 下的“otool”,Linux 下的“objdump”)运行两个可执行文件中的每一个,然后扫描反汇编文本以查看文本中的哪些函数-segment(或 .rodata 段中的字符串)在一个可执行文件和下一个可执行文件之间是不同的。

然后它会打印出一个列表,其中列出了哪些函数与其他可执行文件中的对应函数不同,并且还会写出一个包含实际差异的文件,以防用户希望查看如何功能不同。

实现该程序的主要复杂因素是,当您更改程序中一个函数的大小时,该更改会波及程序的其余部分,因为文本段中稍后出现的所有函数的地址都发生了变化也是。因此,该程序还包含过滤误报的逻辑(通过在执行差异之前将程序集中的绝对地址转换回其相应的函数名称)

正如该问题的评论者所指出的,差异可执行文件不能替代使用版本控制并跟踪与每个构建的可执行文件关联的存储库修订号,因此您可以在源代码级别进行差异.我写这个只是为了看看它是否可以完成,并且作为一个学习练习来教自己更多关于源代码的更改如何反映在生成的二进制文件中。 executable_diff 仅应被视为粗略的启发式算法,因为它无疑会在某些情况下产生误报,并错误地忽略其他情况下有意义的变化。

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    相关资源
    最近更新 更多