flat assembler
Message board for the users of flat assembler.

Index > Linux > return stack access segfaults

Author
Thread Post new topic Reply to topic
sts-q



Joined: 29 Nov 2018
Posts: 57
sts-q 08 Dec 2018, 13:50
Hello,

On a 64-bit Linux box I get return stack size with a syscall
and, using that value, check for return stack overflow.
This seems to work.

Now, when I try to find out, how many stack items have been used, I get a segfault.

What's wrong with my return stack access?
How can I find out how many stack items have really been used, in other words how deep my programs function calls did nest?

The following are a lot of code snippets. I'm sorry for that.
I hope you get the idea.

Best Regards
Heiko

Code:
;----------------------------------------------------------------------------
; :section:   registers

; aregs
a       equ     rax     ; first function parameter  / return value
b       equ     rbx     ; second function parameter / return value
d       equ     rdx     ; third function parameter

; fregs                 ; function regs
c       equ     rcx     ; counter
si      equ     rsi     ; source index
di      equ     rdi     ; destination index
k       equ     r9      ; key
v       equ     r8      ; value

; at the very beginning of the program
entry $
        ; save command line args and rsp
        mov a, [rsp]                    ; commandline args: count and value
        mov [argc], a
        mov [argv], rsp
        mov a, rsp                      ; save rsp in case of restart_on_error
        sub a, ws
        mov [rs_base], a

        ; rs_minval := rs_base - (8 * return_stack_size) + 16384
        call Syscall.return_stack_size
        shl a, 3
        mov b, a
        mov a, [rs_base]
        sub a, b
        add a, 16384                    ; let some space free just in case...
        mov [rs_minval], a              ; write minval for check_rs_overflow

        
; syscall to get return stack size      
; it returns something about 1M qword stack items 
SYS64_GETRLIMIT = 97
RLIMIT_STACK    =  3
Syscall.return_stack_size:
        mov [buffer], zero
        syscall_4 SYS64_GETRLIMIT, RLIMIT_STACK, buffer, zero
        mov a, [buffer]
        shr a, 3                        ; bytes -> stack-items
        ret

        
; check for return stack overflow
; i'm using this macro and 'think' it works fine
; rs_overflow comes at about 1044000 stack items
macro check_rs_overflow {
        mov a, rsp
        mov b, [rs_minval]              
        cmp a,b
        jle Error.rs_overflow
}


;--------------------------------------------
; not working code: moving up from rs_minval
Stacks.max.rs:
        mov a, [rs_minval]
;       mov v, 99377                    ; segfault always
        mov v, 99378                    ; runs always
    doloop
        mov a, [k]
        add k, ws
        iprint v                        ; print integer v
        spc                             ; print space
        dec v
        until_zero v
    .done:
        lf
        shiftup 0
        exec

;--------------------------------------------
; not working code: moving down from rs_base
Stacks.max.rs:
        mov k, [rs_base]
        mov v, 10000                    ; runs       exact limit is changing
;       mov v, 16005                    ; segfault
    doloop
        mov a, [k]
        sub k, ws
        iprint v
        spc
        dec v
        until_zero v
    .done:
        lf
        shiftup 0
        exec

;--------------------------------------------
macro syscall_4 number, p1, p2, p3
{
        ; rax rdi rsi rdx r10 r8 f9
        save_regs
        mov rdi, p1
        mov rsi, p2
        mov rax, number
        mov rdx, p3
        syscall
        load_regs
}

macro save_regs 
{
        push rbx
        push rcx
        push rdx
        push rsi
        push rdi
        push r8
        push r9
        push r10
        push r11
}

macro load_regs                 ; not:  a  tos sos prog zero  dsp rsp
{
        pop r11                 ; sstos
        pop r10                 ; ssp
        pop r9                  ; k
        pop r8                  ; v
        pop rdi                 ; di
        pop rsi                 ; si
        pop rdx                 ; d
        pop rcx                 ; c
        pop rbx                 ; b
}

    
Post 08 Dec 2018, 13:50
View user's profile Send private message Visit poster's website Reply with quote
redsock



