Compiler construction 给定一个指令地址,可以确定包含它的函数的起始地址吗?

Compiler construction 给定一个指令地址,可以确定包含它的函数的起始地址吗?,compiler-construction,x86,reverse-engineering,decompiling,disassembly,Compiler Construction,X86,Reverse Engineering,Decompiling,Disassembly,我在当前的项目中遇到了这个问题,需要在二进制级别对代码进行推理 我认为我们可以通过查看调用指令的操作数来确定程序中所有函数的起始位置。在我们有了这个列表之后,我们可以通过简单地向后搜索直到找到起始地址来确定哪个函数包含一个地址吗?IE包含指令的函数的起始地址是否是小于指令地址的最大函数地址 如果上述方法不正确,是否有其他方法查找包含指令的函数的起始地址 编辑: 补充了对问题的澄清 编辑2: 我的方法可能是错误的。编译器不能保证将函数体放在机器代码的连续区域中。不,汇编代码可以做各种各样的奇怪的事

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

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

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

编辑: 补充了对问题的澄清

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

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

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

通常您无法确定。您的实际情况将随函数二进制代码的构造方式而变化;对于某些编译器,rscheme可能会起作用。但总的来说,你不能相信表面上是指令,实际上是指令。如果你不能指望这一点,你就不可能“向后”追踪到函数的开始。调试器可以做到这一点。调试信息应该包括每个函数的起始地址,这样才有用。因此,您可以从每个函数的起始地址开始,然后继续构建每个函数可能执行的指令列表。然后,给定一条特定指令的地址,您可以确定哪些函数可以执行该指令。使用函数甚至不需要汇编语言。它可能只是一个大的意大利面混乱的gotos。你在汇编语言的上下文中是对的。这里的上下文是编译语言的输出。谢谢。最初,我希望能够对任何已编译的二进制文件执行此操作,但似乎我必须限制使用从C编译的二进制文件并使用调试信息。