Browse Source

* basic implementation for pure pascal programs to allocate tls space

git-svn-id: trunk@40268 -
florian 6 years ago
parent
commit
e949276d9d
3 changed files with 74 additions and 1 deletions
  1. 4 1
      rtl/linux/arm/prt0.as
  2. 1 0
      rtl/linux/arm/syscall.inc
  3. 69 0
      rtl/linux/system.pp

+ 4 - 1
rtl/linux/arm/prt0.as

@@ -107,7 +107,10 @@ _start:
         /* align sp again to 8 byte boundary, needed by eabi */
         /* align sp again to 8 byte boundary, needed by eabi */
         sub sp,sp,#4
         sub sp,sp,#4
 
 
-	/* Let the libc call main and exit with its return code.  */
+	/* Initialize TLS */
+	bl FPC_INITTLS
+
+	/* Call main program, it will never return  */
 	bl PASCALMAIN
 	bl PASCALMAIN
 
 
 	.globl  _haltproc
 	.globl  _haltproc

+ 1 - 0
rtl/linux/arm/syscall.inc

@@ -465,3 +465,4 @@ asm
   ldmfd sp!,{r4,r5,r6}
   ldmfd sp!,{r4,r5,r6}
 end;
 end;
 {$endif FPC_ABI_EABI}
 {$endif FPC_ABI_EABI}
+

+ 69 - 0
rtl/linux/system.pp

@@ -441,6 +441,75 @@ begin
     result := stklen;
     result := stklen;
 end;
 end;
 
 
+
+{$ifdef CPUARM}
+
+Function fpset_tls(p : pointer):cint;
+begin
+ Result:=do_syscall(__ARM_NR_set_tls,TSysParam(p));
+end;
+
+
+procedure InitTLS; [public,alias:'FPC_INITTLS'];
+  const
+    PT_TLS = 7;
+
+  type
+    tphdr = record
+      p_type,
+      p_offset,
+      p_vaddr,
+      p_paddr,
+      p_filesz,
+      p_memsz,
+      p_flags,
+      p_align : dword;
+    end;
+    pphdr = ^tphdr;
+
+  var
+    phdr : pphdr;
+    phnum : dword;
+    i   : integer;
+    tls : pointer;
+    auxp : ppointer;
+    found : boolean;
+  begin
+    auxp:=ppointer(envp);
+    { skip environment }
+    while assigned(auxp^) do
+     inc(auxp);
+    inc(auxp);
+    { now we are at the auxillary vector }
+    while assigned(auxp^) do
+      begin
+        case plongint(auxp)^ of
+          3:
+            phdr:=pphdr(ppointer(auxp+1)^);
+          5:
+            phnum:=pdword(auxp+1)^;
+        end;
+        inc(auxp,2);
+      end;
+    found:=false;
+    for i:=1 to phnum do
+      begin
+        if phdr^.p_type=PT_TLS then
+          begin
+            found:=true;
+            break;
+          end;
+        inc(phdr);
+      end;
+    if found then
+      begin
+        tls:=Fpmmap(nil,phdr^.p_memsz,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0);
+        fpset_tls(tls);
+      end;
+  end;
+{$endif CPUARM}
+
+
 begin
 begin
 {$if defined(i386) and not defined(FPC_USE_LIBC)}
 {$if defined(i386) and not defined(FPC_USE_LIBC)}
   InitSyscallIntf;
   InitSyscallIntf;