* several fixes by Pierre Pede (parts of his patch to mantis #12492)

o fixed gprof under linux/i386
    o fixed pic-compilation of the linux/i386 rtl
    o initialisation of linux shared libraries is now possible with pic-code

git-svn-id: trunk@13703 -
This commit is contained in:
Jonas Maebe 2009-09-12 21:57:41 +00:00
parent cc5aeb09de
commit 92ff07deaf
13 changed files with 925 additions and 331 deletions

View File

@ -1074,8 +1074,8 @@ begin
{ Create some replacements }
{ note: linux does not use exportlib.initname/fininame due to the custom startup code }
InitStr:='-init FPC_LIB_START';
FiniStr:='-fini FPC_LIB_EXIT';
InitStr:='-init FPC_SHARED_LIB_START';
FiniStr:='-fini FPC_SHARED_LIB_EXIT';
SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename^);
{ Call linker }

View File

@ -94,10 +94,12 @@ function mmx_support : boolean;
mmx_support:=false;
end;
{$ifndef FPC_PIC}
{$if not defined(FPC_SYSTEM_HAS_MOVE) and defined(REGCALL) }
{$define USE_FASTMOVE}
{$i fastmove.inc}
{$endif FPC_SYSTEM_HAS_MOVE}
{$endif FPC_PIC}
procedure fpc_cpuinit;
begin
@ -1476,7 +1478,17 @@ asm
jl .Lj3596
.Lj3603:
// [104] If declocked(l^) then
{$ifdef FPC_PIC}
pushl %ebx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ismultithread@GOT(%ebx),%ebx
movl (%ebx),%ebx
cmp $0, %ebx
popl %ebx
{$else FPC_PIC}
cmpl $0,ismultithread
{$endif FPC_PIC}
jne .Lj3610
decl (%edx)
je .Lj3620

View File

@ -19,9 +19,9 @@
.globl _startlib
.type _startlib,@function
_startlib:
.globl FPC_LIB_START
.type FPC_LIB_START,@function
FPC_LIB_START:
.globl FPC_SHARED_LIB_START
.type FPC_SHARED_LIB_START,@function
FPC_SHARED_LIB_START:
pushl %ebp
movl %esp,%ebp
@ -47,6 +47,10 @@ FPC_LIB_START:
.type _haltproc,@function
_haltproc:
_haltproc2: # GAS <= 2.15 bug: generates larger jump if a label is exported
.globl FPC_SHARED_LIB_EXIT
.type FPC_SHARED_LIB_EXIT,@function
FPC_SHARED_LIB_EXIT:
call lib_exit
xorl %eax,%eax
incl %eax /* eax=1, exit call */
movzwl operatingsystem_result,%ebx

View File

