Browse Source

apply multiple patches

Chia-Che Tsai 9 years ago
parent
commit
5eaaf9abfb
73 changed files with 973 additions and 628 deletions
  1. 2 1
      LibOS/buildglibc.py
  2. 14 48
      LibOS/glibc-2.17.patch
  3. 3 7
      LibOS/glibc-2.17/syscallas.S
  4. 0 10
      LibOS/glibc-2.17/syscalldb.h
  5. 2 0
      LibOS/shim/include/shim_internal.h
  6. 0 14
      LibOS/shim/include/shim_thread.h
  7. 1 1
      LibOS/shim/include/shim_tls.h
  8. 2 0
      LibOS/shim/include/shim_vma.h
  9. 1 1
      LibOS/shim/src/Makefile
  10. 1 0
      LibOS/shim/src/bookkeep/shim_thread.c
  11. 73 6
      LibOS/shim/src/bookkeep/shim_vma.c
  12. 9 24
      LibOS/shim/src/elf/shim_rtld.c
  13. 32 9
      LibOS/shim/src/fs/chroot/fs.c
  14. 98 0
      LibOS/shim/src/fs/proc/thread.c
  15. 1 1
      LibOS/shim/src/ipc/shim_ipc_nsimpl.h
  16. 2 4
      LibOS/shim/src/shim.map
  17. 7 6
      LibOS/shim/src/shim_checkpoint.c
  18. 13 160
      LibOS/shim/src/shim_debug.c
  19. 24 2
      LibOS/shim/src/shim_init.c
  20. 2 5
      LibOS/shim/src/shim_malloc.c
  21. 51 5
      LibOS/shim/src/shim_parser.c
  22. 13 4
      LibOS/shim/src/sys/shim_brk.c
  23. 147 70
      LibOS/shim/src/sys/shim_clone.c
  24. 1 2
      LibOS/shim/src/sys/shim_exec.c
  25. 4 6
      LibOS/shim/src/sys/shim_fork.c
  26. 126 20
      LibOS/shim/src/sys/shim_futex.c
  27. 1 1
      LibOS/shim/src/sys/shim_mmap.c
  28. 4 7
      LibOS/shim/src/sys/shim_sigaction.c
  29. 19 22
      LibOS/shim/src/syscallas.S
  30. 4 5
      LibOS/shim/test/Makefile
  31. 3 5
      LibOS/shim/test/apps/Makefile
  32. 1 1
      LibOS/shim/test/apps/apache/httpd.manifest.template
  33. 1 1
      LibOS/shim/test/apps/bash/bash-local.manifest.template
  34. 1 1
      LibOS/shim/test/apps/bash/bash.manifest.template
  35. 1 1
      LibOS/shim/test/apps/busybox/busybox.manifest.template
  36. 1 1
      LibOS/shim/test/apps/busybox/busybox_nofork.manifest.template
  37. 1 1
      LibOS/shim/test/apps/gcc/g++-huge.manifest.template
  38. 1 1
      LibOS/shim/test/apps/gcc/g++-local.manifest.template
  39. 1 1
      LibOS/shim/test/apps/gcc/g++.manifest.template
  40. 1 1
      LibOS/shim/test/apps/gcc/gcc-huge.manifest.template
  41. 1 1
      LibOS/shim/test/apps/gcc/gcc-local.manifest.template
  42. 1 1
      LibOS/shim/test/apps/gcc/gcc.manifest.template
  43. 1 1
      LibOS/shim/test/apps/lighttpd/lighttpd-angel.manifest.template
  44. 1 1
      LibOS/shim/test/apps/lighttpd/lighttpd.manifest.template
  45. 15 9
      LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c
  46. 1 1
      LibOS/shim/test/apps/lmbench/manifest.template
  47. 1 1
      LibOS/shim/test/apps/make/make-huge.manifest.template
  48. 1 1
      LibOS/shim/test/apps/make/make-local.manifest.template
  49. 1 1
      LibOS/shim/test/apps/make/make.manifest.template
  50. 1 1
      LibOS/shim/test/apps/python/python.manifest.template
  51. 2 2
      LibOS/shim/test/inline/Makefile
  52. 2 2
      LibOS/shim/test/native/Makefile
  53. 4 0
      LibOS/shim/test/native/manifest.template
  54. 0 1
      LibOS/shim/test/native/start.c
  55. 12 0
      LibOS/shim/test/native/system.c
  56. 1 1
      Pal/ipc/linux/graphene-ipc.c
  57. 26 11
      Pal/src/Makefile
  58. 78 65
      Pal/src/db_rtld.c
  59. 4 4
      Pal/src/dynamic_link.h
  60. 2 1
      Pal/src/host/Linux/Makefile
  61. 7 0
      Pal/src/host/Linux/Makefile.am
  62. 8 32
      Pal/src/host/Linux/db_main.c
  63. 2 2
      Pal/src/host/Linux/db_misc.c
  64. 1 1
      Pal/src/host/Linux/db_pipes.c
  65. 2 2
      Pal/src/host/Linux/db_process.c
  66. 106 23
      Pal/src/host/Linux/db_rtld.c
  67. 0 0
      Pal/src/host/Linux/pal.lds
  68. 1 2
      Pal/src/host/Linux/pal.map
  69. 3 0
      Pal/src/host/Linux/pal_linux.h
  70. 3 0
      Pal/src/pal_debug.h
  71. 1 5
      Pal/src/pal_internal.h
  72. 15 0
      Pal/src/pal_rtld.h
  73. 0 1
      Pal/src/security/Linux/Makefile

+ 2 - 1
LibOS/buildglibc.py

@@ -86,7 +86,7 @@ try:
 
     os.chdir(buildDir)
 
-    cflags= '{0} -O2 -U_FORTIFY_SOURCE -fno-stack-protector'.format(debug_flags)
+    cflags = '{0} -O2 -U_FORTIFY_SOURCE -fno-stack-protector'.format(debug_flags)
     disabled_features = { 'nscd' }
     extra_flags = '--with-tls --enable-add-ons=nptl --without-selinux {0}'.format(' '.join(['--disable-' + f for f in disabled_features]))
 
@@ -108,6 +108,7 @@ try:
                       ( 'nptl',   'libpthread.so.0' ),
                       ( 'nptl_db','libthread_db.so.1' ),
                       ( 'dlfcn',  'libdl.so.2' ),
+                      ( 'math',   'libm.so.6' ),
                       ( 'csu',    'crt1.o' ),
                       ( 'csu',    'crti.o' ),
                       ( 'csu',    'crtn.o' ),

+ 14 - 48
LibOS/glibc-2.17.patch

@@ -926,10 +926,10 @@ index dc95421..a772f66 100644
  	cmpl	$0, (%rdi)
  	jne	1f
 diff --git a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
-index 5a80ddd..bcc8d57 100644
+index 5a80ddd..f7319ca 100644
 --- a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
 +++ b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
-@@ -214,12 +214,12 @@ LLL_STUB_UNWIND_INFO_END
+@@ -214,7 +214,7 @@ LLL_STUB_UNWIND_INFO_END
      register const struct timespec *__to __asm ("r10") = timeout;	      \
      int __status;							      \
      register __typeof (val) _val __asm ("edx") = (val);			      \
@@ -938,13 +938,7 @@ index 5a80ddd..bcc8d57 100644
  		      : "=a" (__status)					      \
  		      : "0" (SYS_futex), "D" (futex),			      \
  			"S" (__lll_private_flag (FUTEX_WAIT, private)),	      \
- 			"d" (_val), "r" (__to)				      \
--		      : "memory", "cc", "r11", "cx");			      \
-+		      : "memory", "cc", "r11", "cx", "bx");		      \
-     __status;								      \
-   })
- 
-@@ -229,12 +229,12 @@ LLL_STUB_UNWIND_INFO_END
+@@ -229,7 +229,7 @@ LLL_STUB_UNWIND_INFO_END
      int __ignore;							      \
      register __typeof (nr) _nr __asm ("edx") = (nr);			      \
      LIBC_PROBE (lll_futex_wake, 3, futex, nr, private);                       \
@@ -953,13 +947,7 @@ index 5a80ddd..bcc8d57 100644
  		      : "=a" (__ignore)					      \
  		      : "0" (SYS_futex), "D" (futex),			      \
  			"S" (__lll_private_flag (FUTEX_WAKE, private)),	      \
- 			"d" (_nr)					      \
--		      : "memory", "cc", "r10", "r11", "cx");		      \
-+		      : "memory", "cc", "r10", "r11", "cx", "bx");	      \
-   } while (0)
- 
- 
-@@ -532,12 +532,12 @@ LLL_STUB_UNWIND_INFO_END
+@@ -532,7 +532,7 @@ LLL_STUB_UNWIND_INFO_END
      {									      \
        int ignore;							      \
        __asm __volatile (LOCK_INSTR "orl %3, (%2)\n\t"			      \
@@ -968,13 +956,7 @@ index 5a80ddd..bcc8d57 100644
  			: "=m" (futex), "=a" (ignore)			      \
  			: "D" (&(futex)), "i" (FUTEX_OWNER_DIED),	      \
  			  "S" (__lll_private_flag (FUTEX_WAKE, private)),     \
- 			  "1" (__NR_futex), "d" (1)			      \
--			: "cx", "r11", "cc", "memory");			      \
-+			: "cx", "bx", "r11", "cc", "memory");		      \
-     }									      \
-   while (0)
- 
-@@ -547,13 +547,13 @@ LLL_STUB_UNWIND_INFO_END
+@@ -547,7 +547,7 @@ LLL_STUB_UNWIND_INFO_END
       register int __nr_move __asm ("r10") = nr_move;			      \
       register void *__mutex __asm ("r8") = mutex;			      \
       register int __val __asm ("r9") = val;				      \
@@ -983,14 +965,7 @@ index 5a80ddd..bcc8d57 100644
  		       : "=a" (__res)					      \
  		       : "0" (__NR_futex), "D" ((void *) ftx),		      \
  			 "S" (__lll_private_flag (FUTEX_CMP_REQUEUE,	      \
- 						  private)), "d" (nr_wake),   \
- 			 "r" (__nr_move), "r" (__mutex), "r" (__val)	      \
--		       : "cx", "r11", "cc", "memory");			      \
-+		       : "cx", "bx", "r11", "cc", "memory");		      \
-      __res < 0; })
- 
- #define lll_islocked(futex) \
-@@ -573,13 +573,13 @@ LLL_STUB_UNWIND_INFO_END
+@@ -573,7 +573,7 @@ LLL_STUB_UNWIND_INFO_END
      if (_tid != 0)							      \
        __asm __volatile ("xorq %%r10, %%r10\n\t"				      \
  			"1:\tmovq %2, %%rax\n\t"			      \
@@ -999,13 +974,6 @@ index 5a80ddd..bcc8d57 100644
  			"cmpl $0, (%%rdi)\n\t"				      \
  			"jne 1b"					      \
  			: "=&a" (__ignore)				      \
- 			: "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid),      \
- 			  "d" (_tid)					      \
--			: "memory", "cc", "r10", "r11", "cx");		      \
-+			: "memory", "cc", "r10", "r11", "cx", "bx");	      \
-   } while (0)
- 
- extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
 diff --git a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
 index 0b4ef71..36c5572 100644
 --- a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
@@ -1401,7 +1369,7 @@ index 50587b8..374b553 100644
 +  asm volatile ("pushq %%rbx\n\tmovq syscalldb@GOTPCREL(%%rip), %%rbx\n\t" \
 +		"call %%rbx\n\t" :: "a" (__NR_exit), "D" (val) : "bx" )
 diff --git a/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h b/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
-index f3b7649..b466cb1 100644
+index f3b7649..433b8c9 100644
 --- a/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
 +++ b/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
 @@ -28,6 +28,7 @@
@@ -1423,16 +1391,20 @@ index f3b7649..b466cb1 100644
    int rtld_must_xmm_save;
    /* Reservation of some values for the TM ABI.  */
    void *__private_tm[5];
-@@ -135,6 +140,8 @@ typedef struct
+@@ -135,6 +140,12 @@ typedef struct
  # define GET_DTV(descr) \
    (((tcbhead_t *) (descr))->dtv)
  
 +/* For Graphene */
-+#define SYSCALLDB "movq syscalldb@GOTPCREL(%%rip), %%rbx\n\tcall %%rbx\n\t"
++#define SYSCALLDB							      \
++	"pushq %%rbx\n\t"						      \
++	"movq syscalldb@GOTPCREL(%%rip), %%rbx\n\t"			      \
++	"callq *%%rbx\n\t"						      \
++	"popq %%rbx\n\t"
  
  /* Code to initially initialize the thread pointer.  This might need
     special attention since 'errno' is not yet available and if the
-@@ -152,12 +159,12 @@ typedef struct
+@@ -152,7 +163,7 @@ typedef struct
       _head->self = _thrdescr;						      \
  									      \
       /* It is a simple syscall to set the %fs value for the thread.  */	      \
@@ -1441,12 +1413,6 @@ index f3b7649..b466cb1 100644
  		   : "=a" (_result)					      \
  		   : "0" ((unsigned long int) __NR_arch_prctl),		      \
  		     "D" ((unsigned long int) ARCH_SET_FS),		      \
- 		     "S" (_thrdescr)					      \
--		   : "memory", "cc", "r11", "cx");			      \
-+		   : "memory", "cc", "r11", "cx", "bx");		      \
- 									      \
-     _result ? "cannot set %fs base address for thread-local storage" : 0;     \
-   })
 diff --git a/LibOS/glibc-2.17/scripts/mkinstalldirs b/LibOS/glibc-2.17/scripts/mkinstalldirs
 index f945dbf..3c0e48c 100755
 --- a/LibOS/glibc-2.17/scripts/mkinstalldirs

+ 3 - 7
LibOS/glibc-2.17/syscallas.S

@@ -1,15 +1,11 @@
 #include <syscalldb.h>
 
-#ifdef WEAK_SYSCALLDB
 .weak syscalldb
-#else
-.global syscalldb
-#endif
 .type syscalldb,@function
 
 syscalldb:
 	.cfi_startproc
 	syscall
-	ret
-.cfi_endproc
-.size syscalldb,.-syscalldb
+	retq
+	.cfi_endproc
+	.size syscalldb,.-syscalldb

+ 0 - 10
LibOS/glibc-2.17/syscalldb.h

@@ -1,23 +1,13 @@
 #ifndef _SYSCALLDB_H_
 #define _SYSCALLDB_H_
 
-#define WEAK_SYSCALLDB 1
-
 #ifdef __ASSEMBLER__
-# ifdef WEAK_SYSCALLDB
 .weak syscalldb
