Răsfoiți Sursa

* switch x86_64-linux to indirect entry, essentially allowing for the use of dynamic packages on that target

git-svn-id: trunk@36690 -
svenbarth 8 ani în urmă
părinte
comite
0f9451fbb7

+ 1 - 1
compiler/systems.pas

@@ -326,7 +326,7 @@ interface
        systems_indirect_var_imports = systems_all_windows+[system_i386_nativent];
 
        { all systems that support indirect entry information }
-       systems_indirect_entry_information = systems_darwin+[system_i386_win32,system_x86_64_win64];
+       systems_indirect_entry_information = systems_darwin+[system_i386_win32,system_x86_64_win64,system_x86_64_linux];
 
        { all systems for which weak linking has been tested/is supported }
        systems_weak_linking = systems_darwin + systems_solaris + systems_linux + systems_android;

+ 64 - 13
rtl/linux/x86_64/cprt0.as

@@ -44,14 +44,13 @@ _start:
 	popq %rsi		/* Pop the argument count.  */
 	movq %rsp, %rdx		/* argv starts just at the current stack top.  */
 
-        movq    operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
-        movq    %rsi,(%rax)
-        movq    operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
-        movq    %rsp,(%rax)   /* argv starts just at the current stack top.  */
+        movq    entryinfo@GOTPCREL(%rip),%r10 /* load address of entryinfo variable */
+
+        movq    %rsi,56(%r10)
+        movq    %rsp,64(%r10)   /* argv starts just at the current stack top */
         leaq    8(,%rsi,8),%rax
         addq    %rsp,%rax
-        movq    operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
-        movq    %rax,(%rcx)
+        movq    %rax,72(%r10)
 
 	/* Align the stack to a 16 byte boundary to follow the ABI.  */
 	andq  $~15, %rsp
@@ -90,13 +89,38 @@ main_stub:
         movq    %rax,(%rcx)
         pushq   %rax
 
+        /* fill the remaining fields of the entry information */
+        movq    entryinfo@GOTPCREL(%rip),%rdi /* load address of entryinfo variable into argument for SysEntry*/
+
         /* Save initial stackpointer */
-        movq    __stkptr@GOTPCREL(%rip),%rax
-        movq    %rsp,(%rax)
+        movq    %rsp,80(%rdi)
+
+        /* store stack length */
+        movq    __stklen@GOTPCREL(%rip),%rax
+        movq    %rax,88(%rdi)
+
+        /* store pointer to _haltproc */
+        movq    _haltproc@GOTPCREL(%rip),%rax
+        movq    %rax,96(%rdi)
+
+        /* populate the table pointers */
+        movq    INITFINAL@GOTPCREL(%rip),%rax
+        movq    %rax,(%rdi)
+        movq    FPC_THREADVARTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,8(%rdi)
+        movq    FPC_RESOURCESTRINGTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,16(%rdi)
+        movq    FPC_RESSTRINITTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,24(%rdi)
+        movq    FPC_RESLOCATION@GOTPCREL(%rip),%rax
+        movq    %rax,32(%rdi)
+        movq    PASCALMAIN@GOTPCREL(%rip),%rax
+        movq    %rax,40(%rdi)
+        /* valgrind_used can stay 0 */
 
         /* start the program */
         xorq    %rbp,%rbp
-        call    PASCALMAIN@PLT
+        call    FPC_SysEntry@PLT
         hlt
 	.size   main_stub,.-main_stub
 
@@ -135,11 +159,38 @@ ___fpc_ret_rbp:
         .quad   0
 
 .bss
