【问题标题】:Given an instruction address, can the starting address of the function enclosing it be determined?给定一个指令地址,能否确定包含它的函数的起始地址?
【发布时间】:2012-06-03 06:40:58
【问题描述】:

我在当前的项目中遇到了这个问题,这需要在二进制级别对代码进行推理。

我认为我们可以通过查看 CALL 指令的操作数来确定程序中所有函数的起始位置。有了这个列表后,我们是否可以通过简单地向后搜索直到找到起始地址来确定哪个函数包含一个地址? IE 是指包含指令的函数的起始地址 小于指令地址的最大函数地址?

如果上述方法不正确,是否有其他方法可以找到包含指令的函数的起始地址?

编辑: 添加了对问题的说明。

编辑2: 我的方法可能是错误的。编译器不保证将函数体放置在机器代码的连续区域中。

【问题讨论】:

  • 使用函数甚至不需要汇编语言。这可能只是一堆意大利面条式的 goto。
  • 你在汇编语言的上下文中是对的。它的上下文是编译语言的输出。

标签: compiler-construction x86 reverse-engineering decompiling disassembly


【解决方案1】:

你需要更多地限制你的问题空间。即使只限于“编译语言的输出”,现在的编译器也擅长模糊函数之间的界限。内联意味着一个函数可以包含在另一个函数中。尾调用优化在没有CALL 指令的情况下在两个函数之间转移控制。配置文件引导的优化可以创建不连续的功能。代码流分析和noreturn 提示可能导致代码落入数据。跳转表意味着数据可以在没有CALL 目标的情况下进入代码。唯一可靠的方法是让编译器明确地告诉你指令到函数的映射,比如通过调试信息。你没有说你使用的是什么平台,所以很难提供更具体的信息。

【讨论】:

  • 谢谢。最初,我希望能够对任何已编译的二进制文件执行此操作,但似乎我将不得不限制从 C 编译的二进制文件并使用调试信息。
【解决方案2】:

不,汇编代码可以做各种时髦的事情。一个调用可能会完全跳过另一个函数、向后跳转或进入另一个模块。

【讨论】:

  • 一般你无法确定。您的实际情况会因函数二进制代码的构造方式而异;对于某些编译器,rscheme 可能会起作用。但总的来说,你不能相信看似指令的东西,实际上是指令。如果你不能指望这一点,你就不可能“向后”追踪到函数开始。
  • 调试器能够做到这一点。调试信息应该可以吗?
  • 调试信息应该包括每个函数的起始地址,以便有用。因此,您可以从每个函数的起始地址开始并继续前进,以构建每个函数可能执行的指令列表。然后,给定特定指令的地址,您可以确定哪些函数可能执行该指令。
猜你喜欢
  • 1970-01-01
  • 2011-08-21
  • 2011-12-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
相关资源
最近更新 更多