@ -46,6 +46,7 @@ procedure libc_setfpucw; external name '__setfpucw';
procedure libc_start_main; external name '__libc_start_main';
procedure PASCALMAIN; external name 'PASCALMAIN';
Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
{******************************************************************************
C library start/halt
@ -53,38 +54,102 @@ procedure PASCALMAIN; external name 'PASCALMAIN';
{$asmmode ATT}
procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
var
_ebx: LongInt;
_ecx: LongInt;
_libc_init_proc: LongInt;
asm
{ First locate the start of the environment variables }
popl %ecx { Get argc in ecx }
movl %esp,%ebx { Esp now points to the arguments }
{$ifdef FPC_PIC}
movl %esp,_ebx { Points to the arguments }
movl %ecx,_ecx
{$else FPC_PIC}
movl %esp,%ebx { Points to the arguments }
{$endif FPC_PIC}
leal 4(%esp,%ecx,4),%eax { The start of the environment is: esp+4*eax+8 }
andl $0xfffffff8,%esp { Align stack }
movl %eax,operatingsystem_parameter_envp { Move the environment pointer }
movl %ecx,operatingsystem_parameter_argc { Move the argument counter }
movl %ebx,operatingsystem_parameter_argv { Move the argument pointer }
{$ifdef FPC_PIC}
pushl %ecx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
movl libc_environ@GOT(%ebx),%ecx
movl %eax,(%ecx)
pushl %eax
movl operatingsystem_parameter_argc@GOT(%ebx),%ecx
movl _ecx,%eax
movl %eax,(%ecx)
movl operatingsystem_parameter_argv@GOT(%ebx),%ecx
movl _ebx,%eax
movl %eax,(%ecx)
popl %eax
popl %ecx
movl _ebx,%ebx
{$else FPC_PIC}
movl %eax,operatingsystem_parameter_envp { Move the environment pointer }
movl %ecx,operatingsystem_parameter_argc { Move the argument counter }
movl %ebx,operatingsystem_parameter_argv { Move the argument pointer }
movl %eax,libc_environ { libc environ }
{$endif FPC_PIC}
movl %eax,libc_environ { libc environ }
pushl %eax
pushl %ebx
pushl %ecx
call libc_init { init libc }
movzwl libc_fpu_control,%eax
{$ifdef FPC_PIC}
pushl %ecx
pushl %ebx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl libc_init_proc@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_libc_init_proc
popl %ebx
popl %ecx
{$else FPC_PIC}
movzwl libc_fpu_control,%eax
{$endif FPC_PIC}
pushl %eax
call libc_setfpucw
popl %eax
pushl $libc_fini_proc
call libc_atexit
popl %eax
call libc_init_proc
{$ifdef FPC_PIC}
call _libc_init_proc
{$else FPC_PIC}
call libc_init_proc
{$endif FPC_PIC}
popl %eax
popl %eax
{ Save initial stackpointer }
movl %esp,initialstkptr
{$ifdef FPC_PIC}
pushl %ecx
pushl %ebx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ecx
movl %esp,(%ecx)
popl %ebx
popl %ecx
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
xorl %ebp,%ebp
call PASCALMAIN { start the program }
@ -93,12 +158,26 @@ end;
procedure _FPC_libc_haltproc; assembler; nostackframe; public name '_haltproc';
asm
.Lhaltproc:
{$if sizeof(ExitCode)=2}
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
{$else}
mov ExitCode,%ebx
{$endif}
{$endif}
{$endif FPC_PIC}
pushl %ebx
call libc_exit
xorl %eax,%eax
incl %eax { eax=1, exit call }

View File

@ -33,83 +33,166 @@
argc <--- esp
}
{$asmmode att}
var
libc21_fpc_ret, libc21_fpc_ret_ebx, libc21_fpc_ret_ebp: ptrint; { return address to libc }
dlexitproc: pointer; { atexit from loader }
procedure libc_exit; external name '__libc_exit';
procedure libc_init; external name '__libc_init';
procedure libc_setfpucw; external name '__setfpucw';
procedure libc_start_main; external name '__libc_start_main';
procedure PASCALMAIN; external name 'PASCALMAIN';
{ Some helpers }
procedure _init_fini_dummy; compilerproc; nostackframe; assembler;
asm
ret
end;
{******************************************************************************
glibc 2.1 library start/halt
glibc 2.1 lib + profiling start/halt
******************************************************************************}
{$asmmode ATT}
procedure _FPC_libc21_start; assembler; nostackframe; public name '_start';
asm
xorl %ebp,%ebp
{ First locate the start of the environment variables }
popl %esi
movl %eax,%edi
popl %ecx { Get argc in ecx }
movl %esp,%ebx { Points to the arguments }
movl %esi,%eax
incl %eax
shll $2,%eax
addl %esp,%eax
movl %esp,%ebx { Esp now points to the arguments }
leal 4(%esp,%ecx,4),%eax { The start of the environment is: esp+4*eax+4 }
andl $0xfffffff8,%esp { Align stack }
movl %eax,operatingsystem_parameter_envp { Move the environment pointer }
movl %esi,operatingsystem_parameter_argc { Move the argument counter }
movl %ebx,operatingsystem_parameter_argv { Move the argument pointer }
{$ifdef FPC_PIC}
pushl %edx
pushl %ebx
pushl %ecx
call .Lpiclab
.Lpiclab:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
xorl %ebp,%ebp
pushl %edi
pushl %esp
pushl %edx
pushl $.Lfini_dummy
pushl $.Linit_dummy
pushl %ebx
pushl %esi
pushl $.Lmain
call libc_start_main
.Linit_dummy:
.Lfini_dummy:
ret
movl dlexitproc@GOT(%ebx),%ecx
movl %edx,(%ecx)
{ fake main routine which will be run from libc }
.Lmain:
{ save return address }
popl %eax
movl %eax,libc21_fpc_ret
movl %ebx,libc21_fpc_ret_ebx
movl %ebp,libc21_fpc_ret_ebp
pushl %eax
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
movl operatingsystem_parameter_argc@GOT(%ebx),%edx
popl %ecx
movl %ecx,(%edx)
movl operatingsystem_parameter_argv@GOT(%ebx),%edx
popl %ebx
movl %ebx,(%edx)
popl %edx
{$else FPC_PIC}
movl %edx, dlexitproc
movl %eax,operatingsystem_parameter_envp
movl %ecx,operatingsystem_parameter_argc
movl %ebx,operatingsystem_parameter_argv
{$endif FPC_PIC}
{ Save initial stackpointer }
movl %esp,initialstkptr
{$ifdef FPC_PIC}
pushl %ebx
call .Lpiclab2
.Lpiclab2:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ebx
movl %esp,(%ebx)
popl %ebx
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
{ start the program }
xorl %ebp,%ebp
call PASCALMAIN
hlt
{ int __libc_start_main(
int *(main) (int, char * *, char * *),
int argc,
char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)); }
pushl %ebp { padding }
pushl %esp { stack_end }
pushl %edx { function to be registered with
atexit(), passed by loader }
pushl $_init_fini_dummy
pushl $_init_fini_dummy
pushl %ebx { Push second argument: argv. }
pushl %ecx { Push first argument: argc. }
pushl $PASCALMAIN
call libc_start_main
hlt
end;
procedure _FPC_libc21_haltproc; assembler; nostackframe; public name '_haltproc';
asm
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%eax
{$else}
mov ExitCode,%eax
{$endif}
.Lhaltproc:
{$ifdef FPC_PIC}
call .Lpiclab
.Lpiclab:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl dlexitproc@GOT(%ebx),%eax
movl (%eax),%eax
{$else FPC_PIC}
movl dlexitproc,%eax
{$endif FPC_PIC}
testl %eax,%eax
je .Lnodlexitproc
call *%eax
.Lnodlexitproc:
movl syscall_nr_exit_group,%eax
movl libc21_fpc_ret,%edx { return to libc }
movl libc21_fpc_ret_ebp,%ebp
movl libc21_fpc_ret_ebx,%ebx
push %edx
ret
{$ifdef FPC_PIC}
call .Lpiclab2
.Lpiclab2:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
int $0x80
movl syscall_nr_exit,%eax
{$ifdef FPC_PIC}
call .Lpiclab3
.Lpiclab3:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
int $0x80
jmp .Lhaltproc
end;

