MIPS 堆栈帧(和“addiu”指令混淆)

发布于 2024-11-26 20:23:11 字数 2107 浏览 2 评论 0原文

我是 MIPS 新手,正在尝试了解函数的反汇编。
(编辑:它动态链接到 /lib/ld-uClib.so.0 并使用一些常用的 libc 函数,所以我假设它是使用 uClibc 工具链用 C 编写的,因此应该具有该调用过程和堆栈帧等.)。

在函数开始时执行

00400824 <practice_crackme>:
  400824:   3c1c0fc0    lui gp,0xfc0        ; ???
  400828:   279c673c    addiu   gp,gp,26428 ; ???
  40082c:   0399e021    addu    gp,gp,t9    ; ???

  400830:   27bd8020    addiu   sp,sp,-32736  ; sp -= 0x7fe0 (-32736=0xffff8020)
  400834:   34038670    li  v1,0x8670
  400838:   afbf7fdc    sw  ra,32732(sp)
  40083c:   afbe7fd8    sw  s8,32728(sp)
  400840:   afb77fd4    sw  s7,32724(sp)
  400844:   afb67fd0    sw  s6,32720(sp)
  400848:   afb57fcc    sw  s5,32716(sp)
  40084c:   afb47fc8    sw  s4,32712(sp)
  400850:   afb37fc4    sw  s3,32708(sp)
  400854:   afb27fc0    sw  s2,32704(sp)
  400858:   afb17fbc    sw  s1,32700(sp)
  40085c:   afb07fb8    sw  s0,32696(sp)
  400860:   03a3e823    subu    sp,sp,v1  ; sp-=0x8670 (local space=0x8670 bytes)
  400864:   afbc0018    sw  gp,24(sp)

然后在函数结束时执行:

  4009e0:   8fbc0018    lw  gp,24(sp)
  4009e4:   34088670    li  t0,0x8670
  4009e8:   03a8e821    addu    sp,sp,t0    ; sp+=0x8670; //remove local space
  4009ec:   8fbf7fdc    lw  ra,32732(sp)
  4009f0:   8fbe7fd8    lw  s8,32728(sp)
  4009f4:   8fb77fd4    lw  s7,32724(sp)
  4009f8:   8fb67fd0    lw  s6,32720(sp)
  4009fc:   8fb57fcc    lw  s5,32716(sp)
  400a00:   8fb47fc8    lw  s4,32712(sp)
  400a04:   8fb37fc4    lw  s3,32708(sp)
  400a08:   8fb27fc0    lw  s2,32704(sp)
  400a0c:   8fb17fbc    lw  s1,32700(sp)
  400a10:   8fb07fb8    lw  s0,32696(sp)
  400a14:   03e00008    jr  ra
  400a18:   27bd7fe0    addiu   sp,sp,32736 ; sp += 0x7fe0

问题#1:
尽管在互联网上搜索了一段时间,我仍然不太明白 gp 应该如何在堆栈框架中使用。

特别是,我读到的文档说调用过程标准是a0-a3用作函数输入,v0-v3用作函数输出,s0-s8在调用中保留,t0-t9在任何调用中都不保留。所以 s0-s8 的压入和弹出是有意义的。 但是为什么要根据 t9 中的值设置 gp!?

问题 #2:
我不明白为什么它移动堆栈指针两次。似乎预留了两次本地空间。

最重要的是,addiu 指令被反汇编为负数,这是没有意义的,因为“u”意味着无符号,但是除非我真正考虑它,否则代码没有意义负数。我通过在 en.wikipedia.org/wiki/MIPS_architecture 上查找来仔细检查操作码。它确实是“addiu”而不是“addi”。我在这里很困惑。

I'm new to MIPS and am trying to understand the disassembly of a function.
(EDIT: it is dynamically linked to /lib/ld-uClib.so.0 and uses some usual libc functions, so I assume it was written in C using the uClibc toolchain, and should therefore have that calling procedure and stack frame, etc.).

At the start of the function it does