-        .comm __stkptr,8
+/* the entry information looks like this:
+
+  TEntryInformation = record
+    InitFinalTable : Pointer;           // offset 0
+    ThreadvarTablesTable : Pointer;     // offset 8
+    ResourceStringTables : Pointer;     // offset 16
+    ResStrInitTables : Pointer;         // offset 24
+    ResLocation : Pointer;              // offset 32
+    PascalMain : Procedure;             // offset 40
+    valgrind_used : boolean;            // offset 48
+    OS : TEntryInformationOS;           // offset 56
+  end;
+
+  with TEntryInformationOS being
 
-        .comm operatingsystem_parameter_envp,8
-        .comm operatingsystem_parameter_argc,8
-        .comm operatingsystem_parameter_argv,8
+  TEntryInformationOS = record
+    argc: longint;                         // offset 56
+    argv: ppchar;                          // offset 64
+    envp: ppchar;                          // offset 72
+    stkptr: pointer;                       // offset 80
+    stklen: sizeuint;                      // offset 88
+    haltproc: procedure(e:longint);cdecl;  // offset 96
+  end;
+
+  The size of TEntryInformationOS including padding is 5 * sizeof(Pointer) = 40
+
+  The size of TEntryInformation including padding without OS is 8 * sizeof(Pointer) = 64
+
+  Thus the total size of TEntryInformation including padding is 104
+
+*/
+        .comm entryinfo,104
 
 /* We need this stuff to make gdb behave itself, otherwise
    gdb will chokes with SIGILL when trying to debug apps.

+ 66 - 17
rtl/linux/x86_64/dllprt0.as

@@ -44,23 +44,45 @@ FPC_SHARED_LIB_START:
 	.globl _startlib
 	.type _startlib,@function
 _startlib:
-	pushq	 %rbx
-        movq     operatingsystem_parameter_argc@GOTPCREL(%rip),%rbx
-        movq     %rdi,(%rbx)
-        movq     operatingsystem_parameter_argv@GOTPCREL(%rip),%rbx
-	movq     %rsi,(%rbx)          /* argv starts just at the current stack top.  */
-        movq     operatingsystem_parameter_envp@GOTPCREL(%rip),%rbx
-        movq     %rdx,(%rbx)
+        movq    entryinfo@GOTPCREL(%rip),%r10 /* load address of entryinfo variable */
 
-        movq    operatingsystem_islibrary@GOTPCREL(%rip),%rbx
-        movb    $1,(%rbx)
+        movq    %rdi,56(%r10)
+        movq    %rsi,64(%r10)   /* argv starts just at the current stack top */
+        movq    %rdx,72(%r10)
 
         /* Save initial stackpointer */
-        movq    __stkptr@GOTPCREL(%rip),%rbx
-        movq    %rsp,(%rbx)
+        movq    %rsp,80(%r10)
 
-        call    PASCALMAIN@PLT
-	popq	%rbx
+        /* store stack length */
+        movq    __stklen@GOTPCREL(%rip),%rax
+        movq    %rax,88(%r10)
+
+        /* store pointer to _haltproc */
+        movq    _haltproc@GOTPCREL(%rip),%rax
+        movq    %rax,96(%r10)
+
+        /* populate the table pointers */
+        movq    INITFINAL@GOTPCREL(%rip),%rax
+        movq    %rax,(%r10)
+        movq    FPC_THREADVARTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,8(%r10)
+        movq    FPC_RESOURCESTRINGTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,16(%r10)
+        movq    FPC_RESSTRINITTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,24(%r10)
+        movq    FPC_RESLOCATION@GOTPCREL(%rip),%rax
+        movq    %rax,32(%r10)
+        movq    PASCALMAIN@GOTPCREL(%rip),%rax
+        movq    %rax,40(%r10)
+        /* valgrind_used can stay 0 */
+
+        /* setup argument for FPC_SysEntry */
+        movq    %r10,%rdi
+
+        movq    operatingsystem_islibrary@GOTPCREL(%rip),%r10
+        movb    $1,(%r10)
+
+        call    FPC_SysEntry@PLT
 	ret
 
 /* this routine is only called when the halt() routine of the RTL embedded in
@@ -83,11 +105,38 @@ __data_start:
         data_start = __data_start
 
 .bss
-        .comm __stkptr,8
+/* the entry information looks like this:
+
+  TEntryInformation = record
+    InitFinalTable : Pointer;           // offset 0
+    ThreadvarTablesTable : Pointer;     // offset 8
+    ResourceStringTables : Pointer;     // offset 16
+    ResStrInitTables : Pointer;         // offset 24
+    ResLocation : Pointer;              // offset 32
+    PascalMain : Procedure;             // offset 40
+    valgrind_used : boolean;            // offset 48
+    OS : TEntryInformationOS;           // offset 56
+  end;
 
-        .comm operatingsystem_parameter_envp,8
-        .comm operatingsystem_parameter_argc,8
-        .comm operatingsystem_parameter_argv,8
+  with TEntryInformationOS being
+
+  TEntryInformationOS = record
+    argc: longint;                         // offset 56
+    argv: ppchar;                          // offset 64
+    envp: ppchar;                          // offset 72
+    stkptr: pointer;                       // offset 80
+    stklen: sizeuint;                      // offset 88
+    haltproc: procedure(e:longint);cdecl;  // offset 96
+  end;
+
+  The size of TEntryInformationOS including padding is 5 * sizeof(Pointer) = 40
+
+  The size of TEntryInformation including padding without OS is 8 * sizeof(Pointer) = 64
+
+  Thus the total size of TEntryInformation including padding is 104
+
+*/
+        .comm entryinfo,104
 
 
 /* We need this stuff to make gdb behave itself, otherwise

+ 64 - 13
rtl/linux/x86_64/gprt0.as

@@ -44,14 +44,13 @@ _start:
 	popq %rsi		/* Pop the argument count.  */
 	movq %rsp, %rdx		/* argv starts just at the current stack top.  */
 