View File

@ -33,116 +33,224 @@
argc <--- esp
}
var
gmon_etext: longint; external name '_etext';
gmon_start: longint; external name '_start';
gmon_mcleanup: procedure; external name '_mcleanup';
libc21_fpc_ret, libc21_fpc_ret_ebx: ptrint; { return address to libc }
libc21_fpc_ret_esi, libc21_fpc_ret_edi: ptrint;
gmon_monstarted: longint = 0;
{
This file is part of the Free Pascal run time library.
Copyright (c) 2005 by Michael Van Canneyt, Peter Vreman,
& Daniel Mantione, members of the Free Pascal development team.
procedure gmon_monstartup; external name 'monstartup';
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.
**********************************************************************}
{
Linux ELF startup code for Free Pascal
Stack layout at program start:
nil
envn
....
.... ENVIRONMENT VARIABLES
env1
env0
nil
argn
....
.... COMMAND LINE OPTIONS
arg1
arg0
argc <--- esp
}
{$asmmode att}
{ Some helpers }
{$ifdef FPC_PIC}
function fpc0geteipasebx : pointer; compilerproc; nostackframe; assembler;
asm
movl (%esp),%ebx
ret
end;
{$endif FPC_PIC}
procedure _init_fini_dummy; compilerproc; nostackframe; assembler;
asm
ret
end;
procedure gmon_mcleanup; cdecl; external name '_mcleanup';
procedure gmon_monstartup (main,etext : pointer);cdecl;external name 'monstartup';
procedure libc_atexit; external name 'atexit';
procedure libc_exit; external name '__libc_exit';
procedure libc_init; external name '__libc_init';
procedure libc_setfpucw; external name '__setfpucw';
procedure libc_start_main; external name '__libc_start_main';
procedure PASCALMAIN; external name 'PASCALMAIN';
{******************************************************************************
glibc 2.1 lib + profiling start/halt
******************************************************************************}
{$asmmode ATT}
var
dlexitproc: pointer; { atexit from loader }
procedure _FPC_libc21_gprof_gmon_start; assembler; nostackframe;
asm
pushl %ebp
movl gmon_monstarted,%eax
leal 0x1(%eax),%edx
movl %esp,%ebp
movl %edx,gmon_monstarted
testl %eax,%eax
jnz .Lnomonstart
pushl $gmon_start
pushl $gmon_etext { Initialize gmon }
call gmon_monstartup
addl $8,%esp
pushl $gmon_mcleanup
call libc_atexit
addl $4,%esp
.Lnomonstart:
movl %ebp,%esp
popl %ebp
ret
gmon_start : record end;external name 'PASCALMAIN';
gmon_etext : record end;external name '_etext';
gmon_monstarted: longint = 0;
{******************************************************************************
Process start/halt
******************************************************************************}
procedure _FPC_libc21_gprof_gmon_start; public name '_FPC_libc21_gprof_gmon_start';
begin
if gmon_monstarted=0 then
begin
inc(gmon_monstarted);
gmon_monstartup(@gmon_start,@gmon_etext);
end;
PASCALMAIN;
end;
procedure _FPC_libc21_gprof_start; assembler; nostackframe; public name '_start';
asm
xorl %ebp,%ebp
{ First locate the start of the environment variables }
popl %esi
movl %eax,%edi
movl %esp,%ebx { Points to the arguments }
movl %esi,%eax
incl %eax
shll $2,%eax
addl %esp,%eax
popl %ecx { Get argc in ecx }
movl %esp,%ebx { Esp now points to the arguments }
leal 4(%esp,%ecx,4),%eax { The start of the environment is: esp+4*eax+4 }
andl $0xfffffff8,%esp { Align stack }
movl %eax,operatingsystem_parameter_envp { Move the environment pointer }
movl %esi,operatingsystem_parameter_argc { Move the argument counter }
movl %ebx,operatingsystem_parameter_argv { Move the argument pointer }
{$ifdef FPC_PIC}
pushl %edx
pushl %ebx
pushl %ecx
call fpc0geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl %edi,%eax
xorl %ebp,%ebp
pushl %eax
pushl %esp
pushl %edx
pushl $.Lfini_dummy
pushl $.Linit_dummy
pushl %ebx
pushl %esi
pushl $.Lcmain
call libc_start_main
.Linit_dummy:
.Lfini_dummy:
ret
movl dlexitproc@GOT(%ebx),%ecx
movl %edx,(%ecx)
{ fake main routine which will be run from libc }
.Lcmain:
{ save return address }
popl %eax
movl %eax,libc21_fpc_ret
movl %ebx,libc21_fpc_ret_ebx
movl %esi,libc21_fpc_ret_esi
movl %edi,libc21_fpc_ret_edi
pushl %eax
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
call _FPC_libc21_gprof_gmon_start
movl operatingsystem_parameter_argc@GOT(%ebx),%edx
popl %ecx
movl %ecx,(%edx)
movl operatingsystem_parameter_argv@GOT(%ebx),%edx
popl %ebx
movl %ebx,(%edx)
popl %edx
{$else FPC_PIC}
movl %edx, dlexitproc
movl %eax,operatingsystem_parameter_envp
movl %ecx,operatingsystem_parameter_argc
movl %ebx,operatingsystem_parameter_argv
{$endif FPC_PIC}
{ Save initial stackpointer }
movl %esp,initialstkptr
{$ifdef FPC_PIC}
pushl %ebx
call fpc0geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ebx
movl %esp,(%ebx)
popl %ebx
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
{ start the program }
call PASCALMAIN
hlt
{ int __libc_start_main(
int *(main) (int, char * *, char * *),
int argc,
char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)); }
pushl %ebp { padding }
pushl %esp { stack_end }
pushl %edx { function to be registered with
atexit(), passed by loader }
pushl $_init_fini_dummy
pushl $_init_fini_dummy
pushl %ebx { Push second argument: argv. }
pushl %ecx { Push first argument: argc. }
pushl $_FPC_libc21_gprof_gmon_start
call libc_start_main
hlt
end;
procedure _FPC_libc21_gprof_haltproc; assembler; nostackframe; public name '_haltproc';
asm
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%eax
{$else}
mov ExitCode,%eax
{$endif}
procedure _FPC_libc21_gprof_haltproc(e:longint);cdecl;public name '_haltproc';
begin
if gmon_monstarted=1 then
begin
dec(gmon_monstarted);
gmon_mcleanup;
end;
asm
.Lhaltproc:
{$ifdef FPC_PIC}
call fpc0geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl dlexitproc@GOT(%ebx),%eax
movl (%eax),%eax
{$else FPC_PIC}
movl dlexitproc,%eax
{$endif FPC_PIC}
testl %eax,%eax
je .Lnodlexitproc
call *%eax
.Lnodlexitproc:
movl syscall_nr_exit_group,%eax
movl libc21_fpc_ret,%edx { return to libc }
movl libc21_fpc_ret_ebx,%ebx
movl libc21_fpc_ret_esi,%esi
movl libc21_fpc_ret_edi,%edi
push %edx
ret
{$ifdef FPC_PIC}
call fpc0geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
int $0x80
movl syscall_nr_exit,%eax
{$ifdef FPC_PIC}
call fpc0geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
int $0x80
jmp .Lhaltproc
end;
end;

