【问题标题】:How to find the basic block given an instruction location in that basic block?给定基本块中的指令位置,如何找到基本块?
【发布时间】:2014-09-27 04:29:42
【问题描述】:

假设我有一个指令位置。我想找到包含该指令的基本块。让我们将“基本块”定义为包含所需指令的基本块的入口点的指令位置。假设我禁用了任何形式的地址空间随机化,因此只要程序执行,所有程序部分和库都会加载到虚拟地址空间中的相同位置。我该怎么做呢?

【问题讨论】:

  • 这似乎是特定于平台的。例如,根据您使用的是 Windows 还是 Posix,答案会有所不同。另外,不清楚虚拟地址空间是什么意思。事实上,整个问题都是假设性的。
  • 您的意思是 « 包含此说明的部分 » ?
  • 要找到“包含该指令的基本块”,您需要向后扫描(该指令可能不在块的开头)。向后扫描几乎是不可能的;它不是“特定于平台”的,而是特定于 CPU 的。即使使用带有“简单”汇编程序的 CPU——ARM 常规执行空间中的所有操作码都是 4 个字节长——你也不能说你是否正在返回数据区域。如果不反汇编整个代码,您将无法知道代码块从哪里开始。

标签: c assembly compiler-construction


【解决方案1】:

这是一个非常困难的问题。实际上,您甚至无法希望知道汇编级别的一般情况的基本块在哪里。

问题在于汇编是一种基于跳转的语言,根据定义,基本块是一系列指令,其中没有跳转。

即使您执行了 99% 的程序,您也永远无法知道最后一条指令是否不会落在您认为是基本块的中间。当然,我说的只是一个执行,但是对于任何执行都应该考虑这一点。

因此,找到二进制程序的 CFG(以及它的基本块)与停止问题一样困难(参见图灵对角参数)。

您也许应该尝试提供有关您真正需要的更多详细信息,因为正如您所说,一般问题根本不可能。

【讨论】:

  • 我想你不知道基本块的定义。 BB 从跳转目标开始,然后继续到下一个跳转目标之前的指令或跳转指令。
  • 这绝对不是我的定义,也不是人们在静态分析中使用的定义...您可能会发现阅读this definition(维基百科)很有用,它指出没有跳转进入块之间基本块的开始,然后是基本块的结束。
【解决方案2】:

您可以在限制性假设下做到这一点。

首先,在任何一般意义上,代码都不能自我修改。这将使问题无法确定。

其次,您需要一个完整的跳跃目标列表。当然调试信息将包括这一点。但是如果你没有调试信息,仍然可以通过反汇编,找到所有的分支和跳转指令,并获取它们的直接目标来推断出很多东西。实现switch 的跳转表也很有用。一个困难的案例将是函数指针。好的逆向工程工具可以很好地做到这一点:在对其结构知之甚少的情况下反汇编代码。另一方面,它们也不是完美的:散布的数据和代码总是会相互混淆。

第三,您需要一份程序中所有跳转/分支指令地址的列表。

有了这些清单,您就可以开始了。每个基本块都以跳转目标开始,并运行到下一个目标之前的指令或跳转/分支指令(包括),以先到者为准。接受指令地址并在列表中搜索相关块开始和结束的算法很简单。

实际上,将列表合并为一个并使用二分搜索是最简单的。搜索地址前后的条目定义了它所在的块。

【讨论】:

  • 代码甚至不需要自我修改以使其无法确定...从二进制文件中提取所有路径已经与停止问题有关。
  • @perror 那是错误的。如果您可以反汇编程序并且分支目标是静态的,那么您可以计算基本块的流程图。 “与停机问题有关”不是不可判定性证明。
  • 分支并不都是静态的......你应该不时阅读一些汇编程序,它可能会有所帮助。
  • @perror 我已经编写并阅读了数千行汇编程序和编写的编译器。分支指令不会自行移动。您应该阅读基本块和流程图的定义。 Aho Sethi 和 Ullman 编译器设计 是一个很好的起点。
【解决方案3】:

需要做两件事:

  • 您需要保留包含映射的调试信息
  • 优化级别必须足够低才能明确。

简而言之,您需要工具链的支持,如果您实际上想要获得比新变量生效的指令指针更多的信息,而没有关于该变量的任何信息,则更是如此。

【讨论】:

    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    相关资源
    最近更新 更多