summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/systems/t_linux.pas18
-rw-r--r--rtl/linux/arm/dllprt0.as27
-rw-r--r--rtl/linux/arm/prt0.as24
-rw-r--r--rtl/linux/i386/si_prc.inc27
-rw-r--r--rtl/linux/mips/prt0.as10
-rw-r--r--rtl/linux/mipsel/prt0.as15
-rw-r--r--rtl/linux/powerpc/dllprt0.as46
-rw-r--r--rtl/linux/powerpc/prt0.as75
-rw-r--r--rtl/linux/powerpc64/dllprt0.as27
-rw-r--r--rtl/linux/powerpc64/prt0.as103
-rw-r--r--rtl/linux/sparc/prt0.as17
-rw-r--r--rtl/linux/x86_64/dllprt0.as2
-rw-r--r--rtl/linux/x86_64/prt0.as24
-rw-r--r--rtl/linux/x86_64/si_prc.inc14
14 files changed, 321 insertions, 108 deletions
diff --git a/compiler/systems/t_linux.pas b/compiler/systems/t_linux.pas
index 0712159bc9..4977a116a0 100644
--- a/compiler/systems/t_linux.pas
+++ b/compiler/systems/t_linux.pas
@@ -330,6 +330,7 @@ Var
s,s1,s2 : TCmdStr;
found1,
found2 : boolean;
+ linksToSharedLibFiles : boolean;
begin
result:=False;
{ set special options for some targets }
@@ -432,6 +433,13 @@ begin
{ Write sharedlibraries like -l<lib>, also add the needed dynamic linker
here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if (isdll) then
+ begin
+ Add('INPUT(');
+ Add(info.DynamicLinker);
+ Add(')');
+ end;
+ linksToSharedLibFiles := not SharedLibFiles.Empty;
if not SharedLibFiles.Empty then
begin
@@ -497,8 +505,13 @@ begin
end;
end;
- {Entry point.}
- add('ENTRY(_start)');
+ {Entry point. Only needed for executables, set on the linker command line for
+ shared libraries. }
+ if (not isdll) then
+ if (linksToSharedLibFiles and not linklibc) then
+ add('ENTRY(_dynamic_start)')
+ else
+ add('ENTRY(_start)');
{$ifdef x86_64}
{$define LINKERSCRIPT_INCLUDED}
@@ -641,7 +654,6 @@ begin
add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",');
add(' "elf32-littlearm")');
add('OUTPUT_ARCH(arm)');
- add('ENTRY(_start)');
add('SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");');
add('SECTIONS');
add('{');
diff --git a/rtl/linux/arm/dllprt0.as b/rtl/linux/arm/dllprt0.as
index a054991d31..129bc0bb19 100644
--- a/rtl/linux/arm/dllprt0.as
+++ b/rtl/linux/arm/dllprt0.as
@@ -1,3 +1,18 @@
+/*
+ * This file is part of the Free Pascal run time library.
+ * Copyright (c) 2011 by Thomas Schatzl,
+ * member of the Free Pascal development team.
+ *
+ * Startup code for shared libraries, ARM version.
+ *
+ * See the file COPYING.FPC, included in this distribution,
+ * for details about the copyright.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
.file "dllprt0.as"
.text
.globl _startlib
@@ -24,10 +39,6 @@ FPC_SHARED_LIB_START:
ldr ip, =__stklen
str sp, [ip]
- ldr ip, =TC_SYSTEM_ISLIBRARY
- mov a1, #1
- str a1, [ip]
-
/* call main and exit normally */
bl PASCALMAIN
ldmdb fp, {fp, sp, pc}
@@ -35,14 +46,18 @@ FPC_SHARED_LIB_START:
.globl _haltproc
.type _haltproc,#function
_haltproc:
- /* r0 contains exitcode */
+ /* reload exitcode */
+ ldr r0,=operatingsystem_result
+ ldr r0,[r0]
swi 0x900001
b _haltproc
.globl _haltproc_eabi
.type _haltproc_eabi,#function
_haltproc_eabi:
- /* r0 contains exitcode */
+ /* reload exitcode */
+ ldr r0,=operatingsystem_result
+ ldr r0,[r0]
mov r7,#248
swi 0x0
b _haltproc_eabi
diff --git a/rtl/linux/arm/prt0.as b/rtl/linux/arm/prt0.as
index b655e7ddd2..750779e19f 100644
--- a/rtl/linux/arm/prt0.as
+++ b/rtl/linux/arm/prt0.as
@@ -42,6 +42,14 @@
*/
.text
+ .globl _dynamic_start
+ .type _dynamic_start,#function
+_dynamic_start:
+ ldr ip,=__dl_fini
+ str a1,[ip]
+ b _start
+
+ .text
.globl _start
.type _start,#function
_start:
@@ -81,11 +89,20 @@ _haltproc:
.globl _haltproc_eabi
.type _haltproc_eabi,#function
_haltproc_eabi:
+ ldr r0,=__dl_fini
+ ldr r0,[r0]
+ cmp r0,#0
+
+ /* only branch if not equal zero */
+ movne lr,pc
+ bxne r0 /* we require armv5 anyway, so use bx here */
+
+.Lloop:
ldr r0,=operatingsystem_result
- ldrb r0,[r0]
- mov r7,#248
+ ldr r0,[r0]
+ mov r7,#248 /* exit group call */
swi 0x0
- b _haltproc_eabi
+ b .Lloop
/* Define a symbol for the first piece of initialized data. */
.data
@@ -96,6 +113,7 @@ __data_start:
data_start = __data_start
.bss
+ .comm __dl_fini,4
.comm __stkptr,4
.comm operatingsystem_parameter_envp,4
diff --git a/rtl/linux/i386/si_prc.inc b/rtl/linux/i386/si_prc.inc
index 1be4506e59..fd46d7f1fb 100644
--- a/rtl/linux/i386/si_prc.inc
+++ b/rtl/linux/i386/si_prc.inc
@@ -41,7 +41,7 @@ procedure PASCALMAIN; external name 'PASCALMAIN';
******************************************************************************}
var
- dlexitproc: pointer;
+ dlexitproc : pointer;
{$ifdef FPC_PIC}
function fpc_geteipasebxlocal : pointer; [external name 'fpc_geteipasebx'];
@@ -60,12 +60,9 @@ asm
{$ifdef FPC_PIC}
pushl %ebx
pushl %ecx
-
- call fpc_geteipasebxlocal
- addl $_GLOBAL_OFFSET_TABLE_,%ebx
- movl dlexitproc@GOT(%ebx),%ecx
- movl %edx,(%ecx)
+ call fpc_geteipasebxlocal
+ addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
@@ -78,7 +75,6 @@ asm
popl %ebx
movl %ebx,(%edx)
{$else FPC_PIC}
- movl %edx, dlexitproc
movl %eax,operatingsystem_parameter_envp
movl %ecx,operatingsystem_parameter_argc
movl %ebx,operatingsystem_parameter_argv
@@ -103,6 +99,23 @@ asm
call PASCALMAIN
end;
+procedure _FPC_dynamic_proc_start; assembler; nostackframe; public name '_dynamic_start';
+asm
+ {$ifdef FPC_PIC}
+ pushl %ebx
+ call fpc_geteipasebxlocal
+ addl $_GLOBAL_OFFSET_TABLE_,%ebx
+
+ movl dlexitproc@GOT(%ebx),%ebx
+ movl %edx,(%ebx)
+ popl %ebx
+ {$else}
+ movl %edx, dlexitproc
+ {$endif}
+ jmp _FPC_proc_start
+end;
+
+
procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc';
asm
diff --git a/rtl/linux/mips/prt0.as b/rtl/linux/mips/prt0.as
index 0dfcec7702..73512fbe03 100644
--- a/rtl/linux/mips/prt0.as
+++ b/rtl/linux/mips/prt0.as
@@ -14,6 +14,13 @@
.section ".text"
.align 4
+ .global _dynamic_start
+ .type _dynamic_start,#function
+_dynamic_start:
+ /* TODO: need to set __dl_fini here */
+ b _start
+
+ .align 4
.global _start
.type _start,#function
_start:
@@ -77,6 +84,8 @@ _start:
.globl _haltproc
.type _haltproc,@function
_haltproc:
+ /* TODO: need to check whether __dl_fini is non-zero and call the function pointer in case */
+
li v0,4001
lui a0,0x0
lw a0,0(a0)
@@ -87,6 +96,7 @@ _haltproc:
.size _start, .-_start
.comm __stkptr,4
+ .comm __dl_fini,4
.comm operatingsystem_parameter_envp,4
.comm operatingsystem_parameter_argc,4
diff --git a/rtl/linux/mipsel/prt0.as b/rtl/linux/mipsel/prt0.as
index 4477c3ea32..2d1b0ab9e6 100644
--- a/rtl/linux/mipsel/prt0.as
+++ b/rtl/linux/mipsel/prt0.as
@@ -14,6 +14,17 @@
.set noat
.section ".text"
+
+ .align 4
+ .global _dynamic_start
+ .type _dynamic_start,@function
+_dynamic_start:
+ /* TODO: check whether this code is correct */
+ lui $a2,%hi(__dl_fini)
+ sw $v0,%lo(__dl_fini)($a2)
+ b _start
+
+
.align 4
.global _start
.type _start,@function
@@ -29,6 +40,7 @@
sp ($29) The stack contains the arguments and environment:
0(%esp) argc
4(%esp) argv[0]
+
...
(4*argc)(%esp) NULL
(4*(argc+1))(%esp) envp[0]
@@ -75,6 +87,8 @@ _start:
.globl _haltproc
.type _haltproc,@function
_haltproc:
+ /* TODO: need to check whether __dl_fini is non-zero and call the function pointer in case */
+
li $v0,4001
lui $a0,0x0
lw $a0,0($a0)
@@ -85,6 +99,7 @@ _haltproc:
.size _start, .-_start
.comm __stkptr,4
+ .comm __dl_fini,4
.comm operatingsystem_parameter_envp,4
.comm operatingsystem_parameter_argc,4
diff --git a/rtl/linux/powerpc/dllprt0.as b/rtl/linux/powerpc/dllprt0.as
index f4d157bc0d..54579408d1 100644
--- a/rtl/linux/powerpc/dllprt0.as
+++ b/rtl/linux/powerpc/dllprt0.as
@@ -20,42 +20,32 @@
.section ".text"
.globl FPC_SHARED_LIB_START
.type FPC_SHARED_LIB_START,@function
-
- .globl _start
-_start:
FPC_SHARED_LIB_START:
- mr 26,1
- /* Set up an initial stack frame, and clear the LR. */
- clrrwi 1,1,4
- li 0,0
- stwu 1,-16(1)
- mtlr 0
- stw 0,0(1)
- lwz 3,0(26) /* get argc */
+ mflr 0
+ stw 0,4(1)
+ stwu 1,-32(1)
+
+ /* store argument count (in r3)*/
lis 11,operatingsystem_parameter_argc@ha
stw 3,operatingsystem_parameter_argc@l(11);
-
- addi 4,26,4 /* get argv */
+ /* store argument vector (in r4) */
lis 11,operatingsystem_parameter_argv@ha
stw 4,operatingsystem_parameter_argv@l(11);
-
- addi 27,3,1 /* calculate argc + 1 into r27 */
- slwi 27,27,2 /* calculate (argc + 1) * sizeof(char *) into r27 */
- add 5,4,27 /* get address of env[0] */
+ /* store environment pointer (in r5) */
lis 11,operatingsystem_parameter_envp@ha
stw 5,operatingsystem_parameter_envp@l(11);
lis 11,__stkptr@ha
stw 1,__stkptr@l(11);
- /* update library flag in RTL */
- lis 11,operatingsystem_islibrary@ha
- li 6, 1
- stb 6, operatingsystem_islibrary@l(11)
-
+ /* call library initialization */
bl PASCALMAIN
- b _haltproc
+ /* return to the caller */
+ addi 1,1,32
+ lwz 0,4(1)
+ mtlr 0
+ blr
.globl _haltproc
.globl FPC_SHARED_LIB_EXIT
@@ -63,9 +53,17 @@ FPC_SHARED_LIB_START:
.type _haltproc,@function
FPC_SHARED_LIB_EXIT:
_haltproc:
+ lis 11,operatingsystem_result@ha
+ lwz 3,operatingsystem_result@l(3)
+ li 0,234 /* exit group call */
+ sc
+
+ lis 11,operatingsystem_result@ha
+ lwz 3,operatingsystem_result@l(3)
li 0,1 /* exit call */
sc
- b _haltproc
+ /* we should not reach here. Crash horribly */
+ trap
/* Define a symbol for the first piece of initialized data. */
.section ".data"
diff --git a/rtl/linux/powerpc/prt0.as b/rtl/linux/powerpc/prt0.as
index 003c1fdd66..e6f51ded20 100644
--- a/rtl/linux/powerpc/prt0.as
+++ b/rtl/linux/powerpc/prt0.as
@@ -1,22 +1,32 @@
-/* Startup code for programs linked with GNU libc.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
+/*
+ * This file is part of the Free Pascal run time library.
+ * Copyright (c) 2011 by Thomas Schatzl,
+ * member of the Free Pascal development team.
+ *
+ * Startup code for normal programs, PowerPC version.
+ *
+ * See the file COPYING.FPC, included in this distribution,
+ * for details about the copyright.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+/*
+ * Main program entry point for dynamic executables.
+ */
+ .section ".text"
+ .globl _dynamic_start
+_dynamic_start:
+ lis 11,__dl_fini@ha
+ stw 7,__dl_fini@l(11)
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ b _start
+/*
+ * Main program entry point for static executables.
+ */
.section ".text"
.globl _start
_start:
@@ -27,6 +37,7 @@ _start:
stwu 1,-16(1)
mtlr 0
stw 0,0(1)
+
lwz 3,0(26) /* get argc */
lis 11,operatingsystem_parameter_argc@ha
stw 3,operatingsystem_parameter_argc@l(11);
@@ -46,14 +57,36 @@ _start:
bl PASCALMAIN
- b _haltproc
+ /* we should not reach here. Crash horribly */
+ trap
.globl _haltproc
.type _haltproc,@function
_haltproc:
+
+ lis 11,__dl_fini@ha
+ lwz 11,__dl_fini@l(11)
+
+ cmpwi 11, 0
+ beq .LNoDlFiniCall
+
+ mtctr 11
+ bctrl
+
+.LNoDlFiniCall:
+
+ lis 11,operatingsystem_result@ha
+ lwz 3,operatingsystem_result@l(11)
+ li 0,234 /* exit group call */
+ sc
+
+ lis 11,operatingsystem_result@ha
+ lwz 3,operatingsystem_result@l(11)
li 0,1 /* exit call */
sc
- b _haltproc
+ /* we should not reach here. Crash horribly */
+ trap
+
/* Define a symbol for the first piece of initialized data. */
.section ".data"
@@ -63,6 +96,12 @@ data_start:
.section ".bss"
+ .type __dl_fini, @object
+ .size __dl_fini, 4
+ .global __dl_fini
+__dl_fini:
+ .skip 4
+
.type __stkptr, @object
.size __stkptr, 4
.global __stkptr
diff --git a/rtl/linux/powerpc64/dllprt0.as b/rtl/linux/powerpc64/dllprt0.as
index 79907037b9..4896a1d7ae 100644
--- a/rtl/linux/powerpc64/dllprt0.as
+++ b/rtl/linux/powerpc64/dllprt0.as
@@ -3,7 +3,7 @@
* Copyright (c) 2005 by Thomas Schatzl,
* member of the Free Pascal development team.
*
- * Startup code for normal programs, PowerPC64 version.
+ * Startup code for shared libraries, PowerPC64 version.
*
* See the file COPYING.FPC, included in this distribution,
* for details about the copyright.
@@ -56,7 +56,7 @@
std 2, 40(1)
mtctr 0
ld 2, 8(11)
- ld 11, 8(11)
+ ld 11, 16(11)
bctr
.long 0
.byte 0, 12, 128, 0, 0, 0, 0, 0
@@ -322,31 +322,29 @@ _restvr_31: addi r12,r0,-16
/*
* Main program entry point label (function), called by the loader
+ *
+ * The document "64-bit PowerPC ELF Application Binary Interface Supplement 1.9"
+ * pg. 24f specifies the register contents.
*/
FUNCTION_PROLOG FPC_SHARED_LIB_START
-
mflr 0
std 0, 16(1) /* save LR */
stdu 1, -144(1) /* save back chain, make frame */
- /* store argument count (in r3?)*/
+ /* store argument count (in r3)*/
LOAD_64BIT_VAL 10, operatingsystem_parameter_argc
stw 3, 0(10)
- /* store argument vector (in r4?) */
+ /* store argument vector (in r4) */
LOAD_64BIT_VAL 10, operatingsystem_parameter_argv
std 4, 0(10)
- /* store environment pointer (in r5?) */
+ /* store environment pointer (in r5) */
LOAD_64BIT_VAL 10, operatingsystem_parameter_envp
std 5, 0(10)
- /* update library flag in RTL */
- LOAD_64BIT_VAL 8, operatingsystem_islibrary
- li 6, 1
- stb 6, 0(8)
-
LOAD_64BIT_VAL 8, __stkptr
std 1,0(8)
+ /* call library initialization */
bl PASCALMAIN
nop
@@ -355,6 +353,8 @@ FUNCTION_PROLOG FPC_SHARED_LIB_START
ld 0,16(1) /* prepare for method return */
mtlr 0
blr
+.long 0
+.byte 0, 12, 64, 0, 0, 0, 0, 0
/* this routine is only called when the halt() routine of the RTL embedded in
the shared library is called */
@@ -370,7 +370,10 @@ FUNCTION_PROLOG FPC_SHARED_LIB_EXIT
lwz 3, 0(3)
li 0, 1
sc
- b .FPC_SHARED_LIB_EXIT
+ /* we should not reach here. Crash horribly */
+ trap
+.long 0
+.byte 0, 12, 64, 0, 0, 0, 0, 0
/* Define a symbol for the first piece of initialized data. */
.section ".data"
diff --git a/rtl/linux/powerpc64/prt0.as b/rtl/linux/powerpc64/prt0.as
index 9eb7796991..e2b569d211 100644
--- a/rtl/linux/powerpc64/prt0.as
+++ b/rtl/linux/powerpc64/prt0.as
@@ -56,7 +56,7 @@
std 2, 40(1)
mtctr 0
ld 2, 8(11)
- ld 11, 8(11)
+ ld 11, 16(11)
bctr
.long 0
.byte 0, 12, 128, 0, 0, 0, 0, 0
@@ -321,54 +321,97 @@ _restvr_31: addi r12,r0,-16
*/
/*
- * Main program entry point label (function), called by the loader
+ * Main program entry point for dynamic executables.
+ *
+ * r7 contains the function pointer that needs to be registered for calling at exit.
*/
-FUNCTION_PROLOG _start
+FUNCTION_PROLOG _dynamic_start
+ LOAD_64BIT_VAL 11, __dl_fini
+ std 7,0(11)
+ LOAD_64BIT_VAL 11, _start
+ /* do not bother loading the actual function address of _start. We can directly jump to it */
+ /* set up GOT pointer from original start function */
+ ld 2,8(11)
+ /* and environment pointer */
+ ld 11,16(11)
+ b _start
+.long 0
+.byte 0, 12, 64, 0, 0, 0, 0, 0
- mr 26, 1 /* save stack pointer */
+/*
+ * Main program entry point for static executables
+ *
+ * The document "64-bit PowerPC ELF Application Binary Interface Supplement 1.9"
+ * pg. 24f specifies that argc/argv/envp are passed in registers r3/r4/r5 respectively,
+ * but that does not seem to be the case.
+ *
+ * However the stack layout and contents are the same as for other platforms, so
+ * use this.
+ */
+FUNCTION_PROLOG _start
+ mr 26,1 /* save stack pointer */
/* Set up an initial stack frame, and clear the LR */
- clrrdi 1, 1, 5 /* align r1 */
- li 0, 0
+ clrrdi 1,1,5 /* align r1 */
+ li 0,0
stdu 1,-128(1)
mtlr 0
- std 0, 0(1) /* r1 = pointer to NULL value */
+ std 0,0(1) /* r1 = pointer to NULL value */
/* store argument count (= 0(r1) )*/
- ld 3, 0(26)
- LOAD_64BIT_VAL 10, operatingsystem_parameter_argc
- stw 3, 0(10)
+ ld 3,0(26)
+ LOAD_64BIT_VAL 10,operatingsystem_parameter_argc
+ stw 3,0(10)
/* calculate argument vector address and store (= 8(r1) + 8 ) */
- addi 4, 26, 8
- LOAD_64BIT_VAL 10, operatingsystem_parameter_argv
- std 4, 0(10)
+ addi 4,26,8
+ LOAD_64BIT_VAL 10,operatingsystem_parameter_argv
+ std 4,0(10)
/* store environment pointer (= argv + (argc+1)* 8 ) */
- addi 5, 3, 1
- sldi 5, 5, 3
- add 5, 4, 5
+ addi 5,3,1
+ sldi 5,5,3
+ add 5,4,5
LOAD_64BIT_VAL 10, operatingsystem_parameter_envp
- std 5, 0(10)
+ std 5,0(10)
- LOAD_64BIT_VAL 8, __stkptr
+ LOAD_64BIT_VAL 8,__stkptr
std 1,0(8)
bl PASCALMAIN
nop
- /* directly jump to exit procedure, not via the function pointer */
- b ._haltproc
+ /* we should not reach here. Crash horribly */
+ trap
FUNCTION_PROLOG _haltproc
- /* exit group call */
+ mflr 0
+ std 0,16(1)
+ stdu 1,-144(1)
+
+ LOAD_64BIT_VAL 11,__dl_fini
+ ld 11,0(11)
+ cmpdi 11,0
+ beq .LNoCallDlFini
+
+ bl .ptrgl
+ ld 2,40(1)
+
+.LNoCallDlFini:
+
LOAD_64BIT_VAL 3, operatingsystem_result
- lwz 3, 0(3)
- li 0, 234
+ lwz 3,0(3)
+ /* exit group call */
+ li 0,234
sc
- /* exit call */
+
LOAD_64BIT_VAL 3, operatingsystem_result
- lwz 3, 0(3)
- li 0, 1
+ lwz 3,0(3)
+ /* exit call */
+ li 0,1
sc
- b ._haltproc
+ /* we should not reach here. Crash horribly */
+ trap
+ /* do not bother cleaning up the stack frame, we should not reach here */
+.long 0
+.byte 0, 12, 64, 0, 0, 0, 0, 0
/* Define a symbol for the first piece of initialized data. */
.section ".data"
@@ -384,6 +427,12 @@ data_start:
__stkptr:
.skip 8
+ .type __dl_fini, @object
+ .size __dl_fini, 8
+ .global __dl_fini
+__dl_fini:
+ .skip 8
+
.type operatingsystem_parameters, @object
.size operatingsystem_parameters, 24
operatingsystem_parameters:
diff --git a/rtl/linux/sparc/prt0.as b/rtl/linux/sparc/prt0.as
index 48d4cd006a..5f441d61f1 100644
--- a/rtl/linux/sparc/prt0.as
+++ b/rtl/linux/sparc/prt0.as
@@ -19,6 +19,14 @@
02111-1307 USA. */
.section ".text"
+
+ .align 4
+ .global _dynamic_start
+ .type _dynamic_start,#function
+_dynamic_start:
+ /* TODO: need to set __dl_fini here */
+ b _start
+
.align 4
.global _start
.type _start,#function
@@ -49,7 +57,7 @@ _start:
or %o1,%lo(operatingsystem_parameter_envp),%o1
st %o2, [%o1]
- /* Save initial stackpointer */
+ /* Save initial stackpointer */
sethi %hi(__stkptr),%o1
or %o1,%lo(__stkptr),%o1
st %sp, [%o1]
@@ -57,11 +65,15 @@ _start:
/* Call the user program entry point. */
call PASCALMAIN
nop
+ /* Die very horribly if main returns. */
+ unimp
.globl _haltproc
.type _haltproc,@function
_haltproc:
- mov 188, %g1 /* "exit_group" system call */
+ /* TODO: need to check whether __dl_fini is non-zero and call the function pointer in case */
+
+ mov 188, %g1 /* "exit_group" system call */
ta 0x10 /* dot the system call */
nop /* delay slot */
/* Die very horribly if exit returns. */
@@ -70,6 +82,7 @@ _haltproc:
.size _start, .-_start
.comm __stkptr,4
+ .comm __dl_fini,4
.comm operatingsystem_parameter_envp,4
.comm operatingsystem_parameter_argc,4
diff --git a/rtl/linux/x86_64/dllprt0.as b/rtl/linux/x86_64/dllprt0.as
index 8dcbccf7ca..477da7785b 100644
--- a/rtl/linux/x86_64/dllprt0.as
+++ b/rtl/linux/x86_64/dllprt0.as
@@ -44,8 +44,6 @@ FPC_SHARED_LIB_START:
.globl _start
.type _start,@function
_startlib:
-# movq %rdx,%r9 /* Address of the shared library termination
-# function. */
pushq %rbx
movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rbx
movq %rdi,(%rbx)
diff --git a/rtl/linux/x86_64/prt0.as b/rtl/linux/x86_64/prt0.as
index 02fbeeb75c..b8e01f409d 100644
--- a/rtl/linux/x86_64/prt0.as
+++ b/rtl/linux/x86_64/prt0.as
@@ -16,8 +16,10 @@
#
/* This is the canonical entry point, usually the first thing in the text
- segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
- point runs, most registers' values are unspecified, except for:
+ segment. The document "System V Application Binary Interface AMD64
+ Architecture Processor Supplement Version 0.99.5" pg. 30 defines that
+ the entry point runs, most registers' values are unspecified, except
+ for:
%rdx Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
@@ -35,11 +37,17 @@
*/
.text
+ .globl _dynamic_start
+ .type _dynamic_start,@function
+_dynamic_start:
+ movq __dl_fini@GOTPCREL(%rip),%rax
+ movq %rdx,(%rax)
+ jmp _start
+
+ .text
.globl _start
.type _start,@function
_start:
-# movq %rdx,%r9 /* Address of the shared library termination
-# function. */
popq %rsi /* Pop the argument count. */
movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
movq %rsi,(%rax)
@@ -62,6 +70,13 @@ _start:
.globl _haltproc
.type _haltproc,@function
_haltproc:
+ movq __dl_fini@GOTPCREL(%rip),%rax
+ movq (%rax),%rax
+ testq %rax,%rax
+ jz .LNoDlFiniCall
+ call *%rax
+.LNoDlFiniCall:
+
movq operatingsystem_result@GOTPCREL(%rip),%rax
movzwl (%rax),%edi
movl $231,%eax /* exit_group call */
@@ -78,6 +93,7 @@ __data_start:
.bss
.comm __stkptr,8
+ .comm __dl_fini,8
.comm operatingsystem_parameter_envp,8
.comm operatingsystem_parameter_argc,8
diff --git a/rtl/linux/x86_64/si_prc.inc b/rtl/linux/x86_64/si_prc.inc
index a1358d0f07..5f0bcd3e0d 100644
--- a/rtl/linux/x86_64/si_prc.inc
+++ b/rtl/linux/x86_64/si_prc.inc
@@ -37,6 +37,9 @@ procedure PASCALMAIN; external name 'PASCALMAIN';
Process start/halt
******************************************************************************}
+var
+ dlexitproc: pointer;
+
procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
asm
popq %rsi { Pop the argument count. }
@@ -54,9 +57,20 @@ procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
call PASCALMAIN
end;
+procedure _FPC_dynamic_proc_start; assembler; nostackframe; public name '_dynamic_start';
+ asm
+ movq %rdx,dlexitproc
+ jmp _FPC_proc_start
+ end;
procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc';
asm
+ movq dlexitproc,%rdx
+ testq %rdx,%rdx
+ jz .Lhaltproc
+
+ call *%rdx
+
.Lhaltproc:
movl $231,%eax { exit_group call }
movzwl operatingsystem_result,%edi