Browse Source

* attempt at crt1 translation to get freebsd 12 running.

git-svn-id: trunk@44289 -
marco 5 years ago
parent
commit
7b4ef925f0

+ 2 - 0
.gitattributes

@@ -10603,6 +10603,7 @@ rtl/freebsd/Makefile.fpc svneol=native#text/plain
 rtl/freebsd/buildrtl.lpi svneol=native#text/plain
 rtl/freebsd/buildrtl.pp svneol=native#text/plain
 rtl/freebsd/console.pp svneol=native#text/plain
+rtl/freebsd/csucommon/ignore_init.inc svneol=native#text/plain
 rtl/freebsd/errno.inc svneol=native#text/plain
 rtl/freebsd/errnostr.inc svneol=native#text/plain
 rtl/freebsd/freebsd.pas -text svneol=unset#text/plain
@@ -10638,6 +10639,7 @@ rtl/freebsd/x86_64/cprt0.as svneol=native#text/plain
 rtl/freebsd/x86_64/dllprt0.as svneol=native#text/plain
 rtl/freebsd/x86_64/gprt0.as svneol=native#text/plain
 rtl/freebsd/x86_64/prt0.as svneol=native#text/plain
+rtl/freebsd/x86_64/reloc.inc svneol=native#text/plain
 rtl/freebsd/x86_64/si_c.inc svneol=native#text/plain
 rtl/freebsd/x86_64/sighnd.inc svneol=native#text/plain
 rtl/gba/Makefile svneol=native#text/plain

+ 208 - 0
rtl/freebsd/csucommon/ignore_init.inc

@@ -0,0 +1,208 @@
+{
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2012 Konstantin Belousov <[email protected]>
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * Parts of this software was developed by Konstantin Belousov
+ * <[email protected]> under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Translated into Pascal by Marco van de Voort 
+}
+
+//#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: releng/12.1/lib/csu/common/ignore_init.c 339351 2018-10-13 23:52:55Z kib $");
+
+//#include <sys/param.h>
+//#include <sys/elf.h>
+//#include <sys/elf_common.h>
+
+//#include "notes.h"
+
+// replaced by pascalmain in si_c.pp
+//function cmain(argc:longint;argv:ppchar;env:ppchar):longint; cdecl; external name '_main';
+
+
+Type TInitProc     = procedure(argc:longint;argv:ppchar;env:ppchar); cdecl;
+     PInitProc     = ^TInitProc;
+     TCleanupProc  = procedure; cdecl;
+     PCleanupProc  = ^TCleanupProc;
+
+procedure atexit(prc:TCleanupProc); cdecl external name 'atexit';
+procedure cleanup(prc:TCleanupProc); cdecl external name 'cleanup';
+
+var
+  environ : ppchar; cvar; public  name '__environ';
+  _Dynamic  : longint; weakexternal name '_DYNAMIC';
+
+var
+    preinit_array_start  : PInitProc; external name '__preinit_array_start';
+    preinit_array_end    : PInitProc; external name '__preinit_array_end';
+    init_array_start     : PInitProc; external name '__init_array_start';
+    init_array_end       : PInitProc; external name '__init_array_end';
+    fini_array_start     : PCleanupProc; external name '__fini_array_start';
+    fini_array_end       : PCleanupProc; external name '__fini_array_end';
+
+
+procedure _fini; cdecl; external name '_fini';
+procedure _init; cdecl; external name '_init';
+procedure libc_exit(exitcode:longint);cdecl; external name 'exit';
+
+Type
+     // I only doublechecked these for don't know how these records are defined, but they are resp. 24 and 16 byte on 64-bit
+     Elf_Rela = record
+      	r_offset : uint64 {Elf64_Addr};	 { Location to be relocated. }
+      	r_info   : uint64 {Elf64_Xword};	 { Relocation type and symbol index. }
+      	r_addend : uint64 {Elf64_Sxword}; { Addend. }
+     end;
+     PElf_Rela = ^Elf_Rela;
+     Elf_Rel  = record
+      	r_offset : uint64 {Elf64_Addr};	 { Location to be relocated. }
+      	r_info   : uint64 {Elf64_Xword};	 { Relocation type and symbol index. }
+       end;
+     PElf_Rel = ^Elf_Rel;
+
+{$if defined(CRT_IRELOC_RELA)}
+var
+  rela_iplt_start : Elf_rela; weakexternal name '__rela_iplt_start';
+  rela_iplt_end   : Elf_rela; weakexternal name '__rela_iplt_end';
+
+{$include reloc.inc}
+
+procedure process_irelocs; cdecl;
+var p,p2 : pElf_Rela;
+begin
+  p:=@rela_iplt_start;
+  p2:=@rela_iplt_end;
+  while (p<p2) do
+    begin
+       crt1_handle_rela(p);
+       inc(p);
+    end;
+end;
+{$elseif defined(CRT_IRELOC_REL)}
+
+var
+  rel_iplt_start : Elf_Rel; weakexternal name '__rel_iplt_start';
+  rel_iplt_end   : Elf_Rel; weakexternal name '__rel_iplt_end';
+
+  {$include reloc.inc}
+
+procedure process_irelocs; cdecl;
+var p,p2 : pElf_Rel;
+begin
+  p:=@rel_iplt_start;
+  p2:=@rel_iplt_end;
+  while (p<p2) do
+    begin
+       crt1_handle_rel(p)
+       inc(p);
+    end;
+end;
+
+{$elseif defined(CRT_IRELOC_SUPPRESS)}
+{$else}
+{$error 'Define platform reloc type'}
+{$endif}
+
+
+procedure finalizer; cdecl;
+var
+  fn : TCleanupProc;
+  n,array_size : ptruint; // actually: size_t;
+begin
+  array_size:= fini_array_end - fini_array_start;
+  n:=array_size;
+  while n>0 do
+    begin
+      fn := fini_array_start[n - 1];
+      if assigned(fn) and (ptrint(fn)<>-1) then
+        fn();
+      dec(n);
+    end;
+ _fini();
+end;
+
+procedure handle_static_init(argc:longint;argv:ppchar;env:ppchar);  cdecl;
+var fn : TInitProc;
+    n,array_size : ptruint; // actually: size_t;
+begin
+   if assigned(@_dynamic) then
+     exit;
+   atexit(@finalizer);
+   array_size := preinit_array_end - preinit_array_start;
+   n:=0;
+   while n<array_size do
+     begin
+       fn := preinit_array_start[n];
+       if assigned(fn) and (ptrint(fn)<>-1) then
+         fn(argc,argv,env);
+       inc(n);
+     end;
+   _init();
+   n:=0;
+   while n<array_size do
+     begin
+       fn := init_array_start[n];
+       if assigned(fn) and (ptrint(fn)<>-1) then
+         fn(argc,argv,env);
+       inc(n);
+     end;
+end;
+
+procedure handle_argv(argc:longint;argv:ppchar;env:ppchar); inline;
+var
+  s: pchar;
+begin
+   if assigned(environ) then
+      environ:=env;
+   if (argc>0) and assigned(argv[0]) then
+     begin
+       progname:=argv[0];
+       s:=progname;
+       while s^<>#0 do
+          begin
+            if s^='/' then
+              progname:=@s[1];
+          inc(s);
+       end;
+     end;
+end;
+
+(*
+static const struct {
+	int32_t	namesz;
+	int32_t	descsz;
+	int32_t	type;
+	char	name[sizeof(NOTE_FREEBSD_VENDOR)];
+	uint32_t desc;
+} crt_noinit_tag __attribute__ ((section (NOTE_SECTION),
+    aligned(4))) __used = {
+	.namesz = sizeof(NOTE_FREEBSD_VENDOR),
+	.descsz = sizeof(uint32_t),
+	.type = NT_FREEBSD_NOINIT_TAG,
+	.name = NOTE_FREEBSD_VENDOR,
+	.desc = 0
+};
+
+*)

