我正在尝试使用Intel Pin-tool工具对可执行二进制文件进行一些指令分析。
[在分析我的Pin工具中的已执行指令时,我观察到接收到的指令地址(程序计数器)的值范围与使用objdump -d -S <binary>
分析已编译代码的反汇编时所观察到的值范围大不相同。我正在标准Linux /bin/ls
可执行二进制文件上对其进行测试。
根据我的理解,Pin修改了原始二进制文件以放入其自己的“挂钩”,以收集与执行相关的信息,这些信息在我们所需的Pin工具中调用回调进行分析。因此,这自然会导致实际执行的二进制文件与原始二进制文件有所不同。不幸的是,我不了解Pin的其他幕后知识。
我想知道是否有任何方法可以保留原始代码布局,或者在旧的二进制指令地址和新的二进制指令地址之间获得某种对应关系?
现代发行版使用PIE可执行文件,它们是ELF共享对象,可在运行时重新定位。 objdump
仅显示相对于图像库的地址。 What is the -fPIE option for position-independent executables in gcc and ld?和32-bit absolute addresses no longer allowed in x86-64 Linux?
您可以像GDB一样禁用ASLR,因此它总是像0x55555...
一样重定位到same位置,但是仍然与objdump
地址不匹配。
您可能认为可以使用objdump --adjust-vma=offset
重新定位您的反汇编。
或者您可以使用gcc -no-pie -fno-pie -O3
构建非PIE可执行文件,因此objdump将知道每条指令的实际运行时地址。
如果我理解正确,问题在于二进制图像的位置。例如,您的glibc
图像放置在与在Pin
中运行程序时的地址不同的地址。如果是这样,首先,您应该添加image callback,如下所示:
...
VOID callbackFn(IMG img, VOID *v)
{...}
...
int main(int argc, char *argv[])
{
...
IMG_AddInstrumentFunction(callbackFn, 0);
...
}
...
在每个图像加载时间调用回调函数(即callbackFn
)。在回调主体中,可以使用IMG_LowAddress(img)
在运行时获取每个图像的加载地址。还有IMG_Name(img)
和IMG_IsMainExecutable(img)
之类的功能可能会有所帮助。现在,您知道二进制映像的起始地址,即B
。
您想在运行时在图像中找到函数foo()
的地址。假设objdump
表示它位于二进制映像开头的地址A
。为了找到foo()
的运行时地址,只需将A
添加到B
。换句话说,foo()
在运行时位于A + B
。
P.S .:解析图片名称时,请注意符号链接。您可以使用this function解决问题。