Joined: 09 Oct 2009
Posts: 435
Location: Australia
redsock 08 Dec 2018, 20:17
your code snippets aren't very good at debugging segfaults. It is much better if you can recreate the condition in a working program.

I took a few minutes to write a stackframe min/max/size program that does compile, maybe you can modify mine to see where your error is?

Code:
        format ELF64

section '.text' executable align 16

macro check_stackuse {
        mov     rax, [stack_min]
        cmp     rsp, rax
        cmovb   rax, rsp
        mov     [stack_min], rax
}


public example_func
example_func:
        sub     rsp, 4096
        check_stackuse
        add     rsp, 4096
        ret


align 16
public _start
_start:
        mov     [stack_top], rsp
        mov     [stack_min], rsp
        
        mov     eax, 97         ; syscall_getrlimit
        mov     edi, 3          ; RLIMIT_STACK
        sub     rsp, 16
        mov     rsi, rsp
        syscall
        mov     rdx, [rsp]      ; rlimit.rlim_cur
        mov     rcx, [rsp+8]    ; rlimit.rlim_max

        mov     [stack_size], rdx

        add     rsp, 16

        ; breakpoint so we can inspect our values
        int3
        nop

        ; use some stack
        call    example_func

        mov     rcx, [stack_top]
        sub     rcx, [stack_min]

        int3
        nop
        ; inspect our stack usage in rcx

        add     rsp, 16

        ; [rsp] back to commandline args

        mov     eax, 60         ; syscall_exit
        xor     edi, edi
        syscall
        

section '.data' writable align 16

stack_top       dq      0
stack_size      dq      0
stack_min       dq      0
    


When run from inside gdb, we get the following values:
Code:
(gdb) run
Starting program: /tmp/test 

Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000000000400116 in _start ()
(gdb) i r rdx rcx
rdx            0x800000 8388608
rcx            0xffffffffffffffff       -1
(gdb) cont
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x000000000040012b in _start ()
(gdb) i r rcx
rcx            0x1008   4104
(gdb) cont
Continuing.
[Inferior 1 (process 55241) exited normally]
    

_________________
2 Ton Digital - https://2ton.com.au/
Post 08 Dec 2018, 20:17
View user's profile Send private message Reply with quote
sts-q



Joined: 29 Nov 2018
Posts: 57
sts-q 08 Dec 2018, 20:17
The following code is apparently working.
In stead of
mov a, [k]
add k, 8
it does
pop a
starting at rs_minval.

Best Regards and a Happy Second Advent
sts-q

Code:
     Stacks.max.rs:
        mov k, rsp
        mov rsp, [rs_minval]
        mov v, 1048000
        clr d
        
    doloop
        pop a
        dec v
        notzero? a, .done
        inc d
        until_zero v
        error errmess_ssw
        
    .done:
        mov rsp, k
        mov a, [rs_base]
        sub a, [rs_minval]
        shr a,3
        sub a, d
        int a                           ; a := (rs_base - rs_minval ) / 8   -  d
        shiftup a
        exec

    
Post 08 Dec 2018, 20:17
View user's profile Send private message Visit poster's website Reply with quote
sts-q



Joined: 29 Nov 2018
Posts: 57
sts-q 08 Dec 2018, 20:46
Thank you for your answer, redsock!

You solution is simpler and more straight forward than mine: update stack usage together with check for overflow. Ok, the marco is 4 instructions more. I will try it.

That was close: 20:17 both!
Smile

Code:
                    result       return-stack-usage
ackermann( 3, 13 )    65533     196608
ackermann( 3, 14 )   131069    396216
ackermann( 3, 15 )   262141    786432
    


Smile Smile
Post 08 Dec 2018, 20:46
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.