+ 1 - 1
rtl/freebsd/si_crt.pp

@@ -21,6 +21,6 @@ interface
 implementation
 
 {$i sysnr.inc}
-{$i si_crt.inc}
+{$i si_c.inc}
 
 end.

+ 2 - 0
rtl/freebsd/si_intf.inc

@@ -5,3 +5,5 @@ var
   operatingsystem_parameter_envp: ppchar; public name 'operatingsystem_parameter_envp';
   operatingsystem_parameter_argc: ptruint; public name 'operatingsystem_parameter_argc';
   operatingsystem_parameter_argv: ppchar; public name 'operatingsystem_parameter_argv';
+  progname: pchar = ''; cvar; public name '__progname';
+

+ 124 - 0
rtl/freebsd/x86_64/reloc.inc

@@ -0,0 +1,124 @@
+{-
+ * Copyright (c) 2018 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <[email protected]>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ }
+
+//#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: releng/12.1/lib/csu/amd64/reloc.c 339351 2018-10-13 23:52:55Z kib $");
+
+//#include <machine/specialreg.h>
+//#include <machine/cpufunc.h>
+
+Type
+    Elf_Addr = uint64;
+    PElf_Addr = ^Elf_Addr;
+    TElfAddrProc = function (feat1,feat2,stdextfeat1,stdextfeat2:uint32):Elf_Addr; cdecl;
+
+const  R_X86_64_IRELATIVE      = 37;
+
+procedure freebsdIdentTag;nostackframe;assembler;
+  asm
+    .section ".note.openbsd.ident", "a"
+    .p2align 2
+    .long    8
+    .long    4
+    .long    1
+    .asciz   "OpenBSD"
+    .long    0
+
+    .text
+  end;
+
+function ELF_R_TYPE(info:elf_addr):uint32;inline;
+begin
+  ELF_R_TYPE:=info and  uint32($ffffffff);
+end;
+
+{$asmmode intel}
+procedure do_cpuid(funcnr : integer; var p);
+begin
+  asm
+    mov  rax,rdi
+    cpuid
+    mov [rsi],eax
+    mov [rsi+4],ebx
+    mov [rsi+8],ecx
+    mov [rsi+12],edx
+  end['rbx']; // rbx is callee saved in sysv
+end;
+
+procedure cpuid_count(funcnr : integer;count:integer;var p);
+begin
+  asm
+    mov  rax,rdi  // funcnr
+    mov  rcx,rsi  // count
+    mov  rsi,rdx  // save pointer since cpuid destroys edx
+    cpuid
+    mov [rsi],eax
+    mov [rsi+4],ebx
+    mov [rsi+8],ecx
+    mov [rsi+12],edx
+  end['rbx'];
+end;
+
+procedure crt1_handle_rela(r : pelf_rela);
+var p : array[0..3] of uint32;
+    ptr,
+    where : PElf_Addr;
+    target  : Elf_Addr;
+    cpu_feature,
+    cpu_feature2          : uint32;
+    cpu_stdext_feature,
+    cpu_stdext_feature2   : uint32;
+begin
+        do_cpuid(1, p);
+        cpu_feature  := p[3];
+        cpu_feature2 := p[2];
+        do_cpuid(0, p);
+        if (p[0] >= 7) then
+          begin
+            cpuid_count(7, 0, p);
+            cpu_stdext_feature  := p[1];
+            cpu_stdext_feature2 := p[2];
+          end
+        else
+          begin
+            cpu_stdext_feature  := 0;
+            cpu_stdext_feature2 := 0;
+          end;
+
+        case (ELF_R_TYPE(r^.r_info)) of
+          R_X86_64_IRELATIVE:
+             begin
+                ptr :=  PElf_Addr(r^.r_addend);
+                where := PElf_Addr (r^.r_offset);
+                target := TElfAddrProc(ptr)(cpu_feature, cpu_feature2,
+                    cpu_stdext_feature, cpu_stdext_feature2);
+                where^:=target;
+              end;
+          end;
+end;
+

