Определенные динамически связанные вызовы segfaulting в MIPS - PullRequest
0 голосов
/ 16 сентября 2018

Итак, я пытался изучить MIPS в течение последних нескольких часов, и я столкнулся с проблемой, которая, как мне кажется, связана с моим непониманием того, как MIPS выполняет динамически связанные вызовы (в сочетании с в значительной степени недокументированным псевдосигналом GAS).ops).

Насколько я понимаю, в настоящее время это так: .cpload $t9 просто сообщает ассемблеру, что вы хотите получить адрес глобального указателя (где все инструкции jal для динамически связанных функций будут по существуjalr $t9) и .cprestore *offset* просто говорят ассемблеру хранить значение $gp в *offset*($sp), чтобы оно не перекрывалось при вызовах динамически связанных функций.

Я былИмея хоть какой-то успех в выполнении вызовов функций libc друг за другом, я, в конечном счете, продолжаю сталкиваться с segfaults, которые, я считаю, связаны с какой-то формой сбоев, о которых я не знаю.

Код вВопрос заключается в следующем:

.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.С tty отчётами qemu:

[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 s (или другие инструкции, которые не влияют на предыдущую инструкцию) неявно.

Итак, я не понимаю, почему это происходит.Я не верю, что это проблема исключительно с printf, так как я могу назвать это нормально с немедленными запросами, и у меня были подобные проблемы с загрузкой сохраненных в стеке значений перед вызовами других функций libc (таких как free).

Я был бы очень признателен, если бы кто-то мог обнаружить проблему и / или дать представление о том, как следует выполнять динамические вызовы идиоматическим образом (я могу найти мало информации в Интернете, и objdump опускает многоподробно - например, символы).

Я хотел бы уточнить:

1) Как часто следует использовать .cprestore?Означает ли это, что каждый динамический вызов извлекает сохраненное значение (до тех пор, пока конфигурация стека не изменяется)?Если вы расширяете стек, а затем делаете динамический вызов, вам нужно будет использовать .cprestore, чтобы сообщить ассемблеру, что $gp находится в другом относительном месте, чем $sp.

2)быть явным при выполнении инструкций, которые могут быть выполнены со слотами задержки ветвления?(как в: я должен явно писать nop после определенных инструкций или ассемблер обработает это для меня?)

3) Я читал, что стек MIPS должен быть двойным словом (8 байт)выровнены?Это правда?Я определенно сталкивался с проблемами с другими, выровненными по словам, размерами стека (и даже смещениями хранилища).

Я знаю, что это довольно длинный, запутанный вопрос, который я задал, ноЯ действительно в растерянности.Спасибо за чтение, любая помощь будет высоко ценится.

...