Made glibc compile and run x86
authorKevin Klues <klueska@ros-dev.(none)>
Wed, 24 Mar 2010 07:49:32 +0000 (00:49 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:37 +0000 (17:35 -0700)
Environment variables now work right for dynamically-linked
programs (they didn't show up before).

TLS support has been added for x86.

tools/compilers/gcc-glibc/Makefile
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/getcwd.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.h
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/init-first.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/start.c

index 9286249..5d278c7 100644 (file)
@@ -144,7 +144,7 @@ glibc-$(GLIBC_VERSION):
        $(MAKE) .glibc-patch
 
 .glibc-patch: glibc-$(GLIBC_VERSION)
-       cd glibc-$(GLIBC_VERSION); \
+       -cd glibc-$(GLIBC_VERSION); \
        diff -ruB --unidirectional-new-file \
             ../glibc-$(GLIBC_VERSION) \
             ../glibc-$(GLIBC_VERSION)-ros \
index 2a1351e..d33e700 100644 (file)
@@ -20,6 +20,7 @@
 #include <unistd.h>
 #include <stddef.h>
 #include <ros/syscall.h>
+#include <ros/memlayout.h>
 
 /* Get the pathname of the current working directory,
    and put it in SIZE bytes of BUF.  Returns NULL if the
@@ -34,6 +35,11 @@ __getcwd (char *buf, size_t size)
   int allocated = 0;
   if(buf == NULL)
   {
+    // Linux ABI requires we allocate a buffer if NULL is passed.
+    // If size is passed as 0, it means "as big as necessary"
+    if(size == 0)
+      size = PGSIZE;
+
     buf = (char*)malloc(size);
     if(buf == NULL)
     {
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c
new file mode 100644 (file)
index 0000000..5d58953
--- /dev/null
@@ -0,0 +1,5 @@
+#include <elf/dl-load.c>
+
+#ifdef SHARED
+# include <sysdeps/ros/i386/tls.c>
+#endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c
new file mode 100644 (file)
index 0000000..319ff39
--- /dev/null
@@ -0,0 +1,5 @@
+#include <sysdeps/ros/start.c>
+
+#ifndef SHARED
+# include <sysdeps/ros/i386/tls.c>
+#endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c
new file mode 100644 (file)
index 0000000..3290826
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tls.h>
+#include <sys/mman.h>
+#include <ros/arch/hart.h>
+#include <ros/syscall.h>
+#include <ros/procinfo.h>
+#include <ros/procdata.h>
+#include <arch/mmu.h>
+#include <assert.h>
+
+const char* tls_init_tp(void* thrdescr)
+{
+  int core_id = __hart_self();
+
+  static int initialized = 0;
+  if(!initialized)
+  {
+    assert(core_id == 0);
+    initialized = 1;
+
+    size_t sz= (sizeof(segdesc_t)*__procinfo.max_harts+PGSIZE-1)/PGSIZE*PGSIZE;
+    __procdata.ldt = mmap((void*)USTACKBOT - LDT_SIZE, sz,
+                          PROT_READ | PROT_WRITE,
+                          MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+    // force kernel crossing
+    ros_syscall(SYS_getpid,0,0,0,0,0);
+    if(__procdata.ldt == MAP_FAILED)
+      return "tls couldn't allocate memory\n";
+  }
+
+  // Build the segment
+  segdesc_t tmp = SEG(STA_W, (uint32_t)thrdescr, (uint32_t)thrdescr + 4, 3);
+
+  // Setup the correct LDT entry for this hart
+  __procdata.ldt[core_id] = tmp;
+
+  // Create the GS register.
+  uint32_t gs = (core_id << 3) | 0x07;
+
+  // Set the GS register.
+  asm volatile("movl %0,%%gs" : : "r" (gs));
+
+  return NULL;
+}
index eaf161f..3dae1e8 100644 (file)
@@ -30,7 +30,6 @@
 # include <sysdep.h>
 # include <kernel-features.h>
 
-
 /* Type for the dtv.  */
 typedef union dtv
 {
@@ -202,58 +201,8 @@ union user_desc_init
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-# define TLS_INIT_TP(thrdescr, secondcall) \
-  ({ void *_thrdescr = (thrdescr);                                           \
-     tcbhead_t *_head = _thrdescr;                                           \
-     union user_desc_init _segdescr;                                         \
-     int _result;                                                            \
-                                                                             \
-     _head->tcb = _thrdescr;                                                 \
-     /* For now the thread descriptor is at the same address.  */            \
-     _head->self = _thrdescr;                                                \
-     /* New syscall handling support.  */                                    \
-     INIT_SYSINFO;                                                           \
-                                                                             \
-     /* The 'entry_number' field.  Let the kernel pick a value.  */          \
-     if (secondcall)                                                         \
-       _segdescr.vals[0] = TLS_GET_GS () >> 3;                               \
-     else                                                                    \
-       _segdescr.vals[0] = -1;                                               \
-     /* The 'base_addr' field.  Pointer to the TCB.  */                              \
-     _segdescr.vals[1] = (unsigned long int) _thrdescr;                              \
-     /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */           \
-     _segdescr.vals[2] = 0xfffff;                                            \
-     /* Collapsed value of the bitfield:                                     \
-         .seg_32bit = 1                                                      \
-         .contents = 0                                                       \
-         .read_exec_only = 0                                                 \
-         .limit_in_pages = 1                                                 \
-         .seg_not_present = 0                                                \
-         .useable = 1 */                                                     \
-     _segdescr.vals[3] = 0x51;                                               \
-                                                                             \
-     /* Install the TLS.  */                                                 \
-     asm volatile (TLS_LOAD_EBX                                                      \
-                  "int $0x80\n\t"                                            \
-                  TLS_LOAD_EBX                                               \
-                  : "=a" (_result), "=m" (_segdescr.desc.entry_number)       \
-                  : "0" (__NR_set_thread_area),                              \
-                    TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc));    \
-                                                                             \
-     if (_result == 0)                                                       \
-       /* We know the index in the GDT, now load the segment register.       \
-         The use of the GDT is described by the value 3 in the lower         \
-         three bits of the segment descriptor value.                         \
-                                                                             \
-         Note that we have to do this even if the numeric value of           \
-         the descriptor does not change.  Loading the segment register       \
-         causes the segment information from the GDT to be loaded            \
-         which is necessary since we have changed it.   */                   \
-       TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3);                     \
-                                                                             \
-     _result == 0 ? NULL                                                     \
-     : "set_thread_area failed when setting up thread-local storage\n"; })
-
+const char* tls_init_tp(void* thrdescr);
+# define TLS_INIT_TP(thrdescr, secondcall) tls_init_tp(thrdescr)
 
 /* Return the address of the dtv for the current thread.  */
 # define THREAD_DTV() \
index 0ca9b97..f051282 100644 (file)
@@ -43,7 +43,6 @@ char **__libc_argv attribute_hidden;
 
 struct timeval __t0;
 
-
 void
 __libc_init_first (int argc, char **argv, char **envp)
 {
@@ -80,19 +79,7 @@ _init (int argc, char **argv, char **envp)
   __environ = envp;
 
 #ifndef SHARED
-  // hack until TLS works right
-  __libc_tsd_LOCALE = &_nl_global_locale;
-  _nl_current_LC_MONETARY = &_nl_global_locale.__locales[LC_MONETARY];
-  _nl_current_LC_CTYPE = &_nl_global_locale.__locales[LC_CTYPE];
-  _nl_current_LC_TELEPHONE = &_nl_global_locale.__locales[LC_TELEPHONE];
-  _nl_current_LC_ADDRESS = &_nl_global_locale.__locales[LC_ADDRESS];
-  _nl_current_LC_NUMERIC = &_nl_global_locale.__locales[LC_NUMERIC];
-  _nl_current_LC_PAPER = &_nl_global_locale.__locales[LC_PAPER];
-  _nl_current_LC_MESSAGES = &_nl_global_locale.__locales[LC_MESSAGES];
-  _nl_current_LC_IDENTIFICATION = &_nl_global_locale.__locales[LC_IDENTIFICATION];
-  _nl_current_LC_COLLATE = &_nl_global_locale.__locales[LC_COLLATE];
-  _nl_current_LC_TIME = &_nl_global_locale.__locales[LC_TIME];
-  _nl_current_LC_MEASUREMENT = &_nl_global_locale.__locales[LC_MEASUREMENT];
+  __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
 
   __libc_init_secure ();
 
index 9d52548..eb42dc8 100644 (file)
@@ -5,6 +5,7 @@
 #include <ros/syscall.h>
 #include <ros/procinfo.h>
 #include <unistd.h>
+#include <tls.h>
 
 void** __hart_thread_control_blocks = NULL;
 weak_alias(__hart_thread_control_blocks,hart_thread_control_blocks)
@@ -28,10 +29,19 @@ weak_alias(__hart_yield,hart_yield)
 void
 _start(void)
 {
-       // threads besides thread 0 must acquire a TCB.
        // WARNING: __hart_self_on_entry must be read before
        // anything is register-allocated!
        int id = __hart_self_on_entry;
+       static int init = 0;
+       // For dynamically-linked programs, the first time through,
+       // __hart_self_on_entry could be clobbered (on x86), because
+       // the linker will have overwritten eax.  Happily, the first
+       // time through, we know we are vcore 0.  Subsequent entries
+       // into this routine do not have this problem.
+       if(init == 0)
+               id = 0;
+       
+       // threads besides thread 0 must acquire a TCB.
        if(id != 0)
        {
                TLS_INIT_TP(__hart_thread_control_blocks[id],0);
@@ -41,7 +51,6 @@ _start(void)
                goto diediedie;
        }
 
-       static int init = 0;
        if(init)
        {
                failmsg("why did thread 0 re-enter _start?");
@@ -71,6 +80,9 @@ _start(void)
        while(argv[argc])
                argc++;
 
+       extern char** _environ;
+       _environ = argv+argc+1;
+
        __libc_start_main(&main,argc,argv,&__libc_csu_init,&__libc_csu_fini,0,0);
 
        failmsg("why did main() return?");
@@ -82,4 +94,3 @@ diediedie:
        #endif
        while(1);
 }
-