-# else
-.global syscalldb
-# endif
 .type syscalldb, @function
 
 #else /* !__ASSEMBLER__ */
 asm (
-# ifdef WEAK_SYSCALLDB
 ".weak syscalldb\r\n"
-# else
-".global syscalldb\r\n"
-# endif
 ".type syscalldb, @function\r\n");
 
 #endif /* Assembler */

+ 2 - 0
LibOS/shim/include/shim_internal.h

@@ -742,6 +742,8 @@ extern const char ** initial_envp;
         _stack;                                                     \
     })
 
+void get_brk_region (void ** start, void ** end, void ** current);
+
 int init_randgen (void);
 int init_brk (void);
 int init_heap (void);

+ 0 - 14
LibOS/shim/include/shim_thread.h

@@ -265,21 +265,7 @@ void set_handle_map (struct shim_thread * thread,
 int thread_exit (struct shim_thread * self, bool send_ipc);
 int try_process_exit (int error_code);
 
-/* thread cloning helpers */
-struct clone_args {
-    PAL_HANDLE create_event;
-    PAL_HANDLE initialize_event;
-    struct shim_thread * thread;
-    void * stack;
-    void * return_pc;
-};
-
-int clone_implementation_wrapper(struct clone_args * arg);
-
-int clean_held_locks (struct shim_thread * self);
-
 void * allocate_stack (size_t size, size_t protect_size, bool user);
-
 int populate_user_stack (void * stack, size_t stack_size,
                          int nauxv, elf_auxv_t ** auxpp,
                          const char *** argvp, const char *** envpp);

+ 1 - 1
LibOS/shim/include/shim_tls.h

@@ -32,13 +32,13 @@ struct shim_regs {
     unsigned long           r15;
     unsigned long           r14;
     unsigned long           r13;
+    unsigned long           r12;
     unsigned long           r9;
     unsigned long           r8;
     unsigned long           rcx;
     unsigned long           rdx;
     unsigned long           rsi;
     unsigned long           rdi;
-    unsigned long           r12;
     unsigned long           rbx;
     unsigned long           rbp;
 };

+ 2 - 0
LibOS/shim/include/shim_vma.h

@@ -87,6 +87,8 @@ struct shim_vma * next_vma (struct shim_vma * vma);
 
 void * get_unmapped_vma (size_t len, int flags);
 
+int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size);
+
 void unmap_all_vmas (void);
 
 /* Debugging */

+ 1 - 1
LibOS/shim/src/Makefile

@@ -64,7 +64,7 @@ libsysdb.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 
-libsysdb_debug.so: $(addsuffix .o,$(objs)) \
+libsysdb_debug.so: $(addsuffix .o,$(filter-out syscallas,$(objs))) \
 		   $(filter %.map %.lds,$($LDFLAGS-debug)) \
 		   $(graphene_lib) $(pal_lib)
 	@echo [ $@ ]

+ 1 - 0
LibOS/shim/src/bookkeep/shim_thread.c

@@ -231,6 +231,7 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
         thread->parent      = cur_thread;
         thread->stack       = cur_thread->stack;
         thread->stack_top   = cur_thread->stack_top;
+        thread->stack_red   = cur_thread->stack_red;
         thread->cwd         = cur_thread->cwd;
         thread->root        = cur_thread->root;
         thread->umask       = cur_thread->umask;

+ 73 - 6
LibOS/shim/src/bookkeep/shim_vma.c

@@ -282,6 +282,7 @@ static int __bkeep_mmap (void * addr, size_t length,
                     prev->length = addr - prev->addr;
                 }
 
+                assert(prev->addr + prev->length <= addr);
                 cont = prev;
                 pos = &prev->list;
             } else { /* has no precendent vma */
@@ -584,9 +585,12 @@ static int __bkeep_mprotect (void * addr, size_t length, int prot,
                 /* no more vmas, protect the whole area */
                 ret = __bkeep_mmap((void *) addr, length, prot,
                                    VMA_UNMAPPED|(flags ? *flags : 0),
-                                   NULL, 0, "bkeep");
+                                   NULL, 0, NULL);
                 if (ret < 0)
                     return ret;
+
+                candidate = __lookup_vma((void *) addr, length);
+                assert(candidate);
             }
 
             length -= candidate->addr - addr;
@@ -801,6 +805,73 @@ struct shim_vma * next_vma (struct shim_vma * vma)
     return tmp;
 }
 
+int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size)
+{
+    lock(vma_list_lock);
+
+    struct shim_vma * vma;
+    int cnt = 0;
+
+    list_for_each_entry(vma, &vma_list, list) {
+        void * start = vma->addr, * end = vma->addr + vma->length;
+
+        if ((vma->flags & (VMA_INTERNAL|VMA_UNMAPPED)) && !vma->comment[0])
+            continue;
+
+        char prot[3] = {'-', '-', '-'};
+        if (vma->prot & PROT_READ)
+            prot[0] = 'r';
+        if (vma->prot & PROT_WRITE)
+            prot[1] = 'w';
+        if (vma->prot & PROT_EXEC)
+            prot[2] = 'x';
+
+        if (vma->file) {
+            int dev_major = 0, dev_minor = 0;
+            unsigned long ino = vma->file->dentry ? vma->file->dentry->ino : 0;
+            const char * name = "[unknown]";
+
+            if (!qstrempty(&vma->file->path))
+                name = qstrgetstr(&vma->file->path);
+
+            cnt += snprintf(buf + cnt, size - cnt,
+                            start > (void *) 0xffffffff ? "%lx" : "%08x", start);
+
+            cnt += snprintf(buf + cnt, size - cnt,
+                            end > (void *) 0xffffffff ? "-%lx" : "-%08x", end);
+
+            cnt += snprintf(buf + cnt, size - cnt,
+                            " %c%c%cp %08x %02d:%02d %u %s\n",
+                            prot[0], prot[1], prot[2],
+                            vma->offset, dev_major, dev_minor, ino,
+                            name);
+        } else {
+            cnt += snprintf(buf + cnt, size - cnt,
+                            start > (void *) 0xffffffff ? "%lx" : "%08x", start);
+
+            cnt += snprintf(buf + cnt, size - cnt,
+                            end > (void *) 0xffffffff ? "-%lx" : "-%08x", end);
+
+            if (vma->comment[0])
+                cnt += snprintf(buf + cnt, size - cnt,
+                                " %c%c%cp 00000000 00:00 0 [%s]\n",
+                                prot[0], prot[1], prot[2], vma->comment[0]);
+            else
+                cnt += snprintf(buf + cnt, size - cnt,
+                                " %c%c%cp 00000000 00:00 0\n",
+                                prot[0], prot[1], prot[2]);
+        }
+
+        if (cnt >= size) {
+            cnt = -EOVERFLOW;
+            break;
+        }
+    }
+
+    unlock(vma_list_lock);
+    return cnt;
+}
+
 void unmap_all_vmas (void)
 {
     struct shim_thread * cur_thread = get_cur_thread();
@@ -1085,12 +1156,10 @@ RESUME_FUNC_BODY(all_vmas)
 }
 END_RESUME_FUNC
 
-void debug_print_vma_list ()
+void debug_print_vma_list (void)
 {
     sys_printf("vma bookkeeping:\n");
 
-    lock(vma_list_lock);
-
     struct shim_vma * vma;
     list_for_each_entry(vma, &vma_list, list) {
         const char * type = "", * name = "";
@@ -1116,8 +1185,6 @@ void debug_print_vma_list ()
                    vma->comment[0] ? " comment=" : "",
                    vma->comment[0] ? vma->comment : "");
     }
-
-    unlock(vma_list_lock);
 }
 
 void print_vma_hash (struct shim_vma * vma, void * addr, int len,

+ 9 - 24
LibOS/shim/src/elf/shim_rtld.c

@@ -339,23 +339,6 @@ void setup_elf_hash (struct link_map * map)
     map->l_chain = hash;
 }
 
-static const char * __obj_type_str (int type, struct link_map * remap)
-{
-    switch (type) {
-        case OBJECT_INTERNAL:
-            return "elf-internal";
-        case OBJECT_LOAD:
-            return "elf-load";
-        case OBJECT_MAPPED:
-            return "elf-mapped";
-        case OBJECT_REMAP:
-            return __obj_type_str(remap->l_type, NULL);
-        case OBJECT_USER:
-            return "elf-user";
-    }
-    return NULL;
-}
-
 /* Map in the shared object NAME, actually located in REALNAME, and already
    opened on FD */
 static struct link_map *
@@ -376,7 +359,6 @@ __map_elf_object (struct shim_handle * file,
     if (file && (!read || !mmap || !seek))
         return NULL;
 
-    const char * obj_type = __obj_type_str(type, remap);
     struct link_map * l = remap ? :
                           new_elf_object(file ? (!qstrempty(&file->path) ?
                                          qstrgetstr(&file->path) :
@@ -404,6 +386,7 @@ call_lose:
 
     /* Extract the remaining details we need from the ELF header
        and then read in the program header table.  */
+    l->l_addr = (ElfW(Addr)) addr;
     l->l_entry = header->e_entry;
     int e_type = header->e_type;
     l->l_phnum = header->e_phnum;
@@ -438,7 +421,7 @@ call_lose:
                 break;
 
             case PT_INTERP:
-                l->l_interp_libname = ((const char *) l->l_addr + ph->p_vaddr);
+                l->l_interp_libname = (const char *) ph->p_vaddr;
                 break;
 
             case PT_PHDR:
@@ -559,7 +542,7 @@ map_error:
             bkeep_mmap((void *) mappref, ALIGN_UP(maplength), c->prot,
                        c->flags|MAP_PRIVATE|
                        (type == OBJECT_INTERNAL ? VMA_INTERNAL : 0),
-                       file, c->mapoff, obj_type);
+                       file, c->mapoff, NULL);
 
         l->l_addr = l->l_map_start - c->mapstart;
 
@@ -593,6 +576,7 @@ map_error:
     }
 
     /* Remember which part of the address space this object uses.  */
+    l->l_addr = 0;
     l->l_map_start = c->mapstart;
     l->l_map_end = l->l_map_start + maplength;
 
@@ -615,7 +599,7 @@ do_remap:
                     bkeep_mmap(mapaddr, c->mapend - c->mapstart, c->prot,
                                c->flags|MAP_FIXED|MAP_PRIVATE|
                                (type == OBJECT_INTERNAL ? VMA_INTERNAL : 0),
-                               file, c->mapoff, obj_type);
+                               file, c->mapoff, NULL);
         }
 
 postmap:
@@ -1143,12 +1127,12 @@ static int __load_elf_object (struct shim_handle * file, void * addr,
         add_link_map(map);
     }
 
