From eb30da60a683df9d2d27423747cc1dc1b49c6577 Mon Sep 17 00:00:00 2001 From: sergei Date: Mon, 31 Mar 2014 15:57:11 +0000 Subject: [PATCH] * x86_64-linux: fixed existing Pascal startup code (syntax only, operation not tested yet) and added missing files. git-svn-id: trunk@27414 - --- .gitattributes | 2 + rtl/linux/x86_64/si_c.inc | 35 ++++---- rtl/linux/x86_64/si_dll.inc | 61 +++++++++++++ rtl/linux/x86_64/si_g.inc | 174 ++++++++++++++++++++++++++++++++++++ rtl/linux/x86_64/si_prc.inc | 24 +++-- 5 files changed, 272 insertions(+), 24 deletions(-) create mode 100644 rtl/linux/x86_64/si_dll.inc create mode 100644 rtl/linux/x86_64/si_g.inc diff --git a/.gitattributes b/.gitattributes index f5f387c674..aafd8acd15 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8446,6 +8446,8 @@ rtl/linux/x86_64/dllprt0.as svneol=native#text/plain rtl/linux/x86_64/gprt0.as svneol=native#text/plain rtl/linux/x86_64/prt0.as svneol=native#text/plain rtl/linux/x86_64/si_c.inc svneol=native#text/plain +rtl/linux/x86_64/si_dll.inc svneol=native#text/plain +rtl/linux/x86_64/si_g.inc svneol=native#text/plain rtl/linux/x86_64/si_prc.inc svneol=native#text/plain rtl/linux/x86_64/sighnd.inc svneol=native#text/plain rtl/linux/x86_64/sighndh.inc svneol=native#text/plain diff --git a/rtl/linux/x86_64/si_c.inc b/rtl/linux/x86_64/si_c.inc index f7d66310dd..5bf0f83516 100644 --- a/rtl/linux/x86_64/si_c.inc +++ b/rtl/linux/x86_64/si_c.inc @@ -57,12 +57,13 @@ procedure main_stub; assembler; nostackframe; // stack alignment pushq %rax - movq %rax,fpc_ret - movq %rbp,fpc_ret_rbp + movq %rax,fpc_ret(%rip) + movq %rbp,fpc_ret_rbp(%rip) pushq %rax { Save initial stackpointer } - movq %rsp,__stkptr + movq initialstkptr@GOTPCREL(%rip),%rax + movq %rsp,(%rax) { start the program } xorq %rbp,%rbp @@ -71,9 +72,8 @@ procedure main_stub; assembler; nostackframe; end; -procedure ini_dummy; assembler; nostackframe - asm - ret +procedure ini_dummy; + begin end; {****************************************************************************** @@ -105,14 +105,17 @@ 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. } - movq %rsi,operatingsystem_parameter_argc - movq %rsp,operatingsystem_parameter_argv { 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) leaq 8(,%rsi,8),%rax addq %rsp,%rax - movq %rax,operatingsystem_parameter_envp + movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx + movq %rax,(%rcx) { Align the stack to a 16 byte boundary to follow the ABI. } - andq $~15, %rsp + andq $0xfffffffffffffff0, %rsp pushq %rax { Push garbage because we push 8 more bytes. } @@ -135,6 +138,7 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start'; { We need this stuff to make gdb behave itself, otherwise gdb will chokes with SIGILL when trying to debug apps. } +(* .section ".note.ABI-tag", "a" .align 4 .long 1f - 0f @@ -145,17 +149,16 @@ procedure _FPC_libc_start; assembler; nostackframe; public name '_start'; 2: .long 0 .long 2,4,0 3: .align 4 - - .section .note.GNU-stack,"",@progbits + *) end; procedure _FPC_libc_haltproc; assembler; nostackframe; public name '_haltproc'; asm - movzwq operatingsystem_result,%rax { load and save exitcode } + movq ExitCode@GOTPCREL(%rip),%rax + movzwq (%rax),%rax { load and save exitcode } - movq ___fpc_ret,%rdx { return to libc } - movq ___fpc_ret_rbp,%rbp + movq fpc_ret(%rip),%rdx { return to libc } + movq fpc_ret_rbp(%rip),%rbp pushq %rdx - ret end; diff --git a/rtl/linux/x86_64/si_dll.inc b/rtl/linux/x86_64/si_dll.inc new file mode 100644 index 0000000000..fa2bbe970c --- /dev/null +++ b/rtl/linux/x86_64/si_dll.inc @@ -0,0 +1,61 @@ +{ + This file is part of the Free Pascal run time library. + Copyright (c) 2006 by Florian Klaempfl + members of the Free Pascal development team. + + 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. + + **********************************************************************} + + +procedure PASCALMAIN; external name 'PASCALMAIN'; + +procedure _FPC_shared_lib_start(argc:dword; argv,envp:pointer); cdecl; public name 'FPC_SHARED_LIB_START'; public name '_start'; +begin + operatingsystem_parameter_argc:=argc; + operatingsystem_parameter_argv:=argv; + operatingsystem_parameter_envp:=envp; + InitialStkPtr:=get_frame; + PASCALMAIN; +end; + +{ this routine is only called when the halt() routine of the RTL embedded in + the shared library is called } +procedure _FPC_shared_lib_haltproc(e:longint); cdecl; assembler; nostackframe; public name '_haltproc'; +asm + movl e,%edi + movl $231,%eax { exit_group call } + syscall + jmp _FPC_shared_lib_haltproc +end; + +{ Define a symbol for the first piece of initialized data. } +(* .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start *) + + +(* We need this stuff to make gdb behave itself, otherwise + gdb will chokes with SIGILL when trying to debug apps. + +Makes ld choke: + .section ".note.ABI-tag", "a" + .align 4 + .long 1f - 0f + .long 3f - 2f + .long 1 +0: .asciz "GNU" +1: .align 4 +2: .long 0 + .long 2,4,0 +3: .align 4 +*) + diff --git a/rtl/linux/x86_64/si_g.inc b/rtl/linux/x86_64/si_g.inc new file mode 100644 index 0000000000..32f11f89c3 --- /dev/null +++ b/rtl/linux/x86_64/si_g.inc @@ -0,0 +1,174 @@ +{ + 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. + + 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 +} + +var + libc_environ: pchar; external name '__environ'; + libc_fpu_control: word; external name '__fpu_control'; + libc_init_proc: procedure; external name '_init'; + libc_fini_proc: procedure; external name '_fini'; + _etext: pointer; external name '_etext'; + + fpc_ret,fpc_ret_rbp : pointer; + +procedure libc_atexit; external name '__libc_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 gmon_monstartup; external name 'monstartup'; +procedure gmon_mcleanup; external name '_mcleanup'; + +procedure PASCALMAIN; external name 'PASCALMAIN'; +procedure main_stub; forward; + +procedure ini_dummy; + begin + end; + +{****************************************************************************** + C library start/halt + ******************************************************************************} + +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. } + xorq %rbp, %rbp + + { Extract the arguments as encoded on the stack and set up + the arguments for __libc_start_main (int (*main) (int, char **, char **), + int argc, char *argv, + void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end). + The arguments are passed via registers and on the stack: + main: %rdi + argc: %rsi + argv: %rdx + init: %rcx + fini: %r8 + rtld_fini: %r9 + stack_end: stack. } + + movq %rdx, %r9 { Address of the shared library termination + function. } + 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) + leaq 8(,%rsi,8),%rax + addq %rsp,%rax + movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx + movq %rax,(%rcx) + + { Align the stack to a 16 byte boundary to follow the ABI. } + andq $0xfffffffffffffff0, %rsp + + pushq %rax { Push garbage because we push 8 more bytes. } + + { Provide the highest stack address to the user code (for stacks + which grow downwards). } + pushq %rsp + + { Pass address of our own entry points to .fini and .init. } + movq $ini_dummy, %r8 + movq $ini_dummy, %rcx + + movq $main_stub, %rdi + + { Call the user's main function, and exit with its value. + But let the libc call main. } + call libc_start_main@PLT + + hlt { Crash if somehow `exit' does return. } + + { We need this stuff to make gdb behave itself, otherwise + gdb will chokes with SIGILL when trying to debug apps. + } +(* + .section ".note.ABI-tag", "a" + .align 4 + .long 1f - 0f + .long 3f - 2f + .long 1 +0: .asciz "GNU" +1: .align 4 +2: .long 0 + .long 2,4,0 +3: .align 4 +*) + end; + +procedure main_stub; assembler; nostackframe; + asm + { save return address } + popq %rax + + // stack alignment + pushq %rax + + movq %rax,fpc_ret(%rip) + movq %rbp,fpc_ret_rbp(%rip) + pushq %rax + + { Initialize gmon } + movq _etext@GOTPCREL(%rip),%rsi + movq _FPC_libc_start@GOTPCREL(%rip),%rdi + call gmon_monstartup@PLT + + movq gmon_mcleanup@GOTPCREL(%rip),%rdi + call libc_atexit@PLT + { Save initial stackpointer } + movq initialstkptr(%rip),%rax + movq %rsp,(%rax) + + { start the program } + xorq %rbp,%rbp + call PASCALMAIN@PLT + hlt + end; + +procedure _FPC_libc_haltproc; assembler; nostackframe; public name '_haltproc'; + asm + movq ExitCode@GOTPCREL(%rip),%rax + movzwq (%rax),%rax { load and save exitcode } + + movq fpc_ret(%rip),%rdx { return to libc } + movq fpc_ret_rbp(%rip),%rbp + pushq %rdx + end; diff --git a/rtl/linux/x86_64/si_prc.inc b/rtl/linux/x86_64/si_prc.inc index 5f0bcd3e0d..9161465c39 100644 --- a/rtl/linux/x86_64/si_prc.inc +++ b/rtl/linux/x86_64/si_prc.inc @@ -43,15 +43,19 @@ var procedure _FPC_proc_start; assembler; nostackframe; public name '_start'; asm popq %rsi { Pop the argument count. } - movq %rsi,operatingsystem_parameter_argc - movq %rsp,operatingsystem_parameter_argv { 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. } leaq 8(,%rsi,8),%rax addq %rsp,%rax - movq %rax,operatingsystem_parameter_envp + movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rsi + movq %rax,(%rsi) andq $0xfffffffffffffff0,%rsp { Align the stack to a 16 byte boundary to follow the ABI. } { Save initial stackpointer } - movq %rsp,__stkptr + movq initialstkptr@GOTPCREL(%rip),%rax + movq %rsp,(%rax) xorq %rbp, %rbp call PASCALMAIN @@ -59,13 +63,15 @@ procedure _FPC_proc_start; assembler; nostackframe; public name '_start'; procedure _FPC_dynamic_proc_start; assembler; nostackframe; public name '_dynamic_start'; asm - movq %rdx,dlexitproc + movq dlexitproc@GOTPCREL(%rip),%rax + movq %rdx,(%rax) jmp _FPC_proc_start end; procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc'; asm - movq dlexitproc,%rdx + movq dlexitproc@GOTPCREL(%rip),%rax + movq (%rax),%rdx testq %rdx,%rdx jz .Lhaltproc @@ -73,13 +79,15 @@ procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc'; .Lhaltproc: movl $231,%eax { exit_group call } - movzwl operatingsystem_result,%edi + movq ExitCode@GOTPCREL(%rip),%rdi + movzwl (%rdi),%edi syscall jmp .Lhaltproc { We need this stuff to make gdb behave itself, otherwise gdb will chokes with SIGILL when trying to debug apps. } +(* .section ".note.ABI-tag", "a" .align 4 .long 1f - 0f @@ -91,6 +99,6 @@ procedure _FPC_proc_haltproc; assembler; nostackframe; public name '_haltproc'; .long 2,4,0 3: .align 4 - .section .note.GNU-stack,"",@progbits + .section .note.GNU-stack,"",@progbits *) end;