-        movq    operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
-        movq    %rsi,(%rax)
-        movq    operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
-        movq    %rsp,(%rax)   /* argv starts just at the current stack top.  */
+        movq    entryinfo@GOTPCREL(%rip),%r10 /* load address of entryinfo variable */
+
+        movq    %rsi,56(%r10)
+        movq    %rsp,64(%r10)   /* argv starts just at the current stack top */
         leaq    8(,%rsi,8),%rax
         addq    %rsp,%rax
-        movq    operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
-        movq    %rax,(%rcx)
+        movq    %rax,72(%r10)
 
 	/* Align the stack to a 16 byte boundary to follow the ABI.  */
 	andq  $~15, %rsp
@@ -98,13 +97,38 @@ main_stub:
         movq    _mcleanup@GOTPCREL(%rip),%rdi
         call    atexit@PLT
 
+        /* fill the remaining fields of the entry information */
+        movq    entryinfo@GOTPCREL(%rip),%rdi /* load address of entryinfo variable into argument for SysEntry*/
+
         /* Save initial stackpointer */
-        movq    __stkptr@GOTPCREL(%rip),%rax
-        movq    %rsp,(%rax)
+        movq    %rsp,80(%rdi)
+
+        /* store stack length */
+        movq    __stklen@GOTPCREL(%rip),%rax
+        movq    %rax,88(%rdi)
+
+        /* store pointer to _haltproc */
+        movq    _haltproc@GOTPCREL(%rip),%rax
+        movq    %rax,96(%rdi)
+
+        /* populate the table pointers */
+        movq    INITFINAL@GOTPCREL(%rip),%rax
+        movq    %rax,(%rdi)
+        movq    FPC_THREADVARTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,8(%rdi)
+        movq    FPC_RESOURCESTRINGTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,16(%rdi)
+        movq    FPC_RESSTRINITTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,24(%rdi)
+        movq    FPC_RESLOCATION@GOTPCREL(%rip),%rax
+        movq    %rax,32(%rdi)
+        movq    PASCALMAIN@GOTPCREL(%rip),%rax
+        movq    %rax,40(%rdi)
+        /* valgrind_used can stay 0 */
 
         /* start the program */
         xorq    %rbp,%rbp
-        call    PASCALMAIN@PLT
+        call    FPC_SysEntry@PLT
         hlt
         .size   main_stub,.-main_stub
 
@@ -155,11 +179,38 @@ ___fpc_ret_rbp:
         .quad   0
 
 .bss