-    if ((type == OBJECT_LOAD || type == OBJECT_REMAP) &&
+    if ((type == OBJECT_LOAD || type == OBJECT_REMAP || type == OBJECT_USER) &&
         map->l_file && !qstrempty(&map->l_file->uri)) {
         if (type == OBJECT_REMAP)
             remove_r_debug((void *) map->l_addr);
 
-        append_r_debug(qstrgetstr(&map->l_file->uri), (void *) map->l_addr,
+        append_r_debug(qstrgetstr(&map->l_file->uri), (void *) map->l_map_start,
                        (void *) map->l_real_ld);
     }
 
@@ -1440,7 +1424,8 @@ int free_elf_interp (void)
 
 static int __load_interp_object (struct link_map * exec_map)
 {
-    const char * interp_name = exec_map->l_interp_libname;
+    const char * interp_name = (const char *) exec_map->l_interp_libname +
+                               (long) exec_map->l_addr;
     int len = strlen(interp_name);
     const char * filename = interp_name + len - 1;
     while (filename > interp_name && *filename != '/')

+ 32 - 9
LibOS/shim/src/fs/chroot/fs.c

@@ -595,7 +595,7 @@ static inline int __map_buffer (struct shim_handle * hdl, int size)
         return -PAL_ERRNO;
 
     bkeep_mmap(mapbuf, maplen, prot, MAP_FILE|MAP_SHARED|VMA_INTERNAL,
-               hdl, mapoff, "chroot-buffer");
+               hdl, mapoff, NULL);
 
     file->mapbuf    = mapbuf;
     file->mapoffset = mapoff;
@@ -706,14 +706,26 @@ static int chroot_read (struct shim_handle * hdl, void * buf,
         goto out;
     }
 
-    if (hdl->info.file.buf_type == FILEBUF_MAP) {
+    struct shim_file_handle * file = &hdl->info.file;
+
+    if (file->buf_type == FILEBUF_MAP) {
         ret = map_read(hdl, buf, count);
-        goto out;
+        if (ret != -EACCES)
+            goto out;
+
+        lock(hdl->lock);
+        file->buf_type = FILEBUF_NONE;
+    } else {
+        lock(hdl->lock);
     }
 
-    ret = DkStreamRead(hdl->pal_handle, 0, count, buf, NULL, 0) ? :
+    ret = DkStreamRead(hdl->pal_handle, file->marker, count, buf, NULL, 0) ? :
            (PAL_NATIVE_ERRNO == PAL_ERROR_ENDOFSTREAM ? 0 : -PAL_ERRNO);
 
+    if (ret > 0)
+        file->marker += ret;
+
+    unlock(hdl->lock);
 out:
     return ret;
 }
@@ -730,13 +742,26 @@ static int chroot_write (struct shim_handle * hdl, const void * buf,
         goto out;
     }
 
+    struct shim_file_handle * file = &hdl->info.file;
+
     if (hdl->info.file.buf_type == FILEBUF_MAP) {
         ret = map_write(hdl, buf, count);
+        if (ret != -EACCES)
+            goto out;
+
+        lock(hdl->lock);
+        file->buf_type = FILEBUF_NONE;
     } else {
-        ret =  DkStreamWrite(hdl->pal_handle, 0, count, buf, NULL) ? :
-            -PAL_ERRNO;
+        lock(hdl->lock);
     }
 
+    ret = DkStreamWrite(hdl->pal_handle, file->marker, count, buf, NULL) ? :
+          -PAL_ERRNO;
+
+    if (ret > 0)
+        file->marker += ret;
+
+    unlock(hdl->lock);
 out:
     return ret;
 
@@ -804,9 +829,7 @@ static int chroot_seek (struct shim_handle * hdl, off_t offset, int wence)
             break;
 
         case SEEK_END:
-            if (offset < 0)
-                goto out;
-            marker = size - offset;
+            marker = size + offset;
             break;
     }
 

+ 98 - 0
LibOS/shim/src/fs/proc/thread.c

@@ -11,11 +11,14 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
 #include <errno.h>
 
+#define DEFAULT_BUFFER_SIZE 256
+
 static int parse_thread_name (const char * name,
                               const char ** next, int * next_len,
                               const char ** nextnext)
@@ -461,6 +464,100 @@ static const struct proc_dir dir_fd = { .size = 1, .ent = { {
             .nm_ops = &nm_thread_each_fd, .fs_ops = &fs_thread_each_fd,
         }, }, };
 
+static int proc_thread_maps_open (struct shim_handle * hdl,
+                                  const char * name, int flags)
+{
+    if (flags & (O_WRONLY|O_RDWR))
+        return -EACCES;
+
+    const char * next;
+    int next_len;
+    int pid = parse_thread_name(name, &next, &next_len, NULL);
+
+    if (pid < 0)
+        return pid;
+
+    struct shim_thread * thread = lookup_thread(pid);
+
+    if (!thread)
+        return -ENOENT;
+
+    int size = DEFAULT_BUFFER_SIZE;
+    char * strbuf = malloc(size);
+    int ret = 0, len = 0;
+
+    if (!strbuf) {
+        ret = -ENOMEM;
+        goto out;
+    }
+
+retry:
+    ret = dump_all_vmas(thread, strbuf, size);
+
+    if (ret == -EOVERFLOW) {
+        char * newbuf = malloc(size * 2);
+        if (!newbuf) {
+            ret = -ENOMEM;
+            goto err;
+        }
+        free(strbuf);
+        strbuf = newbuf;
+        size *= 2;
+        goto retry;
+    }
+
+    if (ret < 0)
+        goto err;
+
+    len = ret;
+
+    struct shim_str_data * data = malloc(sizeof(struct shim_str_data));
+    if (!data) {
+        ret = -ENOMEM;
+        goto err;
+    }
+
+    memset(data, 0, sizeof(struct shim_str_data));
+    data->str = strbuf;
+    data->len = len;
+    hdl->type = TYPE_STR;
+    hdl->flags = flags & ~O_RDONLY;
+    hdl->acc_mode = MAY_READ;
+    hdl->info.str.data = data;
+    ret = 0;
+out:
+    put_thread(thread);
+    return ret;
+err:
+    free(strbuf);
+    goto out;
+}
+
+static int proc_thread_maps_mode (const char * name, mode_t * mode)
+{
+    *mode = 0400;
+    return 0;
+}
+
+static int proc_thread_maps_stat (const char * name, struct stat * buf)
+{
+    memset(buf, 0, sizeof(struct stat));
+
+    buf->st_dev = buf->st_ino = 1;
+    buf->st_mode = 0400|S_IFREG;
+    buf->st_uid = 0;
+    buf->st_gid = 0;
+    buf->st_size = 0;
+
+    return 0;
+}
+
+static const struct proc_fs_ops fs_thread_maps = {
+            .open           = &proc_thread_maps_open,
+            .mode           = &proc_thread_maps_mode,
+            .stat           = &proc_thread_maps_stat,
+        };
+
 static int proc_thread_dir_mode (const char * name, mode_t * mode)
 {
     const char * next;
@@ -570,4 +667,5 @@ const struct proc_dir dir_thread = { .size = 5, .ent = {
         { .name = "exe", .fs_ops = &fs_thread_link, },
         { .name = "root", .fs_ops = &fs_thread_link, },
         { .name = "fd", .dir = &dir_fd, .fs_ops = &fs_thread_fd, },
+        { .name = "maps", .fs_ops = &fs_thread_maps, },
     }, };

+ 1 - 1
LibOS/shim/src/ipc/shim_ipc_nsimpl.h

@@ -639,7 +639,7 @@ IDTYPE CONCAT2(allocate, NS) (IDTYPE min, IDTYPE max)
                 for ( ; j < BITS ; f <<= 1, j++)
                     if (!(map & f)) {
                         (*m) |= f;
-                        idx = base + i * RANGE_SIZE + j;
+                        idx = base + i * BITS + j;
                         debug("allocated " NS_STR ": %u\n", idx);
                         goto out;
                     }

+ 2 - 4
LibOS/shim/src/shim.map

@@ -1,8 +1,6 @@
 SHIM {
     global:
-        syscalldb;
-        __libc_r_debug; __libc_dl_debug_state;
-        glibc_vers_2_17;
-        register_library;
+        syscalldb; register_library;
+        glibc_vers_*;
     local: *;
 };

+ 7 - 6
LibOS/shim/src/shim_checkpoint.c

@@ -875,7 +875,7 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
 
         bkeep_mmap(cpaddr, ALIGN_UP(cpsize), PROT_READ|PROT_WRITE,
                    MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
-                   NULL, 0, "migrated");
+                   NULL, 0, NULL);
 
         SAVE_PROFILE_INTERVAL(child_load_checkpoint_by_gipc);
 
@@ -897,7 +897,7 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
 
         bkeep_mmap(cpaddr, cpsize_pgalign, PROT_READ|PROT_WRITE,
                    MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
-                   NULL, 0, "migrated");
+                   NULL, 0, NULL);
 
         cpaddr -= cpaddr_pgalign;
 
@@ -944,8 +944,8 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
 
 void restore_context (struct shim_context * context)
 {
-    int nregs = sizeof(struct shim_regs) / sizeof(unsigned long);
-    unsigned long regs[nregs + 1];
+    int nregs = sizeof(struct shim_regs) / sizeof(void *);
+    void * regs[nregs + 1];
 
     if (context->regs)
         memcpy(regs, context->regs, sizeof(struct shim_regs));
@@ -954,7 +954,8 @@ void restore_context (struct shim_context * context)
 
     debug("restore context: SP = %p, IP = %p\n", context->sp, context->ret_ip);
 
-    regs[nregs] = (unsigned long) context->sp;
+    regs[nregs] = (void *) context->sp - 8;
+    *(void **) (context->sp - 8) = context->ret_ip;
 
     memset(context, 0, sizeof(struct shim_context));
 
@@ -962,13 +963,13 @@ void restore_context (struct shim_context * context)
                  "popq %%r15\r\n"
                  "popq %%r14\r\n"
                  "popq %%r13\r\n"
+                 "popq %%r12\r\n"
                  "popq %%r9\r\n"
                  "popq %%r8\r\n"
                  "popq %%rcx\r\n"
                  "popq %%rdx\r\n"
                  "popq %%rsi\r\n"
                  "popq %%rdi\r\n"
-                 "popq %%r12\r\n"
                  "popq %%rbx\r\n"
                  "popq %%rbp\r\n"
                  "popq %%rsp\r\n"

+ 13 - 160
LibOS/shim/src/shim_debug.c

@@ -44,171 +44,44 @@ struct gdb_link_map
     struct gdb_link_map *l_next, *l_prev;
 };
 
-struct gdb_r_debug
-{
-    int r_version;
-    struct gdb_link_map *r_map;
-    uintptr_t r_brk;
-    enum
-    {
-        RT_CONSISTENT,
-        RT_ADD,
-        RT_DELETE,
-    } r_state;
-    uintptr_t r_ldbase;
-};
-
-struct gdb_r_debug __libc_r_debug;
-
-extern struct gdb_r_debug _r_debug;
-extern void _dl_debug_state_trigger (void);
-
 static struct gdb_link_map * link_map_list = NULL;
 
-static inline char * translate_file_path (const char * path)
-{
-    struct shim_dentry * dent = NULL;
-
-    int ret = path_lookupat(NULL, path, 0, &dent);
-    if (ret < 0)
-        return NULL;
-
-    struct shim_mount * fs = dent->fs;
-
-    if (!fs->d_ops->open)
-        return NULL;
-
-    char * new_uri = NULL;
-    struct shim_handle * hdl = get_new_handle();
-    if (!hdl)
-        return NULL;
-
-    set_handle_fs(hdl, fs);
-    hdl->dentry = dent;
-
-    ret = fs->d_ops->open(hdl, dent, O_RDONLY);
-    if (ret < 0)
-        goto out;
-
-    new_uri = qstrtostr(&hdl->uri, false);
-out:
-    put_handle(hdl);
-    return new_uri;
-}
-
-void __libc_dl_debug_state (void)
-{
-    /* first make sure libc map list matches the shadow map list */
-    if (link_map_list) {
-        struct gdb_link_map *m = link_map_list, *n;
-        for ( ; m ; m = m->l_next) {
-            for (n = __libc_r_debug.r_map ; n ; n = n->l_next)
-                if (m->l_addr == n->l_addr)
-                    break;
-            if (!n) {
-                if (m->l_prev)
-                    m->l_prev->l_next = m->l_next;
-                if (m->l_next)
-                    m->l_next->l_prev = m->l_prev;
-                if (m == link_map_list)
-                    link_map_list = m->l_next;
-            }
-        }
-    }
-
-    /* now find the end of the shadow map list, where we are adding to */
-    struct gdb_link_map *prev = NULL;
-    struct gdb_link_map **tail = &_r_debug.r_map;
-
-    while (*tail) {
-        prev = *tail;
-        tail = &(*tail)->l_next;
-    }
-
-    /* add new maps to the shadow map list */
-    struct gdb_link_map **t = tail;
-    struct gdb_link_map *m = __libc_r_debug.r_map;
-
-    for ( ; m ; m = m->l_next) {
-        struct gdb_link_map *re = _r_debug.r_map;
-        while (re && re->l_addr != m->l_addr)
-            re = re->l_next;
-
-        if (re)
-            continue;
-
-        char * uri = translate_file_path(m->l_name);
-        if (!uri)
-            continue;
-        debug("add a library for gdb: %s\n", uri);
-
-        struct gdb_link_map * new = malloc(sizeof(struct gdb_link_map));
-
-        new->l_addr = m->l_addr;
-        new->l_ld = m->l_ld;
-        new->l_name = uri;
-        new->l_prev = prev;
-        prev = *t = new;
-        new->l_next = NULL;
-        t = &new->l_next;
-    }
-
-    if (!link_map_list)
-        link_map_list = *tail;
-
-    _r_debug.r_state = __libc_r_debug.r_state;
-    _dl_debug_state_trigger();
-}
-
 void clean_link_map_list (void)
 {
     if (!link_map_list)
         return;
 
-    _r_debug.r_state = RT_DELETE;
-    _dl_debug_state_trigger();
-
     if (link_map_list->l_prev)
         link_map_list->l_prev->l_next = NULL;
-    if (_r_debug.r_map == link_map_list)
-        _r_debug.r_map = NULL;
 
     struct gdb_link_map * m = link_map_list;
-    for ( ; m ; m = m->l_next)
+    for ( ; m ; m = m->l_next) {
+        DkDebugDetachBinary(m->l_addr);
         free(m);
+    }
 
     link_map_list = NULL;
-
-    _r_debug.r_state = RT_CONSISTENT;
-    _dl_debug_state_trigger();
-
 }
 
 void remove_r_debug (void * addr)
 {
-    struct gdb_link_map * m = _r_debug.r_map;
+    struct gdb_link_map * m = link_map_list;
 
-    for ( ; m && m != link_map_list ; m = m->l_next)
+    for ( ; m ; m = m->l_next)
         if (m->l_addr == addr)
             break;
 
-    if (!m || m == link_map_list)
+    if (!m)
         return;
 
-    _r_debug.r_state = RT_DELETE;
-    _dl_debug_state_trigger();
-
     debug("remove a library for gdb: %s\n", m->l_name);
 
     if (m->l_prev)
         m->l_prev->l_next = m->l_next;
     if (m->l_next)
         m->l_next->l_prev = m->l_prev;
-    if (_r_debug.r_map == m)
-        _r_debug.r_map = m->l_next;
 
-    _r_debug.r_state = RT_CONSISTENT;
-    _dl_debug_state_trigger();
+    DkDebugDetachBinary(addr);
 }
 
 void append_r_debug (const char * uri, void * addr, void * dyn_addr)
@@ -224,26 +97,20 @@ void append_r_debug (const char * uri, void * addr, void * dyn_addr)
     new->l_name = new_uri;
 
     struct gdb_link_map *prev = NULL;
-    struct gdb_link_map **tail = &_r_debug.r_map;
+    struct gdb_link_map **tail = &link_map_list;
 
-    while (*tail && *tail != link_map_list) {
+    while (*tail) {
         prev = *tail;
         tail = &(*tail)->l_next;
     }
 
-    _r_debug.r_state = RT_ADD;
-    _dl_debug_state_trigger();
-
-    debug("add a library for gdb: %s\n", new->l_name);
+    debug("add a library for gdb: %s\n", uri);
 
     new->l_prev = prev;
-    new->l_next = link_map_list;
+    new->l_next = NULL;
     *tail = new;
-    if (link_map_list)
-        link_map_list->l_prev = new;
 
-    _r_debug.r_state = RT_CONSISTENT;
-    _dl_debug_state_trigger();
+    DkDebugAttachBinary(uri, addr);
 }
 
 DEFINE_MIGRATE_FUNC(gdb_map)
@@ -278,10 +145,6 @@ END_MIGRATE_FUNC
 RESUME_FUNC_BODY(gdb_map)
 {
     uint64_t off = GET_FUNC_ENTRY();
-
-    _r_debug.r_state = RT_ADD;
-    _dl_debug_state_trigger ();
-
     struct gdb_link_map *map = (struct gdb_link_map *) (base + off);
 
     RESUME_REBASE(map->l_name);
@@ -299,20 +162,10 @@ RESUME_FUNC_BODY(gdb_map)
     map->l_prev = prev;
     *tail = map;
 
-    tail = &_r_debug.r_map;
-    while (*tail && *tail != link_map_list) {
-        prev = *tail;
-        tail = &(*tail)->l_next;
-    }
-
-    *tail = link_map_list;
-    link_map_list->l_prev = prev;
-
 #ifdef DEBUG_RESUME
     debug("gdb: %s loaded at %p\n", map->l_name, map->l_addr);
 #endif
 
-    _r_debug.r_state = RT_CONSISTENT;
-    _dl_debug_state_trigger ();
+    DkDebugAttachBinary(map->l_name, map->l_addr);
 }
 END_RESUME_FUNC

+ 24 - 2
LibOS/shim/src/shim_init.c

@@ -148,6 +148,9 @@ void allocate_tls (void * tcb_location, struct shim_thread * thread)
         thread->tcb       = tcb;
         tcb->shim_tcb.tp  = thread;
         tcb->shim_tcb.tid = thread->tid;
+    } else {
+        tcb->shim_tcb.tp  = NULL;
+        tcb->shim_tcb.tid = 0;
     }
 
     DkThreadPrivate(tcb);
@@ -210,7 +213,7 @@ void * allocate_stack (size_t size, size_t protect_size, bool user)
 
         if (protect_size &&
             bkeep_mmap(stack - protect_size, protect_size, 0,
-                       STACK_FLAGS, NULL, 0, "stack-red") < 0)
+                       STACK_FLAGS, NULL, 0, NULL) < 0)
             return NULL;
     }
 
