ARM ELF中具有非连续地址空间的子例程

ARM ELF中具有非连续地址空间的子例程,arm,elf,disassembly,Arm,Elf,Disassembly,在反汇编中,需要识别每个子例程的开始和结束地址。x86中出现的一个问题(不是100%确定)是子例程的地址空间可能是非连续的。到目前为止,我在ARM反汇编中找不到这样的子程序 ARM ELF中的子例程通常占用连续的地址空间吗 更新: 我对二进制文件的静态分析感兴趣。对于规模的任何静态分析,在保持精度的同时,应基于合理的假设。对于一个由一组基本块BBH1组成的函数,如果它跳到另一组基本块BBH2,它远离内存,我们可以悲观地考虑BBS2作为我们的目的的另一个函数。但是,如果我们能够将BB_2识别为一组

在反汇编中,需要识别每个子例程的开始和结束地址。x86中出现的一个问题(不是100%确定)是子例程的地址空间可能是非连续的。到目前为止,我在ARM反汇编中找不到这样的子程序

ARM ELF中的子例程通常占用连续的地址空间吗

更新

我对二进制文件的静态分析感兴趣。对于规模的任何静态分析,在保持精度的同时,应基于合理的假设。对于一个由一组基本块BBH1组成的函数,如果它跳到另一组基本块BBH2,它远离内存,我们可以悲观地考虑BBS2作为我们的目的的另一个函数。但是,如果我们能够将BB_2识别为一组遵循常见习惯用法的基本块,例如清理。这可能会有所不同。因此,如果将这些习惯用法与它们在实践中的使用方式结合起来加以识别,那将非常有用。

我不知道有任何“这样的规则”,但您应该在反汇编的上下文中真正开始定义您所称的子例程的开始和结束。 正如@已经说过的那样,有这样的事情:尾随/清理,由编译器和/或链接器生成——你认为它们是子程序的一部分吗?这里没有简单的答案。 在一个ARM平台上,使用“贴面”(拼写,懒惰检查)来确保正确的臂/拇指交互是非常普遍的,你会认为它们是子程序的一部分吗?他们在记忆中肯定相隔数英里

UPD.

ARM ELF中的子例程通常占用连续的地址空间吗

根据我的经验(使用gcc工具链),简单的答案是:
是-如果gcc优化已关闭。
但是,如果启用了优化,则根本无法依赖此功能。
一个现代化的优化编译器/链接器可以做任何它认为合适的“肮脏”把戏。。确实如此。
在问题的上下文中,没有什么可以阻止它在两个(或更多)函数中检测代码的公共部分,并重新组织代码以跳转到该部分,从而避免代码重复


希望这能有所帮助。

与其说是ISA的问题,不如说是什么生成了代码。如果您愿意,您可以在几乎任何ISA上,在手写汇编中执行各种疯狂的操作。如果一个非常聪明的优化编译器可以为x86生成一些棘手的东西(例如,多个函数都分支到一些常见的清理/尾声代码),那么它可以为它支持的几乎任何其他ISA生成这些东西。@不像IDA Pro支持函数“chunks”,这意味着至少在x86(_64)中确认了这个问题。我知道内存中函数的布局与处理器无关。因此,原则上,编译器可以自由地做任何他们想做的事情。然而,ARM可能有一些规则来阻止(甚至禁止)这种做法。如果您知道任何这样的规则,请在回答中提供,我很乐意接受。GCC可以将函数分为热段和冷段,使所有热段保持在一起。它还可以进行部分内联,其中只内联函数的一部分。这可能最终会创建同一函数的两个不同版本。同样,在这个类中,没有任何ARM、X86、MIPS或大多数其他ISA会限制您,我认为X86是最有限制的。这都是关于编译器的,而不是ISA。看看一个版本一个编译器如何在一台主机上工作是很有趣的,但你不能得出任何结论。即使你现在检查了所有可用的编译器,你的研究也可能会很快失效。你的分析工具必须自己定义函数,而不必与高级语言源定义的函数相关联。你只需要从你想要找到的不同的编译过的二进制文件开始你的分析,然后随着每一个新问题的出现,打破你的工具,你就适应了。你无法提前做任何事情来阻止这种情况,它将继续发生。完全独立于ISA。我同意“函数”没有简单的定义。一个良好的开端是,“其他人”只能通过函数入口(序言)到达的任何基本块都应视为函数的一部分。然而,如果我们能够确定拥有一个连续的地址空间是“规则”,并从那里开始量化该规则的例外情况,这将有所帮助。到目前为止,贴面和清理尾声都是明显的例外。@Oxcode我认为如果你陈述了问题的最终目的,对每个人来说都会容易得多。我有一种感觉,如果你这样做,我(和其他人)将能够避开无关的理论概念,更快地切入正题到目前为止,您提到了反汇编、ARM、ELF和“子程序”/“函数”,您还提到了一些x86非连续性问题,我无法对此进行评论,因为我从未在低级别上使用过x86。这个话题仍然太宽泛。。也就是说,如果我们处于“组装”级别,那么根本就没有“功能”(ARM)这样的东西,所以其余的都没有意义:)