-        .comm __stkptr,8
+/* the entry information looks like this:
+
+  TEntryInformation = record
+    InitFinalTable : Pointer;           // offset 0
+    ThreadvarTablesTable : Pointer;     // offset 8
+    ResourceStringTables : Pointer;     // offset 16
+    ResStrInitTables : Pointer;         // offset 24
+    ResLocation : Pointer;              // offset 32
+    PascalMain : Procedure;             // offset 40
+    valgrind_used : boolean;            // offset 48
+    OS : TEntryInformationOS;           // offset 56
+  end;
+
+  with TEntryInformationOS being
 
-        .comm operatingsystem_parameter_envp,8
-        .comm operatingsystem_parameter_argc,8
-        .comm operatingsystem_parameter_argv,8
+  TEntryInformationOS = record
+    argc: longint;                         // offset 56
+    argv: ppchar;                          // offset 64
+    envp: ppchar;                          // offset 72
+    stkptr: pointer;                       // offset 80
+    stklen: sizeuint;                      // offset 88
+    haltproc: procedure(e:longint);cdecl;  // offset 96
+  end;
+
+  The size of TEntryInformationOS including padding is 5 * sizeof(Pointer) = 40
+
+  The size of TEntryInformation including padding without OS is 8 * sizeof(Pointer) = 64
+
+  Thus the total size of TEntryInformation including padding is 104
+
+*/
+        .comm entryinfo,104
 
 /* We need this stuff to make gdb behave itself, otherwise
    gdb will chokes with SIGILL when trying to debug apps.

+ 66 - 15
rtl/linux/x86_64/prt0.as

@@ -48,23 +48,46 @@ _dynamic_start:
 	.globl _start
 	.type _start,@function
 _start:
-	popq    %rsi		      /* Pop the argument count.  */
-        movq 	operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
-        movq    %rsi,(%rax)
-        movq 	operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
-	movq    %rsp,(%rax)   /* argv starts just at the current stack top.  */
+        movq    entryinfo@GOTPCREL(%rip),%rdi /* load address of entryinfo variable into argument for SysEntry */
+
+	popq    %rsi      /* Pop the argument count.  */
+        movq    %rsi,56(%rdi)
+        movq    %rsp,64(%rdi)   /* argv starts just at the current stack top */
         leaq    8(,%rsi,8),%rax
         addq    %rsp,%rax
-        movq 	operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
-        movq    %rax,(%rcx)
-        andq    $~15,%rsp            /* Align the stack to a 16 byte boundary to follow the ABI.  */
+        movq    %rax,72(%rdi)
+
+        andq    $~15,%rsp   /* Align the stack to a 16 byte boundary to follow the ABI */
 
         /* Save initial stackpointer */
-        movq 	__stkptr@GOTPCREL(%rip),%rax
-        movq    %rsp,(%rax)
+        movq    %rsp,80(%rdi)
+
+        /* store stack length */
+        movq    __stklen@GOTPCREL(%rip),%rax
+        movq    %rax,88(%rdi)
+
+        /* store pointer to _haltproc */
+        movq    _haltproc@GOTPCREL(%rip),%rax
+        movq    %rax,96(%rdi)
+
+        /* populate the table pointers */
+        movq    INITFINAL@GOTPCREL(%rip),%rax
+        movq    %rax,(%rdi)
+        movq    FPC_THREADVARTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,8(%rdi)
+        movq    FPC_RESOURCESTRINGTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,16(%rdi)
+        movq    FPC_RESSTRINITTABLES@GOTPCREL(%rip),%rax
+        movq    %rax,24(%rdi)
+        movq    FPC_RESLOCATION@GOTPCREL(%rip),%rax
+        movq    %rax,32(%rdi)
+        movq    PASCALMAIN@GOTPCREL(%rip),%rax
+        movq    %rax,40(%rdi)
+        /* valgrind_used can stay 0 */
 
         xorq    %rbp, %rbp
-        call    PASCALMAIN
+        call    FPC_SysEntry@PLT
+
 	jmp	_haltproc
 
         .globl  _haltproc
@@ -92,12 +115,40 @@ __data_start:
         data_start = __data_start
 
 .bss
-        .comm __stkptr,8
         .comm __dl_fini,8
 
