Author Topic: setjmp/longjmp in 64-bit mode?  (Read 2166 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
setjmp/longjmp in 64-bit mode?
« on: November 14, 2019, 08:54:19 AM »
Hi Charles,

since some time I am experimenting with this small Wikipedia example using O2, which will fail in 64-bit:

Code: [Select]
/*The example shows the basic idea of setjmp. main() calls first(), which in turn calls second().
  Then, second() jumps back into main(), skipping first()'s call of print. */

/* When executed, the output will be:
second
main
*/
   
$ filename "example1.exe"
'uses rtl32
'uses rtl64

uses corewin
uses console


#ifndef mode64bit
  typedef int jmp_buf[16]
#else
  type _jmp_buf
     ulong data[2]        'ulonglong , ulongint - unsigned 64-bit
  end type
 typedef _jmp_buf jmp_buf[16]
#endif     

macro setjmp(env) _setjmp(env)

jmp_buf buf

sub second()
    printl "second"       ' prints
    longjmp(@buf,1)       ' jumps back to where setjmp was called - making setjmp now return 1
end sub

sub first()
    second()
    printl "first"       ' does not print
end sub

sub main() 
printl "here in main: Enter ..." : waitkey
    if not setjmp(@buf) then       
        first()           ' when executed, setjmp returned 0
    else                  ' when longjmp jumps back, setjmp returns 1
        printl "main"     ' prints
    end if 
end sub

main()

printl "Enter ..."
waitkey

For the #else part I tried to understand setjmp.h or setjmp.bi, but I am not sure if I miss something. It also seems I need an unsigned 64-bit integer for Win64. Would this be a qword?

Code: [Select]
setjmp.h

PellesC:
/* type definitions */
typedef struct __declspec(align(16)) {
    unsigned long long data[2];
} jmp_buf[16];


MSVC:
#elif defined _M_X64

    typedef struct _VCRT_ALIGN(16) _SETJMP_FLOAT128
    {
        unsigned __int64 Part[2];
    } SETJMP_FLOAT128;


FB 1.07.1 (setjmp.bi)
#else
#ifdef __FB_64BIT__
'' x86_64 glibc
type __jmp_buf
__opaque(0 to 8-1) as longint
end type
#else
'' x86 glibc
type __jmp_buf
__opaque(0 to 6-1) as long
end type
#endif

#include once "crt/bits/sigset.bi"

type jmp_buf
__jmpbuf as __jmp_buf
__mask_was_saved as long
__saved_mask as __sigset_t
end type

Is there a way to implement jmp_buf for Win64?

However, I am still not sure if setjmp/longjmp is really necessary? There are different opinions. The example above I could also code like this:

Code: [Select]
/* When executed, the output will be:
second
main
*/
   
$ filename "example1a.exe"
'uses rtl32
'uses rtl64

uses corewin
uses console


sub second()
    printl "second"       ' prints
end sub

sub first()
    second()
    exit sub
    printl "first"       ' does not print
end sub

sub main() 
printl "here in main: Enter ..." : waitkey   
    first()           ' calls second
    printl "main"     ' prints 

end sub

main()

printl "Enter ..."
waitkey
« Last Edit: November 15, 2019, 01:22:34 AM by Arnold »

Charles Pegge

  • Guest
Re: setjmp/longjmp in 64-bit mode?
« Reply #1 on: November 14, 2019, 07:54:47 PM »
Hi Roland,

msvcrt _setjmp appears to be busted in 64bit mode, so here is my version that works in both 32bit and 64bit. It also allows you to set the jump-point anywhere in main().

But I do not recomment this strategy for catching recoverable errors where local garbage collection is involved.

Code: [Select]
'19:16 14/11/2019
'jumping back to main
'
$filename "o.exe"
'uses rtl64
sys buf[3] 'must be in global space

macro setjmp(label,buf)
=======================
addr rsi,buf
mov [rsi],rbp
mov [rsi+8],rsp
addr rcx,label
mov [rsi+16],rcx
end macro

macro longjmp(buf,value)
========================
addr rsi,buf
mov rbp,[rsi]
mov rsp,[rsi+8]
mov rax,value
jmp [rsi+16]
end macro


function xx()
=============
longjmp(buf,0x42)
print "not ok 1"
end function

function main()
===============
int a=0x12
setjmp(here,buf)
xx()
print "not ok 2"
'
here:
mov a,rax
print hex a '42
end function
'
main()


Arnold

  • Guest
Re: setjmp/longjmp in 64-bit mode?
« Reply #2 on: November 15, 2019, 01:51:47 AM »
Thank you, Charles. The macros will not conflict with corewin.inc. Perhaps they can be used to simulate the old BASIC: on error goto ... resume constructs. For other applications I think a while loop combined with select case ... will be more readable and less error-prone anyway.

Roland