MIPS中的某些动态链接的呼叫段错误

时间:2018-09-16 14:52:44

标签: mips mips32

因此,在过去的几个小时里,我一直在尝试学习MIPS,但我遇到了一个问题,我认为这是由于我对MIPS如何进行动态链接的调用缺乏了解(与很大程度上未记录的GAS伪操作)。

据我目前的理解是: .cpload $t9只是通知汇编程序您想要获取全局指针的地址(其中所有指向动态链接函数的jal指令实际上都是jalr $t9)和.cprestore *offset*告诉汇编器将$gp的值存储在*offset*($sp)处,以便在动态链接的函数调用期间不会破坏它。

我在接连调用libc函数方面取得了一定的成功,但是,我最终还是遇到了段错误,我认为这些段错误与我不知道的某种形式的破坏有关。 >

有问题的代码如下:

.data

in: .asciz "%d"
out: .asciz "%d\n"

.text
.globl main
main: 
.ent main
.frame $sp, 32, $ra
.set noreorder
.cpload $t9 
.set reorder
    addiu $sp, $sp, -32
    sw $ra, ($sp)
.cprestore 4

    addiu $a1, $sp, 8
    la $a0, in
    jal scanf

    lw $a1, 8($sp)
    la $a0, out
    li $v0, 0
    jal printf

    lw $ra, ($sp)
    li $v0, 0
    jr $ra
    addiu $sp, $sp, 32
.end main

在我为scanf输入值之后,代码出现段错误。使用qemu的tty报告:

[14517.685107] do_page_fault(): sending SIGSEGV to clz for invalid read access from 00000000
[14517.685474] epc = 00000000 in clz[56255000+1000]
[14517.685680] ra  = 56255830 in clz[56255000+1000]

我认为问题可能是由加载和跳转指令后的分支延迟槽引起的,但是我隐约读到.set reorder允许汇编程序用nop(或其他)修补它们。不影响上一条指令的指令)。

所以,我不知道为什么会这样。我不认为这完全是printf的问题,因为我可以用立即数来称呼它,并且在调用其他libc函数(例如{{1} }。

如果有人能发现问题和/或深入了解如何以惯用的方式进行动态呼叫,我将非常感激(我在网络上找不到很少的信息,而free却忽略了很多细节-例如符号)。

我想澄清的是:

1)一个人应该多久使用一次objdump?这样做一次是否意味着每个动态调用都会获取保留的值(只要不更改堆栈配置)?如果扩展堆栈,然后进行动态调用,是否需要使用.cprestore来通知汇编程序.cprestore$gp的相对位置不同。

2)在执行可以使用分支延迟时隙进行的指令时,应该明确一点吗? (例如:我应该在某些指令后明确编写$sp还是由汇编程序代我处理?)

3)我读过MIPS堆栈必须是双字(8字节)对齐的吗?这是真的?我肯定已经遇到了其他与字对齐的堆栈帧大小(甚至存储偏移)的问题。

我知道这是一个漫长而复杂的问题,但我确实感到茫然。感谢您的阅读,我们将不胜感激。

0 个答案:

没有答案