@@ -394,7 +397,8 @@ int init_manifest (PAL_HANDLE manifest_handle)
 
     size_t cfg_size = attr.size;
     void * cfg_addr = DkStreamMap(manifest_handle, NULL,
-                                  PAL_PROT_READ, 0, ALIGN_UP(cfg_size));
+                                  PAL_PROT_READ|PAL_PROT_WRITECOPY, 0,
+                                  ALIGN_UP(cfg_size));
 
     if (!cfg_addr)
         return -PAL_ERRNO;
@@ -583,6 +587,7 @@ int shim_init (int argc, void * args, void ** return_stack)
 
     /* create the initial TCB, shim can not be run without a tcb */
     __libc_tcb_t tcb;
+    memset(&tcb, 0, sizeof(__libc_tcb_t));
     allocate_tls(&tcb, NULL);
     debug_setbuf(&tcb.shim_tcb, true);
 
@@ -920,6 +925,23 @@ int create_handle (const char * prefix, char * uri, size_t size,
                          id ? : &suffix, hdl, NULL);
 }
 
+void check_stack_hook (void)
+{
+    struct shim_thread * cur_thread = get_cur_thread();
+
+    void * rsp;
+    asm volatile ("movq %%rsp, %0" : "=r"(rsp) :: "memory");
+
+    if (rsp <= cur_thread->stack_top && rsp > cur_thread->stack) {
+        if (rsp - cur_thread->stack < PAL_CB(pagesize))
+            sys_printf("*** stack is almost drained (RSP = %p, stack = %p-%p) ***\n",
+                       rsp, cur_thread->stack, cur_thread->stack_top);
+    } else {
+        sys_printf("*** context dismateched with thread stack (RSP = %p, stack = %p-%p) ***\n",
+                   rsp, cur_thread->stack, cur_thread->stack_top);
+    }
+}
+
 #ifdef PROFILE
 static void print_profile_result (PAL_HANDLE hdl, struct shim_profile * root,
                                   int level)

+ 2 - 5
LibOS/shim/src/shim_malloc.c

@@ -111,9 +111,7 @@ static struct shim_heap * __alloc_enough_heap (size_t size)
 
         unlock(shim_heap_lock);
         bkeep_mmap(start, heap_size, PROT_READ|PROT_WRITE,
-                   MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0,
-                   "shim-heap");
-
+                   MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL);
         lock(shim_heap_lock);
     }
 
@@ -175,8 +173,7 @@ int bkeep_shim_heap (void)
             bkeep_mmap(shim_heap_areas[i].start,
                        shim_heap_areas[i].end - shim_heap_areas[i].start,
                        PROT_READ|PROT_WRITE,
-                       MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0,
-                       "shim-heap");
+                       MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL);
 
     unlock(shim_heap_lock);
     return 0;

+ 51 - 5
LibOS/shim/src/shim_parser.c

@@ -37,6 +37,7 @@
 #include <asm/prctl.h>
 #include <asm/mman.h>
 #include <asm/ioctls.h>
+#include <linux/sched.h>
 #include <linux/futex.h>
 #include <linux/wait.h>
 #include <errno.h>
@@ -45,6 +46,7 @@
 static void parse_open_flags    (const char *, va_list);
 static void parse_open_mode     (const char *, va_list);
 static void parse_access_mode   (const char *, va_list);
+static void parse_clone_flags   (const char *, va_list);
 static void parse_mmap_prot     (const char *, va_list);
 static void parse_mmap_flags    (const char *, va_list);
 static void parse_exec_args     (const char *, va_list);
@@ -130,7 +132,7 @@ struct parser_table {
       .parser = { NULL, NULL, NULL, &parse_pipe_fds } },
     { .slow = 0, .parser = { NULL } }, /* setsockopt */
     { .slow = 0, .parser = { NULL } }, /* getsockopt */
-    { .slow = 1, .parser = { NULL } }, /* clone */
+    { .slow = 1, .parser = { &parse_clone_flags } }, /* clone */
     { .slow = 1, .parser = { NULL } }, /* fork */
     { .slow = 1, .parser = { NULL } }, /* vfork */
     { .slow = 1,                       /* execve */
@@ -612,6 +614,37 @@ static void parse_access_mode (const char * type, va_list ap)
     }
 }
 
+static void parse_clone_flags (const char * type, va_list ap)
+{
+    int flags = va_arg (ap, int);
+
+#define FLG(n) { "CLONE_" #n, CLONE_##n, }
+    const struct {
+        const char * name; int flag;
+    } all_flags[] = {
+        FLG(VM), FLG(FS), FLG(FILES), FLG(SIGHAND), FLG(PTRACE), FLG(VFORK),
+        FLG(PARENT), FLG(THREAD), FLG(NEWNS), FLG(SYSVSEM), FLG(SETTLS),
+        FLG(PARENT_SETTID), FLG(CHILD_CLEARTID), FLG(DETACHED), FLG(UNTRACED),
+        FLG(CHILD_SETTID), FLG(NEWUTS), FLG(NEWIPC), FLG(NEWUSER),
+        FLG(NEWPID), FLG(NEWNET), FLG(IO),
+    };
+#undef FLG
+
+    bool printed = false;
+    for (int i = 0 ; i < sizeof(all_flags) / sizeof(all_flags[0]) ; i++)
+        if (flags & all_flags[i].flag) {
+            if (printed)
+                PUTCH('|');
+            else
+                printed = true;
+            PUTS(all_flags[i].name);
+            flags &= ~all_flags[i].flag;
+        }
+
+    if (flags)
+        PRINTF("|0x%x", flags);
+}
+
 static void parse_mmap_prot (const char * type, va_list ap)
 {
     int prot = va_arg (ap, int);
@@ -650,23 +683,36 @@ static void parse_mmap_flags (const char * type, va_list ap)
         PUTS("MAP_SHARED");
         flags &= ~MAP_SHARED;
     }
-    else
+
+    if (flags & MAP_PRIVATE) {
         PUTS("MAP_PRIVATE");
+        flags &= ~MAP_PRIVATE;
+    }
 
     if (flags & MAP_ANONYMOUS) {
         PUTS("|MAP_ANON");
         flags &= ~MAP_ANONYMOUS;
     }
-    else
+
+    if (flags & MAP_FILE) {
         PUTS("|MAP_FILE");
+        flags &= ~MAP_FILE;
+    }
 
     if (flags & MAP_FIXED) {
         PUTS("|MAP_FIXED");
         flags &= ~MAP_FIXED;
     }
 
+#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
+    if (flags & MAP_UNINITIALIZED) {
+        PUTS("|MAP_UNINITIALIZED");
+        flags &= ~MAP_UNINITIALIZED;
+    }
+#endif
+
     if (flags)
-        PRINTF("|%o", flags);
+        PRINTF("|0x%x", flags);
 }
 
 static void parse_exec_args (const char * type, va_list ap)
@@ -884,7 +930,7 @@ static void parse_futexop (const char * type, va_list ap)
             PUTS("FUTEX_CMP_REQUEUE");
             break;
         case FUTEX_WAKE_OP:
-            PUTS("FUTEX_WAKE");
+            PUTS("FUTEX_WAKE_OP");
             break;
         default:
             PRINTF("OP %d", op);

+ 13 - 4
LibOS/shim/src/sys/shim_brk.c

@@ -50,6 +50,15 @@ DEFINE_PROFILE_OCCURENCE(brk, memory);
 DEFINE_PROFILE_OCCURENCE(brk_count, memory);
 DEFINE_PROFILE_OCCURENCE(brk_migrate_count, memory);
 
+void get_brk_region (void ** start, void ** end, void ** current)
+{
+    master_lock();
+    *start   = region.brk_start;
+    *end     = region.brk_end;
+    *current = region.brk_current;
+    master_unlock();
+}
+
 int init_brk_region (void)
 {
     if (region.brk_start)
@@ -88,11 +97,11 @@ int init_brk_region (void)
           brk_region + brk_max_size);
 
     bkeep_mmap(brk_region, BRK_SIZE, PROT_READ|PROT_WRITE,
-               MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "brk");
+               MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "[heap]");
     bkeep_mmap(end_brk_region, brk_max_size - BRK_SIZE,
                PROT_READ|PROT_WRITE,
                MAP_ANONYMOUS|MAP_PRIVATE|VMA_UNMAPPED,
-               NULL, 0, "brk-reserved");
+               NULL, 0, NULL);
 
     return 0;
 }
@@ -148,7 +157,7 @@ unchanged:
 
         bkeep_mmap(region.brk_start, brk_end - region.brk_start,
                    PROT_READ|PROT_WRITE,
-                   MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "brk");
+                   MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "heap");
 
         region.brk_current = brk;
         region.brk_end = brk_end;
@@ -203,7 +212,7 @@ RESUME_FUNC_BODY(brk)
         bkeep_mmap(region.brk_end, brk_max_size - brk_size,
                    PROT_READ|PROT_WRITE,
                    MAP_ANONYMOUS|MAP_PRIVATE|VMA_UNMAPPED, NULL, 0,
-                   "brk-reserved");
+                   NULL);
     }
 
 #ifdef DEBUG_RESUME

+ 147 - 70
LibOS/shim/src/sys/shim_clone.c

@@ -29,6 +29,7 @@
 #include <shim_table.h>
 #include <shim_thread.h>
 #include <shim_utils.h>
+#include <shim_checkpoint.h>
 #include <shim_profile.h>
 
 #include <pal.h>
@@ -40,6 +41,14 @@
 #include <linux/sched.h>
 #include <asm/prctl.h>
 
+struct clone_args {
+    PAL_HANDLE create_event;
+    PAL_HANDLE initialize_event;
+    struct shim_thread * thread, * parent;
+    void * stack;
+    void * return_pc;
+};
+
 /* from **sysdeps/unix/sysv/linux/x86_64/clone.S:
    The userland implementation is:
    int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
@@ -96,10 +105,17 @@ int clone_implementation_wrapper(struct clone_args * arg)
     assert(my_thread);
     get_thread(my_thread);
 
-    if (my_thread->set_child_tid) {
+    if (!my_thread->tcb)
+        my_thread->tcb = __alloca(sizeof(__libc_tcb_t));
+    allocate_tls(my_thread->tcb, my_thread);
+    shim_tcb_t * tcb = &((__libc_tcb_t *) my_thread->tcb)->shim_tcb;
+    debug_setbuf(tcb, true);
+
+    struct shim_regs * regs = __alloca(sizeof(struct shim_regs));
+    *regs = *((__libc_tcb_t *) arg->parent->tcb)->shim_tcb.context.regs;
+
+    if (my_thread->set_child_tid)
         *(my_thread->set_child_tid) = my_thread->tid;
-        debug("clone: tid set at %p\n", my_thread->set_child_tid);
-    }
 
     void * stack = pcargs->stack;
     void * return_pc = pcargs->return_pc;
@@ -107,12 +123,9 @@ int clone_implementation_wrapper(struct clone_args * arg)
     struct shim_vma * vma = NULL;
     lookup_supervma(ALIGN_DOWN(stack), allocsize, &vma);
     assert(vma);
-    my_thread->stack_top = stack;
+    my_thread->stack_top = vma->addr + vma->length;
     my_thread->stack_red = my_thread->stack = vma->addr;
-
-    __libc_tcb_t tcb;
-    allocate_tls(&tcb, my_thread);
-    debug_setbuf(&tcb.shim_tcb, true);
+    snprintf(vma->comment, VMA_COMMENT_LEN, "stack:%d", my_thread->tid);
 
     /* Don't signal the initialize event until we are actually init-ed */ 
     DkEventSet(pcargs->initialize_event);
@@ -125,13 +138,18 @@ int clone_implementation_wrapper(struct clone_args * arg)
     debug("child swapping stack to %p return %p: %d\n",
           stack, return_pc, my_thread->tid);
 
-    asm volatile("movq %0, %%rsp\r\n"
-                 "pushq %1\r\n"
-                 "retq\r\n"
-                 : : "r"(stack), "r"(return_pc), "a"(0));
+    tcb->context.regs = regs;
+    tcb->context.sp = stack;
+    tcb->context.ret_ip = return_pc;
+
+    restore_context(&tcb->context);
     return 0;
 }
 
+int migrate_fork (struct shim_cp_store * cpstore,
+                  struct shim_process * process,
+                  struct shim_thread * thread, va_list ap);
+
 /*  long int __arg0 - flags
  *  long int __arg1 - 16 bytes ( 2 words ) offset into the child stack allocated
  *                    by the parent     */
@@ -144,8 +162,7 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
     struct shim_thread * self = get_cur_thread();
     assert(self);
-    struct clone_args * new_args = __alloca(sizeof(struct clone_args));
-    memset(new_args, 0, sizeof(struct clone_args));
+    int * set_parent_tid = NULL;
     int ret = 0;
 
     assert((flags & ~(CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
@@ -158,67 +175,58 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
 #endif
                       CLONE_SYSVSEM|CSIGNAL)) == 0);
 
-    new_args->create_event = DkNotificationEventCreate(0);
-    if (!new_args->create_event) {
-        ret = -PAL_ERRNO;
-        goto failed;
-    }
+    if (!(flags & CLONE_FS))
+        debug("clone without CLONE_FS is not yet implemented\n");
 