View File

@ -35,18 +35,19 @@
procedure PASCALMAIN; external name 'PASCALMAIN';
function get1eipasebx : pointer; compilerproc; nostackframe; assembler;
asm
movl (%esp),%ebx
ret
end;
{******************************************************************************
Shared library start/halt
******************************************************************************}
{$asmmode ATT}
procedure _FPC_shared_lib_start(argc : dword;argv,envp : pointer); cdecl; public name '_FPC_SHARED_LIB_START_LOCAL'; public name '_start';
procedure _FPC_shared_lib_start(argc : dword;argv,envp : pointer); cdecl; public name 'FPC_SHARED_LIB_START'; public name '_start';
begin
{ we've to discuss about the use of this ;) }
asm
{ Save initial stackpointer }
movl %esp,initialstkptr
end;
operatingsystem_parameter_argc:=argc; { Copy the argument count }
operatingsystem_parameter_argv:=argv; { Copy the argument pointer }
@ -54,53 +55,45 @@ begin
IsLibrary:=true;
asm
{ Save initial stackpointer }
{$ifdef FPC_PIC}
call get1eipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ecx
movl %esp,(%ecx)
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
end;
PASCALMAIN;
end;
{$ifndef VER2_0}
Procedure lib_exit; external name 'FPC_LIB_EXIT';
{ this hack is needed so we can make the reference below to _FPC_shared_lib_start }
{ local in compiler/systems/t_linux.pas }
procedure _FPC_SHARED_LIB_START_LOCAL(argc : dword;argv,envp : pointer); cdecl; external;
procedure initdummy; assembler; nostackframe;
label
FPC_LIB_START;
procedure _FPC_shared_lib_haltproc; assembler; nostackframe; public name 'FPC_SHARED_LIB_EXIT'; public name '_haltproc';
asm
.init
.align 16
.globl FPC_LIB_START
// .type FPC_LIB_START,@function
FPC_LIB_START:
{$ifdef FPC_PIC}
jmp _FPC_SHARED_LIB_START_LOCAL@PLT
{$else FPC_PIC}
jmp _FPC_SHARED_LIB_START_LOCAL
{$endif FPC_PIC}
.text
end;
{$endif VER_2_0}
procedure _FPC_shared_lib_haltproc; assembler; nostackframe; public name '_haltproc';
asm
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
{$endif}
.Lhaltproc:
call lib_exit
{$ifdef FPC_PIC}
call get1eipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
xorl %eax,%eax
incl %eax { eax=1, exit call }
{$ifdef FPC_PIC}
pushl %ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$endif}
int $0x80
jmp .Lhaltproc
popl %ebx
end;