+ 17 - 50
rtl/freebsd/x86_64/si_c.inc

@@ -1,30 +1,20 @@
 
-Type
-    TCleanup = procedure; cdecl;
+{$define CRT_IRELOC_RELA}
 
-var 
-  environ : ppchar; cvar; public  name '__environ';
-  progname: pchar = #0#0; cvar; public name '__progname';
-  dynamic : pchar;  external name '_DYNAMIC'; // #pragma weak
-
-procedure atexit(prc:TCleanup); cdecl external name 'atexit';
-procedure cleanup(prc:TCleanup); cdecl external name 'cleanup';			
 procedure init_tls; cdecl; external name 'init_tls';
-procedure fini; cdecl; external name '_fini';
-procedure init; cdecl; external name '_init';
-procedure libc_exit(exitcode:longint);cdecl; external name 'exit';
-function  main(nrarg:longint;pp:ppchar;env:ppchar):longint; cdecl; external name 'main';
+function  cmain(nrarg:longint;pp:ppchar;env:ppchar):longint; cdecl; external name 'main';
 
 {$ifdef gcrt}
  procedure cmcleanup; cdecl; external name '_mcleanup';
  procedure monstratup(p,p2:pointer); cdecl; external name 'monstartup';
 
 var 
- eprol:longint; external name 'eprol'; 
- etext:longint; external name 'etext';
+  eprol:longint; external name 'eprol';
+  etext:longint; external name 'etext';
 {$endif}
 
-procedure start(ap:ppchar;cleanup:TCleanup);
+{$i ignore_init.inc}
+procedure start(ap:ppchar;cleanup:TCleanupProc);
 
 var argc: longint;
     argv: ppchar;
@@ -35,55 +25,32 @@ begin
   argv:=ppchar(ap[1]);
   env:=	ppchar(ap[2+argc]);
   environ:=env;
-  if (argc>0) and (argv[0]<>#0) Then
-   begin
-     progname:=argv[0];
-     s:=progname;
-     while s^<>#0 do
-        begin
-          if s^='/' then
-            progname:=@s[1];
-          inc(s);
-	end; 
-    end;
-  if assigned(pchar(@dynamic)) then // I suspect this is a trick to find
+  handle_argv(argc,argv,env);
+  if assigned(pchar(@_dynamic)) then // I suspect this is a trick to find
 				    // out runtime if we are shared
 				    // linking, so the same code can be used
 				    // for static and shared linking
     atexit(cleanup)
   else
-    init_tls;
+    begin
+       process_irelocs();
+       init_tls;
+    end;
+
   {$ifdef GCRT}
-    atexit(@_mcleanup);
+    atexit(@cmcleanup);
   {$endif}
-  atexit(@fini);
+  atexit(@_fini);
   {$ifdef GCRT}
     monstartup(@eprol,@etext);
    asm
     eprol:
    end;
   {$endif} 
-  init;
-  libc_exit(main(argc,argv,env)); // doesn't return
- asm
-     { 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 8
-    .long 4 
-    .long  1
-    .asciz "FreeBSD"
-    .align 4
-    .long	900044
-    .align 4
-    .section	.note.GNU-stack,"",@progbits
-  end;
+  handle_static_init(argc, argv, env);
+  libc_exit(cmain(argc,argv,env)); // doesn't return
 end;
 
-
-
 begin
 end.