代码之家  ›  专栏  ›  技术社区  ›  Jeremy Friesner

有没有办法列出在两个可执行二进制文件之间更改了哪些函数?

  •  -2
  • Jeremy Friesner  · 技术社区  · 7 年前

    TLDR/摘要 有没有一种方法,给定两个可执行文件(都是从C++编译的,带有调试信息,以及从相同的或几乎相同的源代码)列出的只是一个不同的函数,相对于另一个?

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

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

    第一个选择(“从头开始”)是安全的,但昂贵的,并导致重大的进度延误。第二种选择(“像以前一样继续测试,但是使用新的构建”)更快,但是如果程序中已经使用旧的构建进行了测试的部分出现任何新引入的错误,则有向用户进行回归的风险。

    所以当Sqa问我关于这个决定的建议时,我现在在两个构建日期之间做一个“Svn DIFF”来精确地检查两个构建之间的C++代码之间的变化,并用它来估计没有进行完全重新测试的风险级别。但是,我们的一些SQA人员不像我那样信任我们的构建过程,他们不愿意假设仅仅因为源代码几乎没有更改,这意味着可执行文件几乎没有更改。(也就是说,他们说,“但是如果在我们不知道的构建机器上更改了某些设置,会怎么样?”我只能呼吁他们相信没有人会做这种事)

    因此,为了缓解SQA的担忧(以及我自己的担忧),如果我可以采用新的候选发布版本并对其执行“diff”(与旧的/部分测试的候选发布版本的可执行文件相比),并查看哪些功能不同,哪些功能保持不变,这将非常有用。(显然,我可以使用二进制diff或md5校验和来完成这项工作,但这些校验和只会告诉我这两个可执行文件是不同的;它们不会告诉我哪些函数是不同的,这是我真正想知道的——例如,在我修复了about框中的一个拼写错误之后,可执行文件中的核心业务逻辑函数并没有相对于之前测试过)

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

    1 回复  |  直到 7 年前
        1
  •  0
  •   Jeremy Friesner    7 年前

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

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

    然后,它打印出一个列表,其中的函数与另一个可执行文件中的对应函数不相同,并写出一个包含实际差异的文件,以防用户希望看到 怎样 功能不同。

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

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

    推荐文章