View File

@ -90,11 +90,23 @@ end;
procedure _FPC_proc_gprof_haltproc; assembler; nostackframe; public name '_haltproc';
asm
.Lhaltproc:
{$if sizeof(ExitCode)=2}
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
{$else}
mov ExitCode,%ebx
{$endif}
{$endif}
{$endif FPC_PIC}
pushl %ebx
call libc_exit { call libc exit, this will write the gmon.out }
movl syscall_nr_exit_group,%eax

View File

@ -35,10 +35,16 @@
procedure PASCALMAIN; external name 'PASCALMAIN';
function fpc_geteipasebx : pointer; compilerproc; nostackframe; assembler;
asm
movl (%esp),%ebx
ret
end;
{******************************************************************************
Process start/halt
******************************************************************************}
{$asmmode ATT}
{$asmmode att}
var
dlexitproc: pointer;
@ -46,27 +52,54 @@ var
procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
asm
{ First locate the start of the environment variables }
popl %ecx { Get argc in ecx }
movl %esp,%ebx { Esp now points to the arguments }
leal 4(%esp,%ecx,4),%eax { The start of the environment is: esp+4*eax+4 }
andl $0xfffffff8,%esp { Align stack }
movl %eax,operatingsystem_parameter_envp
movl %ecx,operatingsystem_parameter_argc
movl %ebx,operatingsystem_parameter_argv
{$ifdef FPC_PIC}
pushl %ebx
pushl %ecx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl %edx, dlexitproc
movl dlexitproc@GOT(%ebx),%ecx
movl %edx,(%ecx)
fninit { initialize fpu }
fwait
fldcw Default8087CW
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
{ Initialize gs for thread local storage }
// movw %ds,%ax
// movw %ax,%gs
movl operatingsystem_parameter_argc@GOT(%ebx),%edx
popl %ecx
movl %ecx,(%edx)
movl operatingsystem_parameter_argv@GOT(%ebx),%edx
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
{$endif FPC_PIC}
{ Initialize FPU }
call SysResetFPU
{ Save initial stackpointer }
movl %esp,initialstkptr
{$ifdef FPC_PIC}
pushl %ebx
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ebx
movl %esp,(%ebx)
popl %ebx
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
xorl %ebp,%ebp
call PASCALMAIN
@ -74,25 +107,59 @@ end;
procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc';
asm
.Lhaltproc:
movl dlexitproc,%eax
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl dlexitproc@GOT(%ebx),%eax
movl (%eax),%eax
{$else FPC_PIC}
movl dlexitproc,%eax
{$endif FPC_PIC}
testl %eax,%eax
je .Lnodlexitproc
call *%eax
.Lnodlexitproc:
movl syscall_nr_exit_group,%eax
{$if sizeof(ExitCode)=2}
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
{$else}
mov ExitCode,%ebx
{$endif}
{$endif}
{$endif FPC_PIC}
int $0x80
movl syscall_nr_exit,%eax
{$if sizeof(ExitCode)=2}
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
{$else}
mov ExitCode,%ebx
{$endif}
{$endif}
{$endif FPC_PIC}
int $0x80
jmp .Lhaltproc
end;

