summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortom_at_work <tom_at_work@3ad0048d-3df7-0310-abae-a5850022a9f2>2011-09-08 21:17:35 +0000
committertom_at_work <tom_at_work@3ad0048d-3df7-0310-abae-a5850022a9f2>2011-09-08 21:17:35 +0000
commit5a0361cbf70922474a3377d9fd8e4f69f009f999 (patch)
treed4d195dc7b7620cbd907c6d72dafca092a2a49ee
parent072147e6cb00fcdd6c0534e4130d862f14047ee4 (diff)
downloadfpc-5a0361cbf70922474a3377d9fd8e4f69f009f999.tar.gz
Fix shared library loading and unloading for Linux platforms. Shared library initialization and finalization are now called correctly at program startup for compile-time linked dynamic libraries on powerpc-/powerpc64-/arm-/i386- and x86_64-linux.
Every startup code must now provide an additional entry point called "_dynamic_start" that is set as new the entry point if the program links to a Pascal shared library. Its purpose is to set up an exit hook usually passed via a register, which should be called during program finalization if non-nil. We use this additional entry point because this register only has meaningful content when there are any compile-time linked shared libraries, otherwise it often contains random garbage. The difference between the _dynamic_start and the original code is minimal; actually in all implementations the _dynamic_start code passes on control to the old startup code, so we use an additional entry point instead of an additional startup file. Detailed changes and fixes list: compiler: always link to the dynamic loader (ld.so) when compiling shared libraries. Fixes crashes in the loader during shared library finalization on some Linuxes remove additional ENTRY() section in arm linker script select either _dynamic_start or _start as entry point depending on whether this is a static or dynamic executable powerpc*: do not set System.isLibrary in startup code, it will be set during library initialization anyway trap in case of reaching code locations that should not be reached instead of looping (possibly endlessly) powerpc: register atexit() function pointer if supplied to the executable and call it during shutdown correctly set argc/argv/envp in shared library code and return correctly to the caller after initialization pass on exitcode in shared library haltproc use the more recent exit_group system call if available for shutdown powerpc64 fix .ptrgl stub, do not set the environment register to the value of the GOT entry in the function descriptor arm do not set System.isLibrary in startup code, it will be set during library initialization anyway reload exitcode to pass to shutdown mips,mipsel,sparc added stubs to allow correct linking git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@19036 3ad0048d-3df7-0310-abae-a5850022a9f2
-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