00400824 <practice_crackme>:
  400824:   3c1c0fc0    lui gp,0xfc0        ; ???
  400828:   279c673c    addiu   gp,gp,26428 ; ???
  40082c:   0399e021    addu    gp,gp,t9    ; ???

  400830:   27bd8020    addiu   sp,sp,-32736  ; sp -= 0x7fe0 (-32736=0xffff8020)
  400834:   34038670    li  v1,0x8670
  400838:   afbf7fdc    sw  ra,32732(sp)
  40083c:   afbe7fd8    sw  s8,32728(sp)
  400840:   afb77fd4    sw  s7,32724(sp)
  400844:   afb67fd0    sw  s6,32720(sp)
  400848:   afb57fcc    sw  s5,32716(sp)
  40084c:   afb47fc8    sw  s4,32712(sp)
  400850:   afb37fc4    sw  s3,32708(sp)
  400854:   afb27fc0    sw  s2,32704(sp)
  400858:   afb17fbc    sw  s1,32700(sp)
  40085c:   afb07fb8    sw  s0,32696(sp)
  400860:   03a3e823    subu    sp,sp,v1  ; sp-=0x8670 (local space=0x8670 bytes)
  400864:   afbc0018    sw  gp,24(sp)

Then at the end of the function it does:

  4009e0:   8fbc0018    lw  gp,24(sp)
  4009e4:   34088670    li  t0,0x8670
  4009e8:   03a8e821    addu    sp,sp,t0    ; sp+=0x8670; //remove local space
  4009ec:   8fbf7fdc    lw  ra,32732(sp)
  4009f0:   8fbe7fd8    lw  s8,32728(sp)
  4009f4:   8fb77fd4    lw  s7,32724(sp)
  4009f8:   8fb67fd0    lw  s6,32720(sp)
  4009fc:   8fb57fcc    lw  s5,32716(sp)
  400a00:   8fb47fc8    lw  s4,32712(sp)
  400a04:   8fb37fc4    lw  s3,32708(sp)
  400a08:   8fb27fc0    lw  s2,32704(sp)
  400a0c:   8fb17fbc    lw  s1,32700(sp)
  400a10:   8fb07fb8    lw  s0,32696(sp)
  400a14:   03e00008    jr  ra
  400a18:   27bd7fe0    addiu   sp,sp,32736 ; sp += 0x7fe0

Question #1:
Despite searching around for awhile on the internet, I still don't really understand how gp is supposed to be used in the stackframe.

In particular, the documents I read say the call procedure standard is a0-a3 are used as function input, v0-v3 as function output, s0-s8 are preserved across calls, and t0-t9 are not preserved across any call. So the pushing and popping of s0-s8 make sense. But why in the world is it setting gp according to the value in t9!?

Question #2:
I don't understand why it moves the stack pointer twice. It seems to reserve local space twice.

And on top of that, the addiu instruction is being disassembled with a negative number which doesn't make sense since the 'u' means unsigned, however the code doesn't make sense unless I actually consider it a negative number. I double checked the opcode by looking it up at en.wikipedia.org/wiki/MIPS_architecture. And it is indeed "addiu" and not "addi". I'm so confused here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

╰ゝ天使的微笑 2024-12-03 20:23:11

前三个指令用于支持位置无关代码。请参阅 此 linux-mips 页面,了解 MIPS 上 PIC 的精彩解释。 t9 保存函数的地址,每次加载支持 PIC 的库时该地址都会发生变化,并且该值会添加到 gp 中已有的常量中。与 x86 类似:

call __i686.get_pc_thunk.bx
add $0x1b88, %ebx

其中 __i686.get_pc_thunk.bx 使用下一条指令的地址加载 %ebx,随后的 add 将 %ebx 转换为将用于访问全局符号的参考点。

添加:
MIPS 上有符号加法和无符号加法之间的唯一区别是有符号加法可能引发溢出异常,因此使用 ADDIU 来避免这种情况。

多次堆栈调整:这些可能与 MIPS 使用 16 位立即数这一事实有关,因此不能总是在一个 ADDIU 中调整堆栈。

The first three instructions are for supporting Position Independent Code. See this linux-mips page for an excellent explanation of PIC on MIPS. t9 holds the address of the function, which can change every time you load a library supporting PIC, and that value is added to a constant already in gp. Similar to x86's:

call __i686.get_pc_thunk.bx
add $0x1b88, %ebx

Where __i686.get_pc_thunk.bx loads %ebx with the address of the next instruction, and the subsequent add converts %ebx into a point of reference that will be used to access global symbols.

ADDIU:
The only difference between signed and unsigned addition on MIPS is that signed addition can raise an overflow exception, so ADDIU is used instead to avoid that.

Several stack adjustments: These probably relate to the fact that MIPS uses 16-bit immediates, so cannot always adjust the stack in one ADDIU.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文