This setjmp.c builds in windows under Microsoft Visual Studio Professional 2019 (Version 16.10.1)
Rebuild started...
1>------ Rebuild All started: Project: setjmp, Configuration: Release x64 ------
1>setjmp.c
1>C:\Users\john\source\repos\setjmp\setjmp.c(48,10): warning C4013: 'setjmp' undefined; assuming extern returning int
1>Generating code
1>Previous IPDB not found, fall back to full compilation.
1>All 1 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
1>Finished generating code
1>setjmp.vcxproj -> C:\Users\john\source\repos\setjmp\x64\Release\setjmp.exe
1>Done building project "setjmp.vcxproj".
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
The actual cl.exe C compiler command is
1> C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\bin\HostX86\x64\CL.exe /c /Zi /nologo /W3 /WX- /diagnostics:column /sdl /O2 /Oi /GL /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /permissive- /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"x64\Release\\" /Fd"x64\Release\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W3 /Gd /TC /FC /errorReport:prompt setjmp.c
The source code is
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
typedef uint64_t QWORD;
typedef uint32_t DWORD;
typedef uint16_t WORD;
typedef uint8_t BYTE;
typedef struct MSTJMP_FLOAT128
{
QWORD Part[2];
} MSTJMP_FLOAT128;
typedef struct JUMP_BUFFER
{
QWORD Frame0;
QWORD Rbx0;
QWORD Rsp0;
QWORD Rbp0;
QWORD Rsi0;
QWORD Rdi0;
QWORD R120;
QWORD R130;
QWORD R140;
QWORD R150;
QWORD Rip0;
DWORD MxCsr4;
WORD FpCsr2;
WORD Spare2;
struct MSTJMP_FLOAT128 Xmm6x;
struct MSTJMP_FLOAT128 Xmm7x;
struct MSTJMP_FLOAT128 Xmm8x;
struct MSTJMP_FLOAT128 Xmm9x;
struct MSTJMP_FLOAT128 Xmm10x;
struct MSTJMP_FLOAT128 Xmm11x;
struct MSTJMP_FLOAT128 Xmm12x;
struct MSTJMP_FLOAT128 Xmm13x;
struct MSTJMP_FLOAT128 Xmm14x;
struct MSTJMP_FLOAT128 Xmm15x;
} JUMP_BUFFER;
int main() {
struct JUMP_BUFFER jumpbuffer;
setjmp(&jumpbuffer, 0);
return 0;
}
The disassembly for setjmp() call is
setjmp(&jumpbuffer, 0);
00007FF641B51019 xor edx,edx
00007FF641B5101B lea rcx,[jumpbuffer]
00007FF641B51020 call __intrinsic_setjmp (07FF641B51C20h)
which leads to the setjmp() code
--- d:\a01\_work\2\s\src\vctools\crt\vcruntime\src\eh\amd64\setjmp.asm ---------
00007FF82B6F0300 mov qword ptr [rcx],rdx
00007FF82B6F0303 mov qword ptr [rcx+8],rbx
00007FF82B6F0307 mov qword ptr [rcx+18h],rbp
so everything is functioning correctly without any errors because windows is using a C-runtime intrinsic within setjmp.asm
However, under linux, it generates an error:
error: macro "setjmp" passed 2 arguments, but takes just 1
Google'ing found this code snippet:
#if defined(_WIN64)
/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
* If this parameter is NULL, longjump does no stack unwinding.
* That is what we need for QEMU. Passing the value of register rsp (default)
* lets longjmp try a stack unwinding which will crash with generated code. */
# undef setjmp
# define setjmp(env) _setjmp(env, NULL)
#endif
To sum up, windows can take 2 args:
setjmp(&jumpbuffer, 0);
and linux can take 1 arg:
setjmp(&jumpbuffer);
To verify that linux likes that setjmp, I traced with gdb as follows:
Your issue is that you didn't #include <setjmp.h>
so the compiler doesn't know the function signature and assumes that setjmp
is some function returning int
and accepts an unknown number of parameters of unknown types. When you declare func()
then it's a function returning int in older C standards and you can call func()
, func(1, 2, 3)
or func(1, "abc", 'd', 2, 3)
... - all are valid
Notice the warning right from your compiler output
setjmp.c(48,10): warning C4013: 'setjmp' undefined; assuming extern returning int
It can also be reproducible on godbolt, with the same warning from MSVC. And you can see that the compiler doesn't report any errors even though I've added some dummy setjmp
calls like
setjmp(&jumpbuffer, 0);
setjmp();
setjmp(1, 2, "abc");
setjmp(&jumpbuffer, 0, 3, 4, 5);
See