asmloader
asmloader copied to clipboard
64 bit linux unaligned stack crash and printf params repetition.
Hi,
AFAIK problem with xmm registers and doubling printf arguments affects only x86_64 linux (and OSX in extension). Tested with a lot of your code from youtube assembly course, seems to work well on 32/64 bit Windows, Linux nad OSX:
For linux stub i had to extend stub space in asmloader itself 0x400 instead 0x200.
Affects 86_64 linux stub:
; remove args passed via registers from stack to avoid printing
; them twice in case of more than 6 printf arguments
; no easy way to detect exact number of arguments so we have to save the stack
; to rebuild it in case of less then 6 params
mov [rel saved_stack_top], rdi
mov [rel saved_stack_nd], rsi
mov [rel saved_stack_rd], rdx
mov [rel saved_stack_fourth], rcx
mov [rel saved_stack_fifth], r8
mov [rel saved_stack_sixth], r9
add rsp, 48`
Next problem was rax usage for printf float args count:
; When calling printf stub uses rax, so this register is nonzero.
; This causes printf to "see" floating point arguments and starts using SSE.
; At the same time if the stack does not have the proper 16 byte alignment asmloader will crash.
; After first [rbx + 3 * 8] call rax may be nonzero again
; so code like:
;
; [bits 64]
;
; call no_arg_procedure
;
; push 0
; call [rbx + 0 * 8]
;
; no_arg_procedure: ; no_arg_procedure()
;
; call _print
; db "abc", 0xa, 0
; _print:
; call [rbx + 3 * 8]
; add rsp, 8
;
; call _print2
; db "cde", 0xa, 0
; _print2:
; call [rbx + 3 * 8]
; add rsp, 8
; ret
; ;end
;
; will leave stack unaligned and nonzero rax, this will crash, so:
xor rax, rax
call r15`
We also need to restore stack add rsp, 48 can hurt some ret address in case less than 6 arguments passed to printf,:
; restore 6 stack elements
push QWORD [rel saved_stack_sixth]
push QWORD [rel saved_stack_fifth]
push QWORD [rel saved_stack_fourth]
push QWORD [rel saved_stack_rd]
push QWORD [rel saved_stack_nd]
push QWORD [rel saved_stack_top]`
Regards