View File

@ -40,75 +40,138 @@
}
procedure libc_init; external name '__uClibc_init';
procedure libc_fini; external name '__uClibc_fini';
procedure libc_exit; external name '_exit';
procedure libc_main; external name '__uClibc_main';
var
dlexitproc: pointer; { atexit from loader }
procedure uclibc_init; external name '__uClibc_init';
procedure uclibc_fini; external name '__uClibc_fini';
procedure uclibc_exit; external name '_exit';
procedure uclibc_main; external name '__uClibc_main';
procedure PASCALMAIN; external name 'PASCALMAIN';
{ Some helpers }
{$ifdef FPC_PIC}
function get3eipasebx : pointer; compilerproc; nostackframe; assembler;
asm
movl (%esp),%ebx
ret
end;
{$endif FPC_PIC}
procedure _init_fini_dummy; compilerproc; nostackframe; assembler;
asm
ret
end;
{******************************************************************************
C library start/halt
glibc 2.1 lib + profiling start/halt
******************************************************************************}
{$asmmode ATT}
procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
procedure _FPC_libc21_start; assembler; nostackframe; public name '_start';
asm
xorl %ebp,%ebp { clear outer most frame for backtraces }
popl %esi { Get argc in ecx }
movl %esp,%ecx { Esp now points to the arguments }
leal 4(%esp,%esi,4),%eax { The start of the environment is: esp+4*eax+8 }
andl $0xfffffff0,%esp { Align stack }
pushl %eax { push garbage, so we push 32 bytes in total }
xorl %ebp,%ebp
{ First locate the start of the environment variables }
movl %eax,operatingsystem_parameter_envp { save the environment pointer }
movl %esi,operatingsystem_parameter_argc { save the argument counter }
movl %ecx,operatingsystem_parameter_argv { save the argument pointer }
movl %esp,initialstkptr { save initial stack pointer }
popl %ecx { Get argc in ecx }
pushl %esp { provide highest stack address to C library }
pushl %edx { push address of shared library finalization }
movl %esp,%ebx { Esp now points to the arguments }
leal 4(%esp,%ecx,4),%eax { The start of the environment is: esp+4*eax+4 }
andl $0xfffffff8,%esp { Align stack }
{$ifdef PIC}
call .L0
.L0:
pop %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx
{$ifdef FPC_PIC}
pushl %edx
pushl %ebx
pushl %ecx
call get3eipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
pushl _fini@GOT(%ebx) { push address of entry points }
pushl _init@GOT(%ebx)
movl dlexitproc@GOT(%ebx),%ecx
movl %edx,(%ecx)
pushl %ecx { push argv }
pushl %esi { push argc }
pushl $PASCALMAIN { push fpc main procedure }
call libc_main { let fpc main be called from libc startup }
{$else}
pushl $libc_fini { push address of entry points }
pushl $libc_init
movl operatingsystem_parameter_envp@GOT(%ebx),%ecx
movl %eax,(%ecx)
pushl %ecx { push argv }
pushl %esi { push argc }
movl operatingsystem_parameter_argc@GOT(%ebx),%edx
popl %ecx
movl %ecx,(%edx)
pushl $PASCALMAIN { push fpc main procedure }
call libc_main { let fpc main be called from libc startup }
{$endif}
movl operatingsystem_parameter_argv@GOT(%ebx),%edx
popl %ebx
movl %ebx,(%edx)
popl %edx
{$else FPC_PIC}
movl %edx, dlexitproc
movl %eax,operatingsystem_parameter_envp
movl %ecx,operatingsystem_parameter_argc
movl %ebx,operatingsystem_parameter_argv
{$endif FPC_PIC}
{ Save initial stackpointer }
{$ifdef FPC_PIC}
pushl %ebx
call get3eipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl initialstkptr@GOT(%ebx),%ebx
movl %esp,(%ebx)
popl %ebx
{$else FPC_PIC}
movl %esp,initialstkptr
{$endif FPC_PIC}
{ int __libc_start_main(
int *(main) (int, char * *, char * *),
int argc,
char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)); }
pushl %ebp { padding }
pushl %esp { stack_end }
pushl %edx { function to be registered with
atexit(), passed by loader }
pushl $_init_fini_dummy
pushl $_init_fini_dummy
pushl %ebx { Push second argument: argv. }
pushl %ecx { Push first argument: argc. }
pushl $PASCALMAIN
call uclibc_main
hlt
end;
procedure _FPC_libc_haltproc; assembler; nostackframe; public name '_haltproc';
procedure _FPC_libc21_haltproc; assembler; nostackframe; public name '_haltproc';
asm
.Lhaltproc:
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$ifdef FPC_PIC}
call get3eipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl ExitCode@GOT(%ebx),%ebx
{$if sizeof(ExitCode)=2}
movzwl (%ebx),%ebx
{$else}
mov (%ebx),%ebx
{$endif}
{$else FPC_PIC}
{$if sizeof(ExitCode)=2}
movzwl ExitCode,%ebx
{$else}
mov ExitCode,%ebx
{$endif}
{$endif FPC_PIC}
pushl %ebx
call libc_exit
call uclibc_exit
xorl %eax,%eax
incl %eax { eax=1, exit call }
popl %ebx
int $0x80
jmp .Lhaltproc
end;
end;