-        .comm operatingsystem_parameter_envp,8
-        .comm operatingsystem_parameter_argc,8
-        .comm operatingsystem_parameter_argv,8
+/* the entry information looks like this:
+
+  TEntryInformation = record
+    InitFinalTable : Pointer;           // offset 0
+    ThreadvarTablesTable : Pointer;     // offset 8
+    ResourceStringTables : Pointer;     // offset 16
+    ResStrInitTables : Pointer;         // offset 24
+    ResLocation : Pointer;              // offset 32
+    PascalMain : Procedure;             // offset 40
+    valgrind_used : boolean;            // offset 48
+    OS : TEntryInformationOS;           // offset 56
+  end;
+
+  with TEntryInformationOS being
+
+  TEntryInformationOS = record
+    argc: longint;                         // offset 56
+    argv: ppchar;                          // offset 64
+    envp: ppchar;                          // offset 72
+    stkptr: pointer;                       // offset 80
+    stklen: sizeuint;                      // offset 88
+    haltproc: procedure(e:longint);cdecl;  // offset 96
+  end;
+
+  The size of TEntryInformationOS including padding is 5 * sizeof(Pointer) = 40
+
+  The size of TEntryInformation including padding without OS is 8 * sizeof(Pointer) = 64
+
+  Thus the total size of TEntryInformation including padding is 104
+
+*/
+        .comm entryinfo,104
 
 
 /* We need this stuff to make gdb behave itself, otherwise

+ 30 - 0
rtl/linux/x86_64/si_c.inc

@@ -50,6 +50,8 @@ procedure libc_init; external name '__libc_init';
 procedure libc_setfpucw; external name '__setfpucw';
 procedure libc_start_main; external name '__libc_start_main';
 
+procedure _FPC_libc_haltproc(e:longint); forward;
+
 procedure main_stub; assembler; nostackframe;
   asm
     { save return address }
@@ -62,6 +64,22 @@ procedure main_stub; assembler; nostackframe;
     movq    %rbp,fpc_ret_rbp(%rip)
     pushq   %rax
 
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    { Save initial stackpointer }
+    movq    SysInitEntryInformation@GOTPCREL(%rip),%rdi
+    movq    %rsp,TEntryInformation.OS.stkptr(%rdi)
+
+    { store stack length }
+    movq StackLength@GOTPCREL(%rip),%rax
+    movq %rax,TEntryInformation.OS.stklen(%rcx)
+
+    { store pointer to haltproc }
+    movq    _FPC_libc_haltproc@GOTPCREL(%rip),%rax
+    movq    %rax,TEntryInformation.OS.haltproc(%rdi)
+
+    xorq    %rbp,%rbp
+    call    SysEntry
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     { Save initial stackpointer }
     movq    initialstkptr@GOTPCREL(%rip),%rax
     movq    %rsp,(%rax)
@@ -69,6 +87,7 @@ procedure main_stub; assembler; nostackframe;
     { start the program }
     xorq    %rbp,%rbp
     call    PASCALMAIN
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     hlt
   end;
 
@@ -106,6 +125,16 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
     popq %rsi               { Pop the argument count.  }
     movq %rsp, %rdx         { argv starts just at the current stack top.  }
 
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    movq SysInitEntryInformation@GOTPCREL(%rip),%rcx
+
+    movl %rsi,TEntryInformation.OS.argc(%rcx)
+    movq %rsp,TEntryInformation.OS.argv(%rcx)
+    movq %rsp,(%rax)
+    leaq 8(,%rsi,8),%rax
+    addq %rsp,%rax
+    movq %rax,TEntryInformation.OS.envp(%rcx)
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
     movq %rsi,(%rax)
     movq operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
@@ -114,6 +143,7 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
     addq %rsp,%rax
     movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
     movq %rax,(%rcx)
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
 
     { Align the stack to a 16 byte boundary to follow the ABI.  }
     andq  $0xfffffffffffffff0, %rsp

+ 12 - 0
rtl/linux/x86_64/si_dll.inc

@@ -14,13 +14,25 @@
 
 {$asmmode gas}
 
+procedure _FPC_shared_lib_haltproc(e:longint); cdecl; forward;
+
 procedure _FPC_shared_lib_start(argc:dword; argv,envp:pointer); cdecl; public name 'FPC_SHARED_LIB_START'; public name '_start';
 begin
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+  SysInitEntryInformation.OS.argc:=argc;
+  SysInitEntryInformation.OS.argv:=argv;
+  SysInitEntryInformation.OS.envp:=envp;
+  SysInitEntryInformation.OS.stkptr:=get_frame;
+  SysInitEntryInformation.OS.stklen:=StackLength;
+  SysInitEntryInformation.OS.haltproc:=@_FPC_shared_lib_haltproc;
+  SysEntry(SysInitEntryInformation);
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
   operatingsystem_parameter_argc:=argc;
   operatingsystem_parameter_argv:=argv;
   operatingsystem_parameter_envp:=envp;
   InitialStkPtr:=get_frame;
   PASCALMAIN;
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
 end;
 
 { this routine is only called when the halt() routine of the RTL embedded in

+ 33 - 1
rtl/linux/x86_64/si_g.inc

@@ -55,6 +55,8 @@ procedure gmon_mcleanup; external name '_mcleanup';
 
 procedure main_stub; forward;
 
+procedure _FPC_libc_haltproc(e:longint); forward;
+
 procedure ini_dummy;
   begin
   end;
@@ -63,7 +65,7 @@ procedure ini_dummy;
                           C library start/halt
  ******************************************************************************}
 
-procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
+ procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
   asm
     { Clear the frame pointer.  The ABI suggests this be done, to mark
      the outermost frame obviously.  }
@@ -88,6 +90,16 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
     popq %rsi               { Pop the argument count.  }
     movq %rsp, %rdx         { argv starts just at the current stack top.  }
 
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    movq SysInitEntryInformation@GOTPCREL(%rip),%rcx
+
+    movl %rsi,TEntryInformation.OS.argc(%rcx)
+    movq %rsp,TEntryInformation.OS.argv(%rcx)
+    movq %rsp,(%rax)
+    leaq 8(,%rsi,8),%rax
+    addq %rsp,%rax
+    movq %rax,TEntryInformation.OS.envp(%rcx)
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
     movq %rsi,(%rax)
     movq operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
@@ -96,6 +108,7 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
     addq %rsp,%rax
     movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
     movq %rax,(%rcx)
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
 
     { Align the stack to a 16 byte boundary to follow the ABI.  }
     andq  $0xfffffffffffffff0, %rsp
@@ -154,6 +167,24 @@ procedure main_stub; assembler; nostackframe;
 
     movq    gmon_mcleanup@GOTPCREL(%rip),%rdi
     call    libc_atexit@PLT
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    movq    SysInitEntryInformation@GOTPCREL(%rip),%rdi
+
+    { Save initial stackpointer }
+    movq    %rsp,TEntryInformation.OS.stkptr(%rdi)
+
+    { store stack length }
+    movq    StackLength@GOTPCREL(%rip),%rax
+    movq    %rax,TEntryInformation.OS.stklen(%rdi)
+
+    { store pointer to haltproc }
+    movq    _FPC_libc_haltproc@GOTPCREL(%rip),%rax
+    movq    %rax,TEntryInformation.OS.haltproc(%rdi)
+
+    xorq    %rbp,%rbp
+    call    SysEntry@PLT
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     { Save initial stackpointer }
     movq    initialstkptr@GOTPCREL(%rip),%rax
     movq    %rsp,(%rax)
@@ -161,6 +192,7 @@ procedure main_stub; assembler; nostackframe;
     { start the program }
     xorq    %rbp,%rbp
     call    PASCALMAIN@PLT
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     hlt
   end;
 

+ 30 - 0
rtl/linux/x86_64/si_prc.inc

@@ -42,8 +42,37 @@
 var
   dlexitproc: pointer;
 
+procedure _FPC_proc_haltproc(e: longint); forward;
+
 procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
   asm
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    movq     SysInitEntryInformation@GOTPCREL(%rip),%r10          { load address of SysInitEntryInformation variable }
+
+    popq     %rsi                                  { Pop the argument count.  }
+    movq     %rsi,TEntryInformation.OS.argc(%r10)
+    movq     %rsp,TEntryInformation.OS.argv(%r10)                           { argv starts just at the current stack top.  }
+    leaq     8(,%rsi,8),%rax
+    addq     %rsp,%rax
+    movq     %rax,TEntryInformation.OS.envp(%r10)
+    andq     $0xfffffffffffffff0,%rsp                             { Align the stack to a 16 byte boundary to follow the ABI.  }
+
+    { Save initial stackpointer }
+    movq    %rsp,TEntryInformation.OS.stkptr(%r10)
+
+    { store stack length }
+    movq    StackLength@GOTPCREL(%rip),%rax
+    movq    %rax,TEntryInformation.OS.stklen(%r10)
+
+    { store pointer to haltproc }
+    movq    _FPC_proc_haltproc@GOTPCREL(%rip),%rax
+    movq    %rax,TEntryInformation.OS.haltproc(%r10)
+
+    movq    %r10,%rdi
+
+    xorq    %rbp, %rbp
+    call    SysEntry
+{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
     popq     %rsi                                  { Pop the argument count.  }
     movq     operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
     movq     %rsi,(%rax)
@@ -61,6 +90,7 @@ procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
 
     xorq    %rbp, %rbp
     call    PASCALMAIN
+{$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
   end;
 
 procedure _FPC_dynamic_proc_start; assembler; nostackframe; public name '_dynamic_start';