-    new_args->initialize_event = DkNotificationEventCreate(0);
-    if (!new_args->initialize_event) {
-        ret = -PAL_ERRNO;
-        goto failed;
+    if (!(flags & CLONE_SIGHAND))
+        debug("clone without CLONE_SIGHAND is not yet implemented\n");
+
+    if (!(flags & CLONE_SYSVSEM))
+        debug("clone without CLONE_SYSVSEM is not yet implemented\n");
+
+    if (flags & CLONE_PARENT_SETTID) {
+        if (!parent_tidptr)
+            return -EINVAL;
+        set_parent_tid = parent_tidptr;
     }
 
-    new_args->thread = get_new_thread(0);
-    if (!new_args->thread) {
+    struct shim_thread * thread = get_new_thread(0);
+    if (!thread) {
         ret = -ENOMEM;
         goto failed;
     }
 
-    new_args->stack     = user_stack_addr;
-    new_args->return_pc = *(void **) user_stack_addr;
+    IDTYPE tid = thread->tid;
 
-    if (flags & CLONE_PARENT_SETTID)
-        new_args->thread->set_child_tid = parent_tidptr;
-
-    if ((flags & CLONE_CHILD_SETTID) && (flags & CLONE_CHILD_CLEARTID)) {
-        ret = -EINVAL;
-        goto failed;
+    if (flags & CLONE_CHILD_SETTID) {
+        if (!child_tidptr) {
+            ret = -EINVAL;
+            goto failed;
+        }
+        thread->set_child_tid = child_tidptr;
     }
 
-    if (flags & CLONE_CHILD_SETTID)
-        new_args->thread->set_child_tid = child_tidptr;
-
     if (flags & CLONE_CHILD_CLEARTID)
         /* Implemented in shim_futex.c: release_clear_child_id */
-        new_args->thread->clear_child_tid = parent_tidptr;
+        thread->clear_child_tid = parent_tidptr;
 
     if (flags & CLONE_SETTLS) {
-        new_args->thread->tcb = tls;
+        if (!tls) {
+            ret = -EINVAL;
+            goto failed;
+        }
+        thread->tcb = tls;
     } else {
-        new_args->thread->tcb = NULL;
+        thread->tcb = NULL;
     }
 
-    if ((flags & CLONE_VM) != CLONE_VM)
-        debug("Fork-like behavior is not yet implemented in clone\n");
-
-    if ((flags & CLONE_FS) != CLONE_FS)
-        debug("clone without CLONE_FS is not yet implemented\n");
-
-    if ((flags & CLONE_SIGHAND) != CLONE_SIGHAND)
-        debug("clone without CLONE_SIGHAND is not yet implemented\n");
-
-    if ((flags & CLONE_SYSVSEM) != CLONE_SYSVSEM)
-        debug("clone without CLONE_SYSVSEM is not yet implemented\n");
-
-    if ((flags & CLONE_THREAD) != CLONE_THREAD)
-        new_args->thread->tgid = new_args->thread->tid;
+    if (!(flags & CLONE_THREAD))
+        thread->tgid = thread->tid;
 
     struct shim_handle_map * handle_map = get_cur_handle_map(self);
 
     if (flags & CLONE_FILES) {
-        set_handle_map(new_args->thread, handle_map);
+        set_handle_map(thread, handle_map);
     } else {
         /* if CLONE_FILES is not given, the new thread should receive
            a copy of current descriptor table */
@@ -226,10 +234,81 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
 
         get_handle_map(handle_map);
         dup_handle_map(&new_map, handle_map);
-        set_handle_map(new_args->thread, new_map);
+        set_handle_map(thread, new_map);
         put_handle_map(handle_map);
     }
 
+    if (!(flags & CLONE_VM)) {
+        __libc_tcb_t * tcb;
+        shim_tcb_t * old_shim_tcb = NULL;
+
+        if (thread->tcb) {
+            tcb = (__libc_tcb_t *) thread->tcb;
+        } else {
+            thread->tcb = tcb = (__libc_tcb_t *) self->tcb;
+            old_shim_tcb = __alloca(sizeof(shim_tcb_t));
+            memcpy(old_shim_tcb, &tcb->shim_tcb, sizeof(shim_tcb_t));
+        }
+
+        if (user_stack_addr) {
+            struct shim_vma * vma = NULL;
+            lookup_supervma(ALIGN_DOWN(user_stack_addr), allocsize, &vma);
+            assert(vma);
+            thread->stack_top = vma->addr + vma->length;
+            thread->stack_red = thread->stack = vma->addr;
+            tcb->shim_tcb.context.sp = user_stack_addr;
+            tcb->shim_tcb.context.ret_ip = *(void **) user_stack_addr;
+        } else {
+            tcb->shim_tcb.context.ret_ip = *(void **) tcb->shim_tcb.context.sp;
+        }
+
+        thread->is_alive = true;
+        thread->in_vm = false;
+        add_thread(thread);
+        set_as_child(self, thread);
+
+        if ((ret = do_migrate_process(&migrate_fork, NULL, NULL, thread)) < 0)
+            goto failed;
+
+        if (old_shim_tcb)
+            memcpy(&tcb->shim_tcb, old_shim_tcb, sizeof(shim_tcb_t));
+
+        lock(thread->lock);
+        handle_map = thread->handle_map;
+        thread->handle_map = NULL;
+        unlock(thread->lock);
+        if (handle_map)
+            put_handle_map(handle_map);
+
+        if (set_parent_tid)
+            *set_parent_tid = tid;
+
+        put_thread(thread);
+        return tid;
+    }
+
+    enable_locking();
+
+    struct clone_args * new_args = __alloca(sizeof(struct clone_args));
+    memset(new_args, 0, sizeof(struct clone_args));
+
+    new_args->create_event = DkNotificationEventCreate(0);
+    if (!new_args->create_event) {
+        ret = -PAL_ERRNO;
+        goto clone_thread_failed;
+    }
+
+    new_args->initialize_event = DkNotificationEventCreate(0);
+    if (!new_args->initialize_event) {
+        ret = -PAL_ERRNO;
+        goto clone_thread_failed;
+    }
+
+    new_args->thread    = thread;
+    new_args->parent    = self;
+    new_args->stack     = user_stack_addr;
+    new_args->return_pc = *(void **) user_stack_addr;
+
     // Invoke DkThreadCreate to spawn off a child process using the actual 
     // "clone" system call. DkThreadCreate allocates a stack for the child 
     // and then runs the given function on that stack However, we want our 
@@ -240,32 +319,30 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
                                           new_args, flags);
     if (!pal_handle) {
         ret = -PAL_ERRNO;
-        goto failed;
+        goto clone_thread_failed;
     }
 
-    new_args->thread->pal_handle = pal_handle;
+    thread->pal_handle = pal_handle;
+    thread->in_vm = thread->is_alive = true;
+    add_thread(thread);
+    set_as_child(self, thread);
 
-    new_args->thread->in_vm = new_args->thread->is_alive = true;
-    add_thread(new_args->thread);
-    set_as_child(NULL, new_args->thread);
-    put_thread(new_args->thread);
-
-    if (new_args->thread->set_child_tid)
-        *new_args->thread->set_child_tid = new_args->thread->tid;
+    if (set_parent_tid)
+        *set_parent_tid = tid;
 
     DkEventSet(new_args->create_event);
-
     DkObjectsWaitAny(1, &new_args->initialize_event, NO_TIMEOUT);
     DkObjectClose(new_args->initialize_event);
+    put_thread(thread);
+    return tid;
 
-    return new_args->thread->tid;
-
-failed:
+clone_thread_failed:
     if (new_args->create_event)
         DkObjectClose(new_args->create_event);
     if (new_args->initialize_event)
         DkObjectClose(new_args->initialize_event);
-    if (new_args->thread)
-        put_thread(new_args->thread);
+failed:
+    if (thread)
+        put_thread(thread);
     return ret;
 }

+ 1 - 2
LibOS/shim/src/sys/shim_exec.c

@@ -154,8 +154,7 @@ static void * __malloc (size_t size)
     addr = DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
 
     if (addr)
-        bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0,
-                   "checkpoint");
+        bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
 
     return addr;
 }

+ 4 - 6
LibOS/shim/src/sys/shim_fork.c

@@ -47,8 +47,7 @@ static void * __malloc (size_t size)
     addr = DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
 
     if (addr)
-        bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0,
-                   "checkpoint");
+        bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
 
     return addr;
 }
@@ -56,9 +55,9 @@ static void * __malloc (size_t size)
 #define malloc_method __malloc
 #include <shim_checkpoint.h>
 
-static int migrate_fork (struct shim_cp_store * cpstore,
-                         struct shim_process * process,
-                         struct shim_thread * thread, va_list ap)
+int migrate_fork (struct shim_cp_store * cpstore,
+                  struct shim_process * process,
+                  struct shim_thread * thread, va_list ap)
 {
     BEGIN_MIGRATION_DEF(fork, struct shim_process * proc,
                         struct shim_thread * thread)
@@ -104,7 +103,6 @@ int shim_do_fork (void)
     if (!new_thread)
         return -ENOMEM;
 
-    new_thread->stack    = cur_thread->stack;
     new_thread->tcb      = cur_thread->tcb;
     new_thread->tgid     = new_thread->tid;
     new_thread->in_vm    = false;

+ 126 - 20
LibOS/shim/src/sys/shim_futex.c

@@ -43,6 +43,11 @@
 #define FUTEX_MIN_VALUE 0
 #define FUTEX_MAX_VALUE 255
 
+struct futex_waiter {
+    struct shim_thread * thread;
+    struct list_head list;
+};
+
 static LIST_HEAD(futex_list);
 static LOCKTYPE futex_list_lock;
 
@@ -66,11 +71,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
         }
 
     if (futex) {
-        hdl = container_of(tmp, struct shim_handle, info.futex);
+        hdl = container_of(futex, struct shim_handle, info.futex);
         get_handle(hdl);
     } else {
-        struct shim_vma * vma_addr = NULL;
-
         if (!(hdl = get_new_handle())) {
             unlock(futex_list_lock);
             return -ENOMEM;
@@ -79,15 +82,6 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
         hdl->type = TYPE_FUTEX;
         futex = &hdl->info.futex;
         futex->uaddr = uaddr;
-        futex->vma = vma_addr;
-
-        futex->event = DkSynchronizationEventCreate(0);
-        if (futex->event == NULL) {
-            ret = -PAL_ERRNO;
-            unlock(futex_list_lock);
-            goto out;
-        }
-
         get_handle(hdl);
         INIT_LIST_HEAD(&futex->waiters);
         INIT_LIST_HEAD(&futex->list);
@@ -97,13 +91,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
     unlock(futex_list_lock);
     lock(hdl->lock);
 
-    struct futex_waiter {
-        struct shim_thread * thread;
-        struct list_head list;
-    };
-
     switch (op & FUTEX_CMD_MASK) {
         case FUTEX_WAIT:
+            debug("FUTEX_WAIT: %p (val = %d) vs %d\n", uaddr, *uaddr, val);
             if (*uaddr != val)
                 break;
 
@@ -118,7 +108,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             break;
 
         case FUTEX_WAKE: {
-            for (int cnt = 0 ; cnt < val ; cnt++) {
+            debug("FUTEX_WAKE: %p (val = %d)\n", uaddr, *uaddr);
+            int cnt;
+            for (cnt = 0 ; cnt < val ; cnt++) {
                 if (list_empty(&futex->waiters))
                     break;
 
@@ -126,9 +118,89 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
                                                           struct futex_waiter,
                                                           list);
 
+                debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n",
+                      waiter->thread->tid, uaddr, *uaddr);
                 list_del(&waiter->list);
                 thread_wakeup(waiter->thread);
             }
+            ret = cnt;
+            debug("FUTEX_WAKE done: %p (val = %d)\n", uaddr, *uaddr);
+            break;
+        }
+
+        case FUTEX_CMP_REQUEUE:
+            if (*uaddr != val3) {
+                ret = -EAGAIN;
+                break;
+            }
+
+        case FUTEX_REQUEUE: {
+            struct shim_futex_handle * futex2 = NULL;
+            struct shim_handle * hdl2;
+
+            lock(futex_list_lock);
+
+            list_for_each_entry(tmp, &futex_list, list)
+                if (tmp->uaddr == uaddr2) {
+                    futex2 = tmp;
+                    break;
+                }
+
+            if (futex2) {
+                hdl2 = container_of(futex2, struct shim_handle, info.futex);
+                get_handle(hdl2);
+            } else {
+                if (!(hdl2 = get_new_handle())) {
+                    unlock(futex_list_lock);
+                    ret = -ENOMEM;
+                    goto out;
+                }
+
+                hdl2->type = TYPE_FUTEX;
+                futex2 = &hdl2->info.futex;
+                futex2->uaddr = uaddr2;
+#if 0
+                futex2->event = DkSynchronizationEventCreate(0);
+                if (futex2->event == NULL) {
+                    ret = -PAL_ERRNO;
+                    unlock(futex_list_lock);
+                    put_handle(hdl2);
+                    goto out;
+                }
+#endif
+                get_handle(hdl2);
+                INIT_LIST_HEAD(&futex2->waiters);
+                INIT_LIST_HEAD(&futex2->list);
+                list_add_tail(&futex2->list, &futex_list);
+            }
+
+            unlock(futex_list_lock);
+
+            int cnt;
+            for (cnt = 0 ; cnt < val ; cnt++) {
+                if (list_empty(&futex->waiters))
+                    break;
+
+                struct futex_waiter * waiter = list_entry(futex->waiters.next,
+                                                          struct futex_waiter,
+                                                          list);
+
+                list_del(&waiter->list);
+                thread_wakeup(waiter->thread);
+            }
+
+            lock(hdl2->lock);
+            while (!list_empty(&futex->waiters)) {
+                struct futex_waiter * waiter = list_entry(futex->waiters.next,
+                                                          struct futex_waiter,
+                                                          list);
+
+                list_del(&waiter->list);
+                list_add_tail(&waiter->list, &futex2->waiters);
+            }
+            unlock(hdl2->lock);
+            put_handle(hdl2);
+            ret = cnt;
             break;
         }
 
@@ -137,6 +209,7 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             break;
 
         default:
+            debug("unsupported futex op: 0x%x\n", op);
             ret = -ENOSYS;
             break;
     }
@@ -205,7 +278,24 @@ void release_robust_list (struct robust_list_head * head)
         if (!futex)
             continue;
 
-        DkEventSet(futex->event);
+        struct shim_handle * hdl =
+            container_of(futex, struct shim_handle, info.futex);
+        get_handle(hdl);
+        lock(hdl->lock);
+
+        debug("release robust list: %p\n", futex_addr);
+        *(int *) futex_addr = 0;
+        while (!list_empty(&futex->waiters)) {
+            struct futex_waiter * waiter = list_entry(futex->waiters.next,
+                                                      struct futex_waiter,
+                                                      list);
+
+            list_del(&waiter->list);
+            thread_wakeup(waiter->thread);
+        }
+
+        unlock(hdl->lock);
+        put_handle(hdl);
     }
 }
 
@@ -230,6 +320,22 @@ void release_clear_child_id (int * clear_child_tid)
     if (!futex)
         return;
 
+    struct shim_handle * hdl =
+            container_of(futex, struct shim_handle, info.futex);
+    get_handle(hdl);
+    lock(hdl->lock);
+
     debug("release futex at %p\n", clear_child_tid);
-    DkEventSet(futex->event);
+    *clear_child_tid = 0;
+    while (!list_empty(&futex->waiters)) {
+        struct futex_waiter * waiter = list_entry(futex->waiters.next,
+                                                  struct futex_waiter,
+                                                  list);
+
+        list_del(&waiter->list);
+        thread_wakeup(waiter->thread);
+    }
+
+    unlock(hdl->lock);
+    put_handle(hdl);
 }

+ 1 - 1
LibOS/shim/src/sys/shim_mmap.c