View File

@ -77,17 +77,34 @@ end;
Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
function FpSysCall(sysnr:TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL0'];
function FpSysCall(sysnr:TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL0'];
{ Var sysnr located in register eax }
asm
// movl sysnr,%eax
cmp $0, sysenter_supported
jne .LSysEnter
int $0x80
push %ebx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
int $0x80
jmp .LTail
.LSysEnter:
call psysinfo
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
call *%ecx
{$else FPC_PIC}
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ecx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -96,21 +113,40 @@ asm
.LSyscOK:
end;
function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL1'];
{ Var sysnr located in register eax
Var param1 located in register edx }
asm
movl %ebx,%ecx
// movl sysnr,%eax
movl %edx,%ebx
push %ebx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
int $0x80
jmp .LTail
.LSysEnter:
call psysinfo
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %edx,%ebx // param1
call *%ecx
{$else FPC_PIC}
movl %edx,%ebx // param1
call psysinfo
{$endif FPC_PIC}
.LTail:
movl %ecx,%ebx
pop %ecx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -125,17 +161,37 @@ function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler; regis
Var param2 located in register ecx }
asm
push %ebx
// movl sysnr,%eax
movl %edx,%ebx
// movl param2,%ecx
push %edx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
int $0x80
jmp .LTail
.LSysEnter:
call psysinfo
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl %edx,%ebx // param1
movl (%ecx),%edx
pop %ecx // param2
call *%edx
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ebx
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -149,20 +205,45 @@ function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;
Var param1 located in register edx
Var param2 located in register ecx
Var param3 located at ebp+20 }
var
_psysinfo: LongWord;
asm
push %ebx
// movl sysnr,%eax
movl %edx,%ebx
// movl param2,%ecx
movl param3,%edx
push %edx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ebx
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -177,23 +258,48 @@ function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; asse
Var param2 located in register ecx
Var param3 located at ebp+20
Var param4 located at ebp+16 }
var
_psysinfo: LongWord;
asm
push %ebx
push %esi
// movl sysnr,%eax
movl %edx,%ebx
// movl param2,%ecx
movl param3,%edx
movl param4,%esi
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
jne .LSysEnter
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
int $0x80
jmp .LTail
jmp .LTail
.LSysEnter:
call psysinfo
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %esi
pop %ebx
pop %esi
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -209,26 +315,55 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysRes
Var param3 located at ebp+20
Var param4 located at ebp+16
Var param5 located at ebp+12 }
var
_psysinfo: LongWord;
asm
push %ebx
push %edx
push %esi
push %edi
// movl sysnr,%eax
movl %edx,%ebx
// movl param2,%ecx
movl param3,%edx
movl param4,%esi
movl param5,%edi
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
int $0x80
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %edi
pop %esi
pop %ebx
pop %edi
pop %esi
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
@ -245,29 +380,60 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6: TSysParam):T
Var param4 located at ebp+16
Var param5 located at ebp+12
Var param6 located at ebp+8 }
var
_psysinfo: LongWord;
asm
push %ebx
push %edx
push %esi
push %edi
push %ebp
// movl sysnr,%eax
movl %edx,%ebx
// movl param2,%ecx
movl param3,%edx
movl param4,%esi
movl param5,%edi
movl param6,%ebp
push %ebp
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ebp
pop %edi
pop %esi
pop %ebx
pop %ebp
pop %edi
pop %esi
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax

