所以我试图使用objdump实用程序从程序集构建一个控制流图,我遇到了一个问题。基本上,每当分支发生且目标地址相对时,我不知道如何知道下一个基本块的起始位置。我不确定我是否清楚,所以我会添加一个例子。假设我的程序正在通过objdump输出,并记录了第一个基本块的起始地址。然后它命中一个跳转命令,该命令使用相对寻址指向要跳转到的正确地址。我知道我的第一个基本块的结束就在那里,但是如何在下一个基本块的开头找到正确的地址呢?非常感谢任何人都可以提供的任何指导,我最多只是x86新手,过去一周我一直在反对这一点。
答案 0 :(得分:4)
假设我理解这个问题,也许这会让你开始。相对跳跃是基于pc的。
d: eb 04 jmp 13
0xEB是基于8位立即数的相对跳转的操作码。指令的地址在objdump输出中,在这种情况下为d或0xD。它是一个双字节指令(x86是可变长度)。它在输出中告诉你目标地址是什么,在本例中是jmp 13.所以在objdump输出中查找以13开头的冒号并且冒号是下一个代码块的开头。
了解如何计算该地址。当pc开始获取指令时,它处于0xD,需要两个字节,因此当它准备执行该指令时,pc处于0xD + 2 = 0xF。偏移量为0x4,因此目标地址为0xF + 0x4 = 0x13。
20: 75 ed jne f
同样适用于倒退。 pc加上字节数= 0x20 + 2 = 0x22。 0xED是带符号的数字,是负数,所以符号扩展0xED到0xFFFFFFF ... FFFFED,无论你的地址寄存器是多大。添加0x22 + 0xFFFFFF ... FFFED,你得到目标地址0x0F。您也可以使用0xED,反转并添加1来否定它。 ~0xED = 0x12,0x12 + 1 = 0x13。所以0xED意味着减去0x13。 0x22-0x13 =为0x0F。
以下是更多内容,在每种情况下,它都会为您提供目标地址,您可以在objdump输出中查找。
了解它如何计算该值。同样的故事,从0x400A81的操作码开始,在这种情况下,可变长度指令需要6个字节。因此,当您准备好执行时,pc处于0x400A81 + 6 = 0x400A87。偏移量为0x107,因此如果满足条件,则目标地址为0x400A87 + 0x107 = 0x400B8E。
请注意,这些是从较大的程序中获取的,而不是顺序代码,只是一组孤立的示例。
400a81: 0f 8f 07 01 00 00 jg 400b8e 400a8f: 0f 8f e6 00 00 00 jg 400b7b 400a9d: 0f 8f c5 00 00 00 jg 400b68 400aab: 0f 8f a4 00 00 00 jg 400b55 400ab9: 0f 8f 83 00 00 00 jg 400b42 401d76: 0f 8f 31 01 00 00 jg 401ead