通用寄存器的内容包含什么?

时间:2013-03-04 23:09:48

标签: ios objective-c macos cpu-registers

我包含了iOS标签,但是我在Core i7 MacBook Pro(x86-64上)的模拟器中运行,对吧?,所以我认为这并不重要。

我正在调试Flurry的视频广告中的崩溃。我有一个关于Objective-C异常的断点。当断点被击中时,我在objc_msgSend。 callstack包含私有Flurry和iOS方法的混合,没有任何公开,也没有我写过的东西。从register read堆栈帧调用objc_msgSend会输出以下内容:

(lldb) register read
General Purpose Registers:
       eax = 0x1ac082d0
       ebx = 0x009600b5  "spaceWillDismiss:interstitial:"
       ecx = 0x03e2cddb  "makeKeyAndVisible"
       edx = 0x0000003f
       edi = 0x0097c6f3  "removeWindow"
       esi = 0x00781e65  App`-[FlurryAdViewController removeWindow] + 12
       ebp = 0xbfffd608
       esp = 0xbfffd5e8
        ss = 0x00000023
    eflags = 0x00010202  App`-[FeedTableCell setupVisibleCommentAndLike] + 1778 at FeedTableCell.m:424
       eip = 0x049bd09b  libobjc.A.dylib`objc_msgSend + 15
        cs = 0x0000001b
        ds = 0x00000023
        es = 0x00000023
        fs = 0x00000000
        gs = 0x0000000f

我对这个输出有几个问题。

  • 我假设$ ebx包含导致崩溃的选择器,$ edi是最后执行的方法。是这样的吗?
  • $ eip是我崩溃的地方。通常情况如此吗?
  • $ eflags引用一个实例方法,据我所知,该方法与此崩溃无关。那是什么?
  • 我可以从这些寄存器中撬出任何其他信息吗?

1 个答案:

答案 0 :(得分:1)

我无法专门与iOS / Objective-C框架布局进行对话,因此我无法回答有关EBX和EDI的问题。但我可以帮助你了解EIP和EFLAGS,并给你一些关于ESP / EBP和选择器寄存器的一般提示。 (顺便说一下,模拟器正在模拟32位x86环境;你可以说,因为你的寄存器是32位长。)

EIP是instruction pointer寄存器,也称为程序计数器,它包含当前正在执行的机器指令的地址。因此,它将指向程序崩溃的位置,或更一般地说,程序在遇到断点,转储核心等时的位置。

EIP被保存并恢复以实现函数调用(在机器代码级别 - 内联可能导致高级语言调用不执行实际调用)。在内存不安全的语言中,堆栈缓冲区溢出可能会覆盖指令指针的保存值,导致返回指令返回错误的位置。如果你很幸运,被覆盖的值将在下一次内存提取时触发段错误,但EIP的值将是任意的,并且在调试问题时无益。如果您不走运,攻击者会将新EIP指向有用的代码,因此许多环境都会使用"堆栈Cookie"或者"金丝雀"在恢复保存/覆盖的EIP之前检测这些覆盖,在这种情况下,EIP值可能有用。

EFLAGS不是内存地址,可以说不是通用寄存器。 EFLAGS的每个位都是可以通过各种指令设置或测试的标志。最重要的标志是进位,零和符号标志,它们由算术指令设置并用于条件分支。您的调试器将其误解为内存地址并将其显示为最接近的函数,但这实际上与您的崩溃无关。 (+ 1778是赠品:这意味着EFLAGS将1778个字节指向函数,但该函数实际上不太可能长达1778个字节。)

ESP是堆栈指针,EBP(通常)是帧指针(也称为基指针)。这些寄存器绑定了调用堆栈上的当前帧。您的调试器通常可以根据这些指针向您显示堆栈变量和当前调用堆栈的值。如果出现损坏,有时您可以手动检查堆栈以恢复EBP并手动展开调用堆栈。注意,可以在没有帧指针(帧指针省略)的情况下编译代码,释放EBP用于其他用途;这在x86上很常见,因为通用寄存器很少。

SS,CS,DS,ES,FS和GS保留段选择器,在分页之前用于实现segmentation的旧时代。今天,FS和GS通常被操作系统用于进程和线程状态块;它们是唯一进入x86-64的选择器寄存器。选择器寄存器通常对调试没有帮助。