View File

@ -19,9 +19,9 @@
.globl _startlib
.type _startlib,@function
_startlib:
.globl FPC_LIB_START
.type FPC_LIB_START,@function
FPC_LIB_START:
.globl FPC_SHARED_LIB_START
.type FPC_SHARED_LIB_START,@function
FPC_SHARED_LIB_START:
|
| The args and envs are not tested yet
|
@ -36,6 +36,9 @@ FPC_LIB_START:
.globl _haltproc
.type _haltproc,@function
haltproc:
.globl FPC_SHARED_LIB_EXIT
.type FPC_SHARED_LIB_EXIT,@function
FPC_SHARED_LIB_EXIT:
moveq.l #1,%d0
move.w U_SYSLINUX_EXITCODE,%d1
trap #0

View File

@ -35,9 +35,9 @@
*/
.section .init
.align 16
.globl FPC_LIB_START
.type FPC_LIB_START,@function
FPC_LIB_START:
.globl FPC_SHARED_LIB_START
.type FPC_SHARED_LIB_START,@function
FPC_SHARED_LIB_START:
jmp _startlib@PLT
.text
@ -68,6 +68,10 @@ _startlib:
.globl _haltproc
.type _haltproc,@function
_haltproc:
.globl FPC_SHARED_LIB_EXIT
.type FPC_SHARED_LIB_EXIT,@function
FPC_SHARED_LIB_EXIT:
call FPC_LIB_EXIT@PLT
movl $231,%eax /* exit_group call */
movq operatingsystem_result@GOTPCREL(%rip),%rbx
movzwl (%rbx),%edi