@@ -94,7 +94,7 @@ void * shim_do_mmap (void * addr, size_t length, int prot, int flags, int fd,
     }
 
     ret = bkeep_mmap((void *) mapped, mapped_end - mapped, prot,
-                     flags, hdl, offset, "user");
+                     flags, hdl, offset, NULL);
     assert(!ret);
     if (hdl)
         put_handle(hdl);

+ 4 - 7
LibOS/shim/src/sys/shim_sigaction.c

@@ -165,8 +165,7 @@ static int __kill_proc (struct shim_thread * thread, void * arg,
     if (!warg->use_ipc && !thread->in_vm)
         return 0;
 
-    /* only signal thread leader */
-    if (thread->tgid != warg->id || thread->tid != thread->tgid)
+    if (thread->tgid != warg->id)
         return 0;
 
     if (warg->current == thread)
@@ -185,7 +184,6 @@ static int __kill_proc (struct shim_thread * thread, void * arg,
         return (!ipc_pid_kill_send(warg->sender, warg->id, KILL_PROCESS,
                                    warg->sig)) ? 1 : 0;
     } else {
-
         lock(thread->lock);
 
         if (!thread->is_alive)
@@ -216,7 +214,7 @@ static int __kill_proc_simple (struct shim_simple_thread * sthread,
     struct walk_arg * warg = (struct walk_arg *) arg;
     int srched = 0;
 
-    if (sthread->tgid != warg->id || sthread->tgid != sthread->tid)
+    if (sthread->tgid != warg->id)
         return 0;
 
     lock(sthread->lock);
@@ -276,8 +274,7 @@ static int __kill_pgroup (struct shim_thread * thread, void * arg,
     if (!warg->use_ipc && !thread->in_vm)
         return 0;
 
-    /* only signal thread leader */
-    if (thread->pgid != warg->id || thread->tgid != thread->tid)
+    if (thread->pgid != warg->id)
         return 0;
 
     if (warg->current == thread)
@@ -312,7 +309,7 @@ static int __kill_pgroup_simple (struct shim_simple_thread * sthread,
     struct walk_arg * warg = (struct walk_arg *) arg;
     int srched = 0;
 
-    if (sthread->pgid != warg->id || sthread->tgid != sthread->tid)
+    if (sthread->pgid != warg->id)
         return 0;
 
     lock(sthread->lock);

+ 19 - 22
LibOS/shim/src/syscallas.S

@@ -22,8 +22,8 @@
 
 #include <shim_tls.h>
 
-        .text
-        .globl syscalldb
+.text
+        .global syscalldb
         .type syscalldb, @function
         .extern shim_table
 
@@ -42,18 +42,10 @@ syscalldb:
         .cfi_def_cfa_register 6
 
         pushq %rbx
-        pushq %r12
 
-        movq %rax, %fs:(SHIM_TCB_OFFSET + 24)
-        movq %rsp, %rbx
-        addq $152, %rbx
-        movq %rbx, %fs:(SHIM_TCB_OFFSET + 32)
-        movq (%rbx), %rbx
-        movq %rbx, %fs:(SHIM_TCB_OFFSET + 40)
-
-        movq shim_table@GOTPCREL(%rip), %rbx
-        movq (%rbx,%rax,8), %r12
-        cmp $0, (%r12)
+        leaq shim_table(%rip), %rbx
+        movq (%rbx,%rax,8), %rbx
+        cmp $0, (%rbx)
         je isundef
 
 isdef:
@@ -63,16 +55,29 @@ isdef:
         pushq %rcx
         pushq %r8
         pushq %r9
+        pushq %r12
         pushq %r13
         pushq %r14
         pushq %r15
+
+        movq %rax, %fs:(SHIM_TCB_OFFSET + 24)
+        leaq 224(%rsp), %rax
+        movq %rax, %fs:(SHIM_TCB_OFFSET + 32)
+        movq (%rax), %rax
+        movq %rax, %fs:(SHIM_TCB_OFFSET + 40)
         movq %rsp, %fs:(SHIM_TCB_OFFSET + 48)
 
-        call *(%rbx,%rax,8)
+        call *%rbx
+
+        movq $0, %fs:(SHIM_TCB_OFFSET + 24)
+        movq $0, %fs:(SHIM_TCB_OFFSET + 32)
+        movq $0, %fs:(SHIM_TCB_OFFSET + 40)
+        movq $0, %fs:(SHIM_TCB_OFFSET + 48)
 
         popq %r15
         popq %r14
         popq %r13
+        popq %r12
         popq %r9
         popq %r8
         popq %rcx
@@ -86,17 +91,9 @@ isundef:
         movq $-38, %rax
 
 ret:
-        popq %r12
         popq %rbx
         popq %rbp
-
-        movq $0, %fs:(SHIM_TCB_OFFSET + 24)
-        movq $0, %fs:(SHIM_TCB_OFFSET + 32)
-        movq $0, %fs:(SHIM_TCB_OFFSET + 40)
-        movq $0, %fs:(SHIM_TCB_OFFSET + 48)
-
         addq $128, %rsp
-
         retq
 
         .cfi_endproc

+ 4 - 5
LibOS/shim/test/Makefile

@@ -26,12 +26,11 @@ manifest: manifest.template
 	rm -rf $@
 	cp $@.template $@
 
-.PHONY: pal palsec
-
 pal:
-	ln -sf $(level)../../../Pal/src/libpal.so
-palsec:
-	ln -sf $(level)../../../Pal/src/libpal_sec.so libpal.so
+	[ ! -f $(level)../../../Pal/src/pal ] || ln -sf $(level)../../../Pal/src/pal pal
+
+pal_sec:
+	[ ! -f $(level)../../../Pal/src/pal_sec ] || ln -sf $(level)../../../Pal/src/pal_sec pal_sec
 
 # Regression Test
 rtest:	$(rtarget)

+ 3 - 5
LibOS/shim/test/apps/Makefile

@@ -1,26 +1,24 @@
 apps = lmbench gcc busybox lighttpd bash apache make
 
-targets = pal
+targets = pal pal_sec
 clean-extra = clean-all
 
 level = ../
 include ../Makefile
 
 manifest_rules = \
+	-e 's:\$$(PAL):$(shell pwd)/pal_loader:g' \
 	-e 's:\$$(PWD):$(shell pwd)/$(appdir):g' \
 	-e 's:\$$(BIN):$(subst .manifest,,$(notdir $@)):g' \
 	-e 's:\$$(SHIMPATH):$(shell readlink -f ../../src/libsysdb.so):g' \
 	-e 's:\$$(GLIBCDIR):$(shell readlink -f $(glibc_dir)):g' \
 	$(extra_rules)
 
-%.manifest: %.manifest.template libpal.so
+%.manifest: %.manifest.template
 	rm -f $@ $@.backup
 	sed $(manifest_rules) $< >$@
 	chmod +x $@
 
-libpal.so:
-	make pal
-
 build-all:
 	for f in $(apps); do (cd $$f; make $(DEBUG) || true; cd ..); done
 

+ 1 - 1
LibOS/shim/test/apps/apache/httpd.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:obj/bin/httpd

+ 1 - 1
LibOS/shim/test/apps/bash/bash-local.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:bash-local

+ 1 - 1
LibOS/shim/test/apps/bash/bash.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/bin/bash

+ 1 - 1
LibOS/shim/test/apps/busybox/busybox.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:busybox

+ 1 - 1
LibOS/shim/test/apps/busybox/busybox_nofork.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:busybox_nofork

+ 1 - 1
LibOS/shim/test/apps/gcc/g++-huge.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/g++

+ 1 - 1
LibOS/shim/test/apps/gcc/g++-local.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.interp = file:$(SHIM)build/elf/ld.so
 loader.preload = file:$(SHIM)build/libsysdb.so

+ 1 - 1
LibOS/shim/test/apps/gcc/g++.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/g++

+ 1 - 1
LibOS/shim/test/apps/gcc/gcc-huge.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/gcc

+ 1 - 1
LibOS/shim/test/apps/gcc/gcc-local.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.interp = file:$(SHIMROOT)build/elf/ld.so
 loader.preload = file:$(SHIMROOT)build/libsysdb.so

+ 1 - 1
LibOS/shim/test/apps/gcc/gcc.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/gcc

+ 1 - 1
LibOS/shim/test/apps/lighttpd/lighttpd-angel.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:$(PWD)build/sbin/lighttpd-angel

+ 1 - 1
LibOS/shim/test/apps/lighttpd/lighttpd.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:$(PWD)build/sbin/lighttpd

+ 15 - 9
LibOS/shim/test/apps/lmbench/lmbench-2.5/src/lat_syscall.c

@@ -12,23 +12,23 @@ char	*id = "$Id$\n";
 #define	FNAME "/usr/include/x86_64-linux-gnu/sys/types.h"
 
 void
-do_write(int fd)
+do_write(int fd, char *s)
 {
 	char	c;
 
 	if (write(fd, &c, 1) != 1) {
-		perror("/dev/null");
+		perror(s);
 		return;
 	}
 }
 
 void
-do_read(int fd)
+do_read(int fd, char *s)
 {
 	char	c;
 
 	if (read(fd, &c, 1) != 1) {
-		perror("/dev/zero");
+		perror(s);
 		return;
 	}
 }
@@ -81,17 +81,23 @@ main(int ac, char **av)
 		BENCH(getppid(), 0);
 		micro("Simple syscall", get_n());
 	} else if (!strcmp("write", av[1])) {
-		fd = open("/dev/null", 1);
-		BENCH(do_write(fd), 0);;
+		file = av[2] ? av[2] : "/dev/null";
+		fd = open(file, 1);
+		if (fd == -1) {
+			fprintf(stderr, "Write from %s: %s\n", file, strerror(errno));
+			return(1);
+		}
+		BENCH(do_write(fd, file), 0);;
 		micro("Simple write", get_n());
 		close(fd);
 	} else if (!strcmp("read", av[1])) {
-		fd = open("/dev/zero", 0);
+		file = av[2] ? av[2] : "/dev/null";
+		fd = open(file, 0);
 		if (fd == -1) {
-			fprintf(stderr, "Read from /dev/zero: -1");
+			fprintf(stderr, "Read from %s: %s\n", file, strerror(errno));
 			return(1);
 		}
-		BENCH(do_read(fd), 0);
+		BENCH(do_read(fd, file), 0);
 		micro("Simple read", get_n());
 		close(fd);
 	} else if (!strcmp("stat", av[1])) {

+ 1 - 1
LibOS/shim/test/apps/lmbench/manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:$(PWD)lmbench-2.5/bin/linux/$(BIN)

+ 1 - 1
LibOS/shim/test/apps/make/make-huge.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/make

+ 1 - 1
LibOS/shim/test/apps/make/make-local.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:make-local

+ 1 - 1
LibOS/shim/test/apps/make/make.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/make

+ 1 - 1
LibOS/shim/test/apps/python/python.manifest.template

@@ -1,4 +1,4 @@
-#!$(PWD)../libpal.so
+#!$(PAL)
 
 loader.preload = file:$(SHIMPATH)
 loader.exec = file:/usr/bin/python

+ 2 - 2
LibOS/shim/test/inline/Makefile

@@ -2,7 +2,7 @@ INLINE_TESTS_CPP = $(patsubst %.cpp,%,$(wildcard *.cpp))
 INLINE_TESTS = $(patsubst %.c,%,$(wildcard *.c))
 
 rtarget = helloworld fork vfork
-targets = $(rtarget) manifest pal
+targets = $(rtarget) manifest pal pal_sec
 clean-extra = clean-exec
 
 level = ../
@@ -23,4 +23,4 @@ test-vfork = grep -q "Hello, Dad" OUTPUT && grep -q "Hello, Kid" OUTPUT
 
 clean-exec:
 	find -type f -executable -exec rm {} \;
-	rm -rf manifest libpal.so
+	rm -rf manifest pal pal_sec

+ 2 - 2
LibOS/shim/test/native/Makefile

@@ -5,7 +5,7 @@ NATIVE_TESTS_STATIC = static
 NATIVE_TESTS = $(filter-out $(NATIVE_TESTS_STATIC),$(patsubst %.c,%,$(wildcard *.c)))
 
 targets = $(NATIVE_TESTS) $(NATIVE_TESTS_CPP) $(NATIVE_TESTS_STATIC) \
-	  manifest static.manifest pal
+	  manifest static.manifest pal pal_sec
 rtarget = helloworld clone vfork fork exec vfork_exec errno dup time \
 	  helloworld.pthread udp tcp unix file dev
 clean-extra = clean-exec
@@ -47,4 +47,4 @@ test-helloworld = grep -q "Hello world" OUTPUT
 
 clean-exec:
 	find -type f -executable -exec rm {} \;
-	rm -rf manifest static.manifest libpal.so
+	rm -rf manifest static.manifest pal pal_sec

+ 4 - 0
LibOS/shim/test/native/manifest.template

@@ -10,6 +10,10 @@ fs.mount.other.lib.type = chroot
 fs.mount.other.lib.path = /lib
 fs.mount.other.lib.uri = file:../../../build
 
+fs.mount.other.bin.type = chroot
+fs.mount.other.bin.path = /bin
+fs.mount.other.bin.uri = file:/bin
+
 # allow to bind on port 8000
 net.rules.1 = 127.0.0.1:8000:0.0.0.0:0-65535
 # allow to connect to port 8000

+ 0 - 1
LibOS/shim/test/native/start.c

@@ -28,6 +28,5 @@ int main (int argc, char ** argv, char ** envp)
     unsigned long long overhead = (msec4 - msec3) / OVERHEAD_TIMES;
 
     printf("%llu\n", msec2 - msec1 - overhead);
-
     return 0;
 }

+ 12 - 0
LibOS/shim/test/native/system.c

@@ -0,0 +1,12 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+/* a simple helloworld test */
+
+#include <stdlib.h>
+
+int main(int argc, char ** argv)
+{
+    system("./helloworld");
+    return 0;
+}

+ 1 - 1
Pal/ipc/linux/graphene-ipc.c

@@ -895,7 +895,7 @@ out:
 		mutex_unlock(&pending->receiver_lock);
 		up_write(&current_tsk->mm->mmap_sem);
 
-		rv = copy_to_user(((struct gipc_recv *)arg)->addr, addrs,
+		rv = copy_to_user(gr.addr, addrs,
 				  sizeof(unsigned long) * gr.entries);
 		if (rv) {
 			printk(KERN_ERR "Graphene error: bad buffer %p\n",

+ 26 - 11
Pal/src/Makefile

@@ -9,18 +9,21 @@ LD	= ld
 CFLAGS	= -Wall -fPIC -O2 -std=gnu99 -fgnu89-inline -U_FORTIFY_SOURCE \
 	  -fno-omit-frame-pointer \
 	  -fno-stack-protector -fno-builtin
-LDFLAGS	= -shared -nostdlib --version-script pal.map -z combreloc -z defs \
-	  -T pal.lds
+LDFLAGS	= -shared -nostdlib -z combreloc -z defs
 ARFLAGS	=
 
 pal_loader = libpal.so
-pal_lib = libpal.a
+pal_sec =
+pal_lib = libpal.so
+pal_lib_deps =
+pal_lib_post =
+pal_static = libpal.a
 
 include host/$(OS)/Makefile.am
 
 CFLAGS	+= -I. -I../include -Ihost/$(OS) -I../lib
 
-pal_target = $(pal_loader) $(pal_lib)
+pal_target = $(pal_lib) $(pal_lib_post) $(pal_static) $(pal_loader) $(pal_sec) pal pal_sec
 defs	= -DIN_PAL -DSRCDIR="$(PWD)/"
 objs	= $(addprefix db_,streams memory threading semaphore events process \
 	    object main misc ipc exception rtld) slab printf
@@ -28,14 +31,14 @@ graphene_lib = ../lib/graphene-lib.a
 host_lib = host/$(OS)/libpal-$(OS).a
 headers	= $(wildcard *.h) $(wildcard ../lib/*.h)
 
-all: $(pal_target) security
+all: $(pal_target)
 
 debug: debug = debug
 debug: CC = gcc -gdwarf-2 -g3
 debug: CFLAGS += -DDEBUG
-debug: $(pal_target) security
+debug: $(pal_target)
 
-.PHONY: security $(host_lib) $(graphene_lib)
+.PHONY: $(host_lib) $(graphene_lib)
 
 $(graphene_lib):
 	make -C ../lib $(debug)
@@ -43,15 +46,27 @@ $(graphene_lib):
 $(host_lib):
 	@[ ! -d host/$(OS) ] || make -C host/$(OS) $(debug)
 
-security:
+ifneq ($(pal_sec),)
+$(pal_sec):
 	@[ ! -d security/$(OS) ] || make -C security/$(OS) $(debug)
 
-$(pal_loader): $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
-	    $(host_lib) $(graphene_lib)
+pal_sec: $(pal_sec)
+	ln -sf $(pal_sec) pal_sec
+endif
+
+$(pal_lib): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib) $(pal_lib_deps)
 	@echo [ libpal.exe ]
 	$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) $(LDFLAGS-suffix)
 
-$(pal_lib): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
+pal: $(pal_loader)
+	ln -sf $(pal_loader) pal
+
+ifneq ($(pal_lib_post),)
+$(pal_lib_post): $(pal_lib)
+	make -C host/$(OS) ../../$@
+endif
+
+$(pal_static): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 	@echo [ $@ ]
 	$(AR) $(ARFLAGS) $@ $^ $(ARFLAGS-suffix)
 

+ 78 - 65
Pal/src/db_rtld.c

@@ -52,39 +52,6 @@ void __attribute__((noinline)) __assert (void)
 }
 #endif
 
-/* This structure communicates dl state to the debugger.  The debugger
-   normally finds it via the DT_DEBUG entry in the dynamic section, but in
-   a statically-linked program there is no dynamic section for the debugger
-   to examine and it looks for this particular symbol name.  */
-struct r_debug pal_r_debug =
-        { 1, NULL, (ElfW(Addr)) &pal_dl_debug_state, RT_CONSISTENT, 0 };
-
-extern __typeof(pal_r_debug) _r_debug
-    __attribute ((alias ("pal_r_debug")));
-
-    /* This function exists solely to have a breakpoint set on it by the
-   debugger.  The debugger is supposed to find this function's address by
-   examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
-   for this particular symbol name in the PT_INTERP file.  */
-
-/* The special symbol name is set as breakpoint in gdb */
-void __attribute__((noinline)) pal_dl_debug_state (void)
-{
-}
-
-extern __typeof(pal_dl_debug_state) _dl_debug_state
-    __attribute ((alias ("pal_dl_debug_state")));
-
-void __attribute__((noinline)) _dl_debug_state_trigger (void)
-{
-    struct link_map *l = pal_r_debug.r_map;
-    for ( ; l ; l = l->l_next)
-        if (!memcmp(l->l_name, "file:", 5))
-            l->l_name += 5;
-
-    pal_dl_debug_state();
-}
-
 /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
 static ElfW(Addr) resolve_map (const char **strtab, ElfW(Sym) ** ref)
 {
@@ -251,7 +218,7 @@ call_lose:
     /* Scan the program header table, collecting its load commands.  */
     struct loadcmd {
         ElfW(Addr) mapstart, mapend, dataend, allocend;
-        off_t mapoff;
+        unsigned int mapoff;
         int prot;
     } loadcmds[l->l_phnum], *c;
 
@@ -309,18 +276,13 @@ call_lose:
                     has_holes = true;
 
                 /* Optimize a common case.  */
-#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
-                c->prot = (PF_TO_PROT
-                          >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
-#else
                 c->prot = 0;
                 if (ph->p_flags & PF_R)
-                    c->prot |= PROT_READ;
+                    c->prot |= PAL_PROT_READ;
                 if (ph->p_flags & PF_W)
-                    c->prot |= PROT_WRITE;
+                    c->prot |= PAL_PROT_WRITE;
                 if (ph->p_flags & PF_X)
-                    c->prot |= PROT_EXEC;
-#endif
+                    c->prot |= PAL_PROT_EXEC;
                 break;
 
             case PT_TLS:
@@ -390,7 +352,7 @@ map_error:
                unallocated.  Then jump into the normal segment-mapping loop to
                handle the portion of the segment past the end of the file
                mapping.  */
-            _DkVirtualMemoryProtect((caddr_t) (l->l_addr + c->mapend),
+            _DkVirtualMemoryProtect((void *) (l->l_addr + c->mapend),
                                     loadcmds[nloadcmds - 1].mapstart - c->mapend,
                                     PAL_PROT_NONE);
 
@@ -414,12 +376,12 @@ map_error:
         }
 
 postmap:
-        if (c->prot & PROT_EXEC) {
+        if (c->prot & PAL_PROT_EXEC) {
             l->l_text_start = l->l_addr + c->mapstart;
             l->l_text_end = l->l_addr + c->mapend;
         }
 
-        if (c->prot & PROT_WRITE) {
+        if (c->prot & PAL_PROT_WRITE) {
             l->l_data_start = l->l_addr + c->mapstart;
             l->l_data_end = l->l_addr + c->mapend;
         }
@@ -447,7 +409,7 @@ postmap:
 
             if (zerosec > zero) {
                 /* Zero the final part of the last section of the segment.  */
-                if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
+                if (__builtin_expect ((c->prot & PAL_PROT_WRITE) == 0, 0))
                 {
                     /* Dag nab it.  */
                     if (_DkVirtualMemoryProtect((void *) ALLOC_ALIGNDOWN(zero),
@@ -458,7 +420,7 @@ postmap:
                     }
                 }
                 memset ((void *) zero, '\0', zerosec - zero);
-                if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
+                if (__builtin_expect ((c->prot & PAL_PROT_WRITE) == 0, 0))
                     _DkVirtualMemoryProtect((void *) ALLOC_ALIGNDOWN(zero),
                                             allocsize, c->prot);
             }
@@ -563,16 +525,12 @@ void free_elf_object (struct link_map * map)
     _DkVirtualMemoryFree((void *) map->l_map_start,
                          map->l_map_end - map->l_map_start);
 
-    pal_sec_info._r_debug->r_state = RT_DELETE;
-    pal_sec_info._dl_debug_state();
-
     if (map->l_prev)
         map->l_prev->l_next = map->l_next;
     if (map->l_next)
         map->l_next->l_prev = map->l_prev;
 
-    pal_sec_info._r_debug->r_state = RT_CONSISTENT;
-    pal_sec_info._dl_debug_state();
+    _DkDebugDelMap(map);
 
     if (loaded_libraries == map)
         loaded_libraries = map->l_next;
@@ -675,9 +633,6 @@ int load_elf_object_by_handle (PAL_HANDLE handle, enum object_type type)
         }
     }
 
-    pal_sec_info._r_debug->r_state = RT_ADD;
-    pal_sec_info._dl_debug_state();
-
     struct link_map * map;
 
     if (!(map = map_elf_object_by_handle(handle, type, &fb, len, true))) {
@@ -706,8 +661,7 @@ int load_elf_object_by_handle (PAL_HANDLE handle, enum object_type type)
     map->l_prev = prev;
     map->l_next = NULL;
 
-    pal_sec_info._r_debug->r_state = RT_CONSISTENT;
-    pal_sec_info._dl_debug_state();
+    _DkDebugAddMap(map);
 
     return 0;
 
@@ -969,18 +923,13 @@ static int relocate_elf_object (struct link_map * l)
             if (ret < 0)
                 return ret;
 
-#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
-            r->prot = (PF_TO_PROT
-                      >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
-#else
             r->prot = 0;
             if (ph->p_flags & PF_R)
-                r->prot |= PROT_READ;
+                r->prot |= PAL_PROT_READ;
             if (ph->p_flags & PF_W)
-                r->prot |= PROT_WRITE;
+                r->prot |= PAL_PROT_WRITE;
             if (ph->p_flags & PF_X)
-                r->prot |= PROT_EXEC;
-#endif
+                r->prot |= PAL_PROT_EXEC;
             r->next = textrels;
             textrels = r;
         }
@@ -1026,6 +975,70 @@ static int relocate_elf_object (struct link_map * l)
     return 0;
 }
 
+void DkDebugAttachBinary (PAL_STR uri, PAL_PTR start_addr)
+{
+    if (memcmp(uri, "file:", 5))
+        return;
+
+    struct link_map * l = new_elf_object(uri + 5, OBJECT_EXTERNAL);
+
+    /* This is the ELF header.  We read it in `open_verify'.  */
+    const ElfW(Ehdr) * header = start_addr;
+
+    l->l_entry = header->e_entry;
+    l->l_phnum = header->e_phnum;
+    l->l_addr = l->l_map_start = (ElfW(Addr)) start_addr;
+
+    ElfW(Phdr) * phdr = (void *) (start_addr + header->e_phoff);
+    const ElfW(Phdr) * ph;
+
+    for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
+        switch (ph->p_type)
+        {
+            /* These entries tell us where to find things once the file's
+               segments are mapped in.  We record the addresses it says
+               verbatim, and later correct for the run-time load address.  */
+            case PT_DYNAMIC:
+                l->l_ld = l->l_real_ld = (void *) ph->p_vaddr;
+                l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+                break;
+
+            case PT_PHDR:
+                l->l_phdr = (void *) ph->p_vaddr;
+                break;
+
+            case PT_LOAD: {
+                ElfW(Addr) start = l->l_addr + ALLOC_ALIGNDOWN(ph->p_vaddr);
+                ElfW(Addr) end = l->l_addr + ALLOC_ALIGNDOWN(ph->p_vaddr +
+                                                             ph->p_memsz);
+
+                if (ph->p_flags & PF_X) {
+                    l->l_text_start = start;
+                    l->l_text_end = end;
+                }
+
+                if (ph->p_flags & PF_W) {
+                    l->l_data_start = start;
+                    l->l_data_end = end;
+                }
+
+                l->l_map_end = end;
+                break;
+            }
+
+            case PT_GNU_RELRO:
+                l->l_relro_addr = ph->p_vaddr;
+                l->l_relro_size = ph->p_memsz;
+                break;
+        }
+
+    _DkDebugAddMap(l);
+}
+
+void DkDebugDetachBinary (PAL_PTR start_addr)
+{
+}
+
 void start_execution (int argc, const char ** argv)
 {
     /* First we will try to run all the preloaded libraries which come with

+ 4 - 4
Pal/src/dynamic_link.h

@@ -39,23 +39,23 @@
    copying memory, breaking the very code written to handle the
    unaligned cases.  */
 #if ! ELF_MACHINE_NO_REL
-static void __attribute__((always_inline))
+static inline void __attribute__((always_inline))
 elf_machine_rel (ElfW(Dyn) ** l_info, ElfW(Addr) l_addr,
                  ElfW(Rel) *reloc, ElfW(Sym) *sym, void *const reloc_addr,
                  bool rel, bool rel_relative);
 
-static void __attribute__((always_inline))
+static inline void __attribute__((always_inline))
 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
                           void *const reloc_addr);
 #endif
 
 #if ! ELF_MACHINE_NO_RELA
-static void __attribute__((always_inline))
+static inline void __attribute__((always_inline))
 elf_machine_rela (ElfW(Dyn) ** l_info, ElfW(Addr) l_addr,
                   ElfW(Rela) *reloc, ElfW(Sym) *sym, void *const reloc_addr,
                   bool rel, bool rel_relative);
 
-static void __attribute__((always_inline))
+static inline void __attribute__((always_inline))
 elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
                            void *const reloc_addr);
 #endif

+ 2 - 1
Pal/src/host/Linux/Makefile

@@ -16,7 +16,8 @@ ARFLAGS	=
 
 host_target = libpal-Linux.a
 
-defs	= -DIN_PAL -DGDB_SCRIPT="$(CURDIR)/pal-gdb.py"
+defs	= -DIN_PAL -DPAL_LOADER_PATH="$(shell readlink -f ../../pal)" \
+	  -DGDB_SCRIPT="$(CURDIR)/pal-gdb.py"
 objs	= $(addprefix db_,files devices pipes sockets streams memory threading \
 	    semaphore mutex events process object main rtld misc ipc \
 	    exception) manifest clone-x86_64 gettimeofday-x86_64

+ 7 - 0
Pal/src/host/Linux/Makefile.am

@@ -1 +1,8 @@
 # Add host-specific compilation rules here
+HOST_DIR = host/$(OS)
+SEC_DIR = security/$(OS)
+
+pal_sec = $(SEC_DIR)/libpal_sec.so
+pal_lib_deps = $(HOST_DIR)/pal.map $(HOST_DIR)/pal.lds
+
+LDFLAGS += --version-script $(HOST_DIR)/pal.map -T $(HOST_DIR)/pal.lds

+ 8 - 32
Pal/src/host/Linux/db_main.c

@@ -70,7 +70,6 @@ static gid_t gid;
 static ElfW(Addr) sysinfo_ehdr;
 #endif
 
-static const char * libname;
 static const char * child_args;
 
 static void pal_init_bootstrap (void * args, int * pargc,
@@ -124,9 +123,7 @@ static void pal_init_bootstrap (void * args, int * pargc,
 #endif
         }
 
-    if (memcmp(*argv + strlen(*argv) - LIBRARY_NAMELEN, LIBRARY_NAME,
-               LIBRARY_NAMELEN) == 0) {
-        libname = *argv;
+    if (!memcmp(*argv + strlen(*argv) - 3, "pal", 3)) {
         argv++;
         argc--;
 
@@ -198,8 +195,6 @@ int read_shebang (const char ** argv)
 
     if (IS_ERR(fd)) {
 bad_shebang:
-        printf("The program is either not libpal.so or script with "
-               "shebang. I can't recognize.\n");
         INLINE_SYSCALL(close, 1, fd);
         return -PAL_ERROR_INVAL;
     }
@@ -215,14 +210,8 @@ bad_shebang:
         goto bad_shebang;
 
     char * p = &buffer[2];
-    while (*p && *p != ' ' && *p != '\r' && *p != '\n');
-    p++;
-
-    if (!libname) {
-        char * name = malloc(p - buffer - 1);
-        memcpy(name, &buffer[2], p - buffer - 2);
-        libname = name;
-    }
+    while (*p && *p != ' ' && *p != '\r' && *p != '\n')
+        p++;
 
     int len = strlen(*argv);
     PAL_HANDLE manifest = malloc(HANDLE_SIZE(file) + len + 1);
@@ -265,7 +254,7 @@ void pal_linux_main (void * args)
 
     init_slab_mgr();
 
-    setup_pal_map(XSTRINGIFY(SRCDIR) "/" LIBRARY_NAME, pal_dyn, pal_addr);
+    setup_pal_map(XSTRINGIFY(SRCDIR) "/pal", pal_dyn, pal_addr);
 
     /* jump to main function */
     pal_main(argc, argv, envp);
@@ -345,9 +334,6 @@ int _DkInitHost (int * pargc, const char *** pargv)
         return -PAL_ERROR_INVAL;
     }
 
-    if (pal_sec_info.pal_name)
-        libname = pal_sec_info.pal_name;
-
     pal_linux_config.pid = INLINE_SYSCALL(getpid, 0);
 
     signal_setup();
@@ -359,12 +345,8 @@ int _DkInitHost (int * pargc, const char *** pargv)
         goto read_manifest;
     }
 
-    if (!libname) {
-        if ((ret = read_shebang(argv)) < 0)
-            return ret;
-
+    if (!(ret = read_shebang(argv)) < 0)
         goto read_manifest;
-    }
 
     PAL_HANDLE file = NULL;
     const char * file_uri = NULL;
@@ -468,12 +450,6 @@ read_manifest:
     }
 
 done_init:
-    if (!child_args && pal_config.exec)
-        printf("Program \"%s\" loaded in Graphene Library OS\n",
-               pal_config.exec);
-
-    pal_config.lib_name = libname;
-
     if (!child_args && !pal_sec_info.domain_id) {
         if ((ret = create_domain_dir()) < 0)
             return ret;
@@ -490,9 +466,9 @@ done_init:
 #endif
 
     if (!pal_sec_info.mcast_port) {
-        do {
-            getrand(&pal_sec_info.mcast_port, sizeof(unsigned short));
-        } while (pal_sec_info.mcast_port < 1024);
+        unsigned short mcast_port;
+        getrand(&mcast_port, sizeof(unsigned short));
+        pal_sec_info.mcast_port = mcast_port % 1024;
     }
 
     __pal_control.broadcast_stream = pal_sec_info.mcast_handle ? :

+ 2 - 2
Pal/src/host/Linux/db_misc.c

@@ -55,10 +55,10 @@ unsigned long _DkSystemTimeQuery (void)
 
 #if USE_VDSO_GETTIME == 1
     if (__vdso_clock_gettime) {
-        ret = __vdso_clock_gettime(CLOCK_MONOTONIC, &time);
+        ret = __vdso_clock_gettime(CLOCK_REALTIME, &time);
     } else {
 #endif
-        ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_MONOTONIC, &time);
+        ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_REALTIME, &time);
 #if USE_VDSO_GETTIME == 1
     }
 #endif

+ 1 - 1
Pal/src/host/Linux/db_pipes.c

@@ -165,7 +165,7 @@ static int pipe_waitforclient (PAL_HANDLE handle, PAL_HANDLE * client)
     *client = clnt;
 #else
     PAL_IDX connid;
-    getrand(&connid, sizeof(PAL_IDX));
+    system_getrand(&connid, sizeof(PAL_IDX));
     PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipe));
     SET_HANDLE_TYPE(clnt, pipecli);
     clnt->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);

+ 2 - 2
Pal/src/host/Linux/db_process.c

@@ -106,7 +106,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
     const char ** new_args = __alloca(sizeof(const char *) * (nargs + 3));
     int bufsize = STRARG_SIZE;
     char * argbuf = __alloca(STRARG_SIZE);
-    new_args[0] = pal_config.lib_name;
+    new_args[0] = PAL_LOADER;
     new_args[1] = argbuf;
     if (args)
         memcpy(new_args + 2, args, sizeof(const char *) * nargs);
@@ -170,7 +170,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
         if (manifest_fd >= 0)
             INLINE_SYSCALL(fcntl, 3, manifest_fd, F_SETFD, 0);
 
-        rete = INLINE_SYSCALL(execve, 3, pal_config.lib_name, new_args,
+        rete = INLINE_SYSCALL(execve, 3,  PAL_LOADER, new_args,
                               pal_config.environments);
 
         /* shouldn't get to here */

+ 106 - 23
Pal/src/host/Linux/db_rtld.c

@@ -43,7 +43,111 @@
 
 #include "elf-x86_64.h"
 
-struct link_map * rtld_map = NULL;
+/* This structure communicates dl state to the debugger.  The debugger
+   normally finds it via the DT_DEBUG entry in the dynamic section, but in
+   a statically-linked program there is no dynamic section for the debugger
+   to examine and it looks for this particular symbol name.  */
+struct r_debug pal_r_debug =
+        { 1, NULL, (ElfW(Addr)) &pal_dl_debug_state, RT_CONSISTENT, 0 };
+
+extern __typeof(pal_r_debug) _r_debug
+    __attribute ((alias ("pal_r_debug")));
+
+/* This function exists solely to have a breakpoint set on it by the
+   debugger.  The debugger is supposed to find this function's address by
+   examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
+   for this particular symbol name in the PT_INTERP file.  */
+
+/* The special symbol name is set as breakpoint in gdb */
+void __attribute__((noinline)) pal_dl_debug_state (void)
+{
+    if (pal_sec_info._dl_debug_state)
+        pal_sec_info._dl_debug_state();
+}
+
+extern __typeof(pal_dl_debug_state) _dl_debug_state
+    __attribute ((alias ("pal_dl_debug_state")));
+
+void _DkDebugAddMap (struct link_map * map)
+{
+    struct r_debug * dbg = pal_sec_info._r_debug ? : &pal_r_debug;
+    int len = map->l_name ? strlen(map->l_name) + 1 : 0;
+
+    struct link_map ** prev = &dbg->r_map, * last = NULL,
+                    * tmp = *prev;
+    while (tmp) {
+        if (tmp->l_addr == map->l_addr &&
+            tmp->l_ld == map->l_ld &&
+            !memcmp(tmp->l_name, map->l_name, len))
+            return;
+
+        last = tmp;
+        tmp = *(prev = &last->l_next);
+    }
+
+    struct link_gdb_map * m = malloc(sizeof(struct link_gdb_map) + len);
+    if (!m)
+        return;
+
+    if (len) {
+        m->l_name = (char *) m + sizeof(struct link_gdb_map);
+        memcpy((void *) m->l_name, map->l_name, len);
+    } else {
+        m->l_name = NULL;
+    }
+
+    m->l_addr = map->l_addr;
+    m->l_ld   = map->l_real_ld;
+
+    dbg->r_state = RT_ADD;
+    pal_dl_debug_state();
+
+    *prev = (struct link_map *) m;
+    m->l_prev = last;
+    m->l_next = NULL;
+
+    dbg->r_state = RT_CONSISTENT;
+    pal_dl_debug_state();
+}
+
+void _DkDebugDelMap (struct link_map * map)
+{
+    struct r_debug * dbg = pal_sec_info._r_debug ? : &pal_r_debug;
+    int len = map->l_name ? strlen(map->l_name) + 1 : 0;
+
+    struct link_map ** prev = &dbg->r_map, * last = NULL,
+                    * tmp = *prev, * found = NULL;
+    while (tmp) {
+        if (tmp->l_addr == map->l_addr &&
+            tmp->l_ld == map->l_ld &&
+            !memcmp(tmp->l_name, map->l_name, len)) {
+            found = tmp;
+            break;
+        }
+
+        last = tmp;
+        tmp = *(prev = &last->l_next);
+    }
+
+    if (!found)
+        return;
+
+    dbg->r_state = RT_DELETE;
+    pal_dl_debug_state();
+
+    if (last)
+        last->l_next = tmp->l_next;
+    else
+        dbg->r_map = tmp->l_next;
+
+    if (tmp->l_next)
+        tmp->l_next->l_prev = last;
+
+    free(tmp);
+
+    dbg->r_state = RT_CONSISTENT;
+    pal_dl_debug_state();
+}
 
 extern void setup_elf_hash (struct link_map *map);
 
@@ -84,30 +188,9 @@ void setup_pal_map (const char * realname, ElfW(Dyn) ** dyn, ElfW(Addr) addr)
         l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) &pal_r_debug;
 
     l->l_prev = l->l_next = NULL;
-    rtld_map = l;
     loaded_libraries = l;
 
-    if (!pal_sec_info._r_debug) {
-        pal_r_debug.r_version = 1;
-        pal_r_debug.r_brk = (ElfW(Addr)) &pal_dl_debug_state;
-        pal_r_debug.r_ldbase = addr;
-        pal_r_debug.r_map = loaded_libraries;
-        pal_sec_info._r_debug = &pal_r_debug;
-        pal_sec_info._dl_debug_state = &pal_dl_debug_state;
-    } else {
-        pal_sec_info._r_debug->r_state = RT_ADD;
-        pal_sec_info._dl_debug_state();
-
-        if (pal_sec_info._r_debug->r_map) {
-            l->l_prev = pal_sec_info._r_debug->r_map;
-            pal_sec_info._r_debug->r_map->l_next = l;
-        } else {
-            pal_sec_info._r_debug->r_map = loaded_libraries;
-        }
-
-        pal_sec_info._r_debug->r_state = RT_CONSISTENT;
-        pal_sec_info._dl_debug_state();
-    }
+    _DkDebugAddMap(l);
 }
 
 #if USE_VDSO_GETTIME == 1

+ 0 - 0
Pal/src/pal.lds → Pal/src/host/Linux/pal.lds


+ 1 - 2
Pal/src/pal.map → Pal/src/host/Linux/pal.map

@@ -44,11 +44,10 @@ PAL {
         DkStreamAttributesSetbyHandle;
 
         # Debugging ABIs
-        pal_printf; pal_snprintf;
+        pal_printf; pal_snprintf; DkDebugAttachBinary; DkDebugDetachBinary;
 
         # Control block
         pal_control; pal_control_addr; pal_sec_info;
 
-
     local: *;
 };

+ 3 - 0
Pal/src/host/Linux/pal_linux.h

@@ -23,6 +23,9 @@
 #include "pal_defs.h"
 #include "pal_linux_defs.h"
 #include "pal.h"
+#include "pal_internal.h"
+
+#define PAL_LOADER XSTRINGIFY(PAL_LOADER_PATH)
 
 #include <sys/syscall.h>
 

+ 3 - 0
Pal/src/pal_debug.h

@@ -59,6 +59,9 @@ int pal_snprintf (char *buf, size_t n, const char *fmt, ...);
 int pal_atoi (const char *nptr);
 long int pal_atol (const char *nptr);
 
+void DkDebugAttachBinary (PAL_STR uri, PAL_PTR start_addr);
+void DkDebugDetachBinary (PAL_PTR start_addr);
+
 #endif
 
 #endif

+ 1 - 5
Pal/src/pal_internal.h

@@ -35,9 +35,6 @@
 # error "pal_internal.h can only be included in PAL"
 #endif
 
-#define LIBRARY_NAME        "libpal.so"
-#define LIBRARY_NAMELEN     9
-
 /* handle_ops is the operators provided for each handler type. They are
    mostly used by Stream-related PAL calls, but can also be used by
    some others in special ways. */
@@ -286,7 +283,6 @@ extern struct pal_config {
     PAL_HANDLE      manifest_handle;
     PAL_HANDLE      exec_handle;
     struct config_store * root_config;
-    const char *    lib_name;
     const char **   environments;
     unsigned long   pagesize;
     unsigned long   alloc_align;
@@ -430,7 +426,7 @@ int unblock_signals (int * sigs, int nsig);
 void * find_address (void * addr);
 
 /* function and definition for loading binaries */
-enum object_type { OBJECT_RTLD, OBJECT_EXEC, OBJECT_PRELOAD };
+enum object_type { OBJECT_RTLD, OBJECT_EXEC, OBJECT_PRELOAD, OBJECT_EXTERNAL };
 
 int check_elf_object (PAL_HANDLE handle);
 int load_elf_object (const char * uri, enum object_type type);

+ 15 - 0
Pal/src/pal_rtld.h

@@ -102,6 +102,16 @@ struct link_map {
     const Elf32_Word * l_gnu_chain_zero;
 };
 
+struct link_gdb_map {
+    /* These first few members are part of the protocol with the debugger.
+       This is the same format used in SVR4.  */
+
+    ElfW(Addr) l_addr;          /* Base address shared object is loaded at. */
+    const char * l_name;        /* Absolute file name object was found in.  */
+    ElfW(Dyn) * l_ld;           /* Dynamic section of the shared object.    */
+    struct link_map * l_next, * l_prev;     /* Chain of loaded objects.     */
+};
+
 extern struct link_map * loaded_libraries;
 extern struct link_map * rtld_map;
 extern struct link_map * exec_map;
@@ -207,4 +217,9 @@ do_lookup_map (ElfW(Sym) * ref, const char * undef_name,
                const uint_fast32_t hash, unsigned long int elf_hash,
                const struct link_map * map);
 
+/* for GDB debugging */
+void _DkDebugAddMap (struct link_map * map);
+void _DkDebugDelMap (struct link_map * map);
+
+
 #endif /* PAL_RTLD_H */

+ 0 - 1
Pal/src/security/Linux/Makefile

@@ -27,7 +27,6 @@ libpal_sec.so: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@echo [ security/Linux/$@ ]
 	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(LD) $(LDFLAGS) -o $@ $^ -soname=libpal_sec.so
-	@cd ../.. && ln -sf security/Linux/libpal_sec.so
 
 %.o: %.c
 	@echo [ security/Linux/$@ ]