【问题标题】:Disassembly of object file with offset from instruction pointer从指令指针偏移的目标文件的反汇编
【发布时间】:2018-11-26 12:34:39
【问题描述】:

this book 中提供了以下示例。

有两个.c 文件和一个.h 文件。

main.c

#include "function.h"
extern int nCompletionStatus;
int main(int argc, char* argv[])
{
    float x = 1.0;
    float y = 5.0;
    float z;

    z = add_and_multiply(x,y);
    nCompletionStatus = 1;
    return 0;
}

函数.h

#pragma once

#define FIRST_OPTION
#ifdef FIRST_OPTION
    #define MULTIPLIER (3.0)
#else
    #define MULTIPLIER (2.0)
#endif

float add_and_multiply(float x, float y);

函数.c

#include "function.h"
int nCompletionStatus = 0;

float add(float x, float y)
{
    float z = x + y;
    return z;
}

float add_and_multiply(float x, float y)
{
    float z = add(x,y);
    z *= MULTIPLIER;
    return z;
} 

要生成.o 文件,提供以下命令:

gcc -c function.c main.c

那么,要查看main.o的内容,我们有:

objdump -D -M intel main.o.

作者在他的书中列出了objdump 输出的(sn-ps of)内容,因此重点关注main.oadd_and_multiply(,)externed nCompletionStatus 中未解决的外部引用:

27: 89 04 24             mov    DWORD PTR [esp],eax
2a: e8 fc ff ff ff       call   2b <main + 0x2b>    ;//highlighted (a) by author
2f: d9 5c 24 1c          fstp   DWORD PTR [esp+0x1c]
33: c7 05 00 00 00 00 01 mov    DWORD PTR ds:0x0,0x1 ;//highlighted (b) by author

在我的机器上,这与作者制作的略有不同,我得到objdump 的以下输出(仅相关部分):

3c: e8 00 00 00 00       call   41 <main+0x41>;//Equivalent to highlight (a) of author?
41: 66 0f 7e c0          movd   eax,xmm0
45: 89 45 fc             mov    DWORD PTR [rbp-0x4],eax
48: c7 05 00 00 00 00 01 mov    DWORD PTR [rip+0x0],0x1        # 52 <main+0x52>;//equivalent to highlight (b) of author?

我的问题在上面用 cmets 表示。也就是我机器上的输出(运行gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10))和作者报告的效果如何?

特别是,在作者的版本中,在突出显示 (b) 中,ds: 似乎被访问,而在我的版本中,rip 寄存器的一些偏移似乎已经到位。它们如何等效?

【问题讨论】:

    标签: c assembly compilation object-files


    【解决方案1】:

    您所指的书使用 32 位汇编,而您的编译器发出 64 位汇编。将-m32 传递给gcc 以将您的C 代码编译为32 位机器代码。还可以考虑使用-d 而不是-D 代替objdump,因为前者只尝试反汇编已知包含机器代码的部分。

    【讨论】:

    • 让我试试。虽然,我不一定试图将我的输出与作者报告的内容相匹配。我的问题更多地与 32 位中的突出显示 (b) 似乎是指数据段 (?) 有关,而在 64 位中,它是指令指针的一些偏移量。
    • @Tryer 每个内存访问都与某个段相关。但这是一条红鲱鱼,因为现代操作系统中不使用分段。程序集喜欢包含绝对内存访问的段的名称,但我真的不知道为什么。在 64 位模式中,存在一种新的rip 相对寻址模式,它被用来代替绝对寻址。它归结为同一件事,只是您的代码现在与位置无关。
    • IIUC,在作者的版本中,代码段(highlight(b))是指目标文件中其他地方的数据段。在我的版本中,指令指针的偏移量似乎为 0。现在,当指令指针位于第 48 行时,是否会到达执行此行?然后,偏移量 0 再次指向代码段本身的第 48 行。所以,让我感到困惑的是,在我的版本(64 位)中,如何对数据段进行任何引用。
    • 偏移量为 0,因为您正在检查一个尚未填写变量和函数位置的目标文件。如果您检查一个可执行程序(即在链接之后),那么链接器已经填写了所有重定位并且这些数字是有意义的。 ELF 二进制文件的部分和段与 x86 段不对应。不要混淆这两者,并试图忘记后者存在一段时间。
    • @Tryer 实际上,在普通的 x86 操作系统上,所有四个基本的 x86 段寄存器都设置为引用相同的段基,因此在引用时使用哪个段并不重要记忆中的一个数据。也就是说,段寄存器 fs 和 gs 有时用于特殊目的,即用于线程本地存储。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 2014-01-22
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多