1{
2    This file is part of the Free Pascal run time library.
3    Copyright (c) 2005 by Michael Van Canneyt, Peter Vreman,
4    & Daniel Mantione, members of the Free Pascal development team.
5
6    See the file COPYING.FPC, included in this distribution,
7    for details about the copyright.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 **********************************************************************}
14
15{
16 Linux ELF startup code for Free Pascal
17
18
19 Stack layout at program start:
20
21         nil
22         envn
23         ....
24         ....           ENVIRONMENT VARIABLES
25         env1
26         env0
27         nil
28         argn
29         ....
30         ....           COMMAND LINE OPTIONS
31         arg1
32         arg0
33         argc <--- esp
34}
35
36var
37  libc_environ: pchar; external name '__environ';
38  libc_fpu_control: word; external name '__fpu_control';
39  libc_init_proc: procedure; external name '_init';
40  libc_fini_proc: procedure; external name '_fini';
41
42procedure libc_atexit; external name '__libc_atexit';
43procedure libc_exit; external name '__libc_exit';
44procedure libc_init; external name '__libc_init';
45procedure libc_setfpucw; external name '__setfpucw';
46procedure libc_start_main; external name '__libc_start_main';
47
48Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
49
50{******************************************************************************
51                          C library start/halt
52 ******************************************************************************}
53{$asmmode ATT}
54
55procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
56asm
57  { First locate the start of the environment variables }
58  popl    %ecx                    { Get argc in ecx }
59
60  {$ifdef FPC_PIC}
61        movl    %esp,%ebp               { Points to the arguments }
62        movl    %ecx,%esi
63  {$else FPC_PIC}
64        movl    %esp,%ebx               { Points to the arguments }
65  {$endif FPC_PIC}
66
67  leal    4(%esp,%ecx,4),%eax     { The start of the environment is: esp+4*eax+8 }
68  andl    $0xfffffff8,%esp        { Align stack }
69
70  {$ifdef FPC_PIC}
71        pushl   %ecx
72        call  fpc_geteipasebx
73        addl  $_GLOBAL_OFFSET_TABLE_,%ebx
74        movl  operatingsystem_parameter_envp@GOT(%ebx),%ecx
75        movl  %eax,(%ecx)
76        movl  libc_environ@GOT(%ebx),%ecx
77        movl  %eax,(%ecx)
78
79        pushl %eax
80        movl  operatingsystem_parameter_argc@GOT(%ebx),%ecx
81        movl  %esi,%eax
82        movl  %eax,(%ecx)
83        movl  operatingsystem_parameter_argv@GOT(%ebx),%ecx
84        movl  %ebp,%eax
85        movl  %eax,(%ecx)
86	popl  %eax
87
88        popl  %ecx
89        movl  %ebp,%ebx
90  {$else FPC_PIC}
91	movl    %eax,operatingsystem_parameter_envp    { Move the environment pointer }
92	movl    %ecx,operatingsystem_parameter_argc    { Move the argument counter    }
93	movl    %ebx,operatingsystem_parameter_argv    { Move the argument pointer    }
94  	movl    %eax,libc_environ          { libc environ }
95  {$endif FPC_PIC}
96
97
98  pushl   %eax
99  pushl   %ebx
100  pushl   %ecx
101
102  call    libc_init             { init libc }
103
104  {$ifdef FPC_PIC}
105        pushl   %ecx
106  	pushl   %ebx
107        call  fpc_geteipasebx
108        addl  $_GLOBAL_OFFSET_TABLE_,%ebx
109        movl  libc_init_proc@GOT(%ebx),%ecx
110	movl  (%ecx),%edi
111  	popl    %ebx
112        popl    %ecx
113  {$else FPC_PIC}
114	movzwl  libc_fpu_control,%eax
115  {$endif FPC_PIC}
116
117
118  pushl   %eax
119  call    libc_setfpucw
120  popl    %eax
121  pushl   $libc_fini_proc
122  call    libc_atexit
123  popl    %eax
124
125  {$ifdef FPC_PIC}
126	call    *%edi
127  {$else FPC_PIC}
128	call    libc_init_proc
129  {$endif FPC_PIC}
130
131  popl    %eax
132  popl    %eax
133
134  { Save initial stackpointer }
135  {$ifdef FPC_PIC}
136        pushl   %ecx
137  	pushl   %ebx
138        call  fpc_geteipasebx
139        addl  $_GLOBAL_OFFSET_TABLE_,%ebx
140        movl  initialstkptr@GOT(%ebx),%ecx
141	movl  %esp,(%ecx)
142  	popl    %ebx
143        popl    %ecx
144  {$else FPC_PIC}
145	movl    %esp,initialstkptr
146  {$endif FPC_PIC}
147
148  xorl    %ebp,%ebp
149  call    PASCALMAIN              { start the program }
150end;
151
152procedure _FPC_libc_haltproc(e: longint); cdecl; assembler; public name '_haltproc';
153asm
154.Lhaltproc:
155  pushl   e
156  call    libc_exit
157  xorl    %eax,%eax
158  incl    %eax                    { eax=1, exit call }
159  movl    e,%ebx
160  int     $0x80
161  jmp     .Lhaltproc
162end;
163
164