Browse Source

release v0.3

- Bugfixes in PAL and SHIM
- Improvement of migration scheme in SHIM, which largely speed up
  forking
- Upgrade glibc to 2.19
- FreeBSD port
- Support OpenJDK, python and R
Chia-Che Tsai 8 years ago
parent
commit
b5586bbfc6
100 changed files with 4704 additions and 2458 deletions
  1. 1 0
      LibOS/.packed/glibc.sha384
  2. BIN
      LibOS/.packed/glibc.tar.gz
  3. 8 8
      LibOS/Makefile
  4. 2 2
      LibOS/buildglibc.py
  5. 1845 0
      LibOS/glibc-2.19.patch
  6. 1 0
      LibOS/glibc-2.19/elf/syscallas.S
  7. 1 0
      LibOS/glibc-2.19/elf/syscalldb.c
  8. 56 0
      LibOS/glibc-2.19/libos/Makefile
  9. 15 0
      LibOS/glibc-2.19/libos/Versions
  10. 27 0
      LibOS/glibc-2.19/libos/benchmark.c
  11. 13 0
      LibOS/glibc-2.19/libos/checkpoint.c
  12. 13 0
      LibOS/glibc-2.19/libos/msgpersist.c
  13. 27 0
      LibOS/glibc-2.19/libos/sandbox.c
  14. 11 0
      LibOS/glibc-2.19/syscallas.S
  15. 10 0
      LibOS/glibc-2.19/syscalldb.c
  16. 15 0
      LibOS/glibc-2.19/syscalldb.h
  17. 1 0
      LibOS/glibc-2.19/sysdeps/unix/sysv/linux/x86_64/syscalldb.h
  18. 266 404
      LibOS/shim/include/shim_checkpoint.h
  19. 5 1
      LibOS/shim/include/shim_defs.h
  20. 35 25
      LibOS/shim/include/shim_fs.h
  21. 25 7
      LibOS/shim/include/shim_handle.h
  22. 38 17
      LibOS/shim/include/shim_signal.h
  23. 16 16
      LibOS/shim/include/shim_table.h
  24. 26 7
      LibOS/shim/include/shim_thread.h
  25. 195 23
      LibOS/shim/include/shim_types.h
  26. 9 0
      LibOS/shim/include/shim_unistd.h
  27. 1 1
      LibOS/shim/include/shim_utils.h
  28. 15 18
      LibOS/shim/include/shim_vma.h
  29. 0 0
      LibOS/shim/src/.packed/shim.sha384
  30. BIN
      LibOS/shim/src/.packed/shim.tar.gz
  31. 9 8
      LibOS/shim/src/Makefile
  32. 85 148
      LibOS/shim/src/bookkeep/shim_handle.c
  33. 28 54
      LibOS/shim/src/bookkeep/shim_signal.c
  34. 87 199
      LibOS/shim/src/bookkeep/shim_thread.c
  35. 261 200
      LibOS/shim/src/bookkeep/shim_vma.c
  36. 1 1
      LibOS/shim/src/elf/dl-machine-x86_64.h
  37. 67 173
      LibOS/shim/src/elf/shim_rtld.c
  38. 26 13
      LibOS/shim/src/fs/chroot/fs.c
  39. 5 1
      LibOS/shim/src/fs/dev/fs.c
  40. 9 5
      LibOS/shim/src/fs/pipe/fs.c
  41. 6 2
      LibOS/shim/src/fs/proc/fs.c
  42. 5 1
      LibOS/shim/src/fs/proc/info.c
  43. 6 1
      LibOS/shim/src/fs/proc/ipc-thread.c
  44. 5 1
      LibOS/shim/src/fs/proc/thread.c
  45. 79 10
      LibOS/shim/src/fs/shim_dcache.c
  46. 58 80
      LibOS/shim/src/fs/shim_fs.c
  47. 47 22
      LibOS/shim/src/fs/shim_namei.c
  48. 5 1
      LibOS/shim/src/fs/socket/fs.c
  49. 6 2
      LibOS/shim/src/fs/str/fs.c
  50. 44 67
      LibOS/shim/src/ipc/shim_ipc.c
  51. 28 4
      LibOS/shim/src/ipc/shim_ipc_child.c
  52. 1 1
      LibOS/shim/src/ipc/shim_ipc_helper.c
  53. 38 15
      LibOS/shim/src/shim.lds
  54. 1 1
      LibOS/shim/src/shim_async.c
  55. 519 383
      LibOS/shim/src/shim_checkpoint.c
  56. 38 29
      LibOS/shim/src/shim_debug.c
  57. 56 66
      LibOS/shim/src/shim_init.c
  58. 13 15
      LibOS/shim/src/shim_parser.c
  59. 12 11
      LibOS/shim/src/shim_syscalls.c
  60. 8 1
      LibOS/shim/src/start.S
  61. 1 1
      LibOS/shim/src/sys/shim_alarm.c
  62. 14 18
      LibOS/shim/src/sys/shim_brk.c
  63. 3 3
      LibOS/shim/src/sys/shim_clone.c
  64. 0 1
      LibOS/shim/src/sys/shim_dup.c
  65. 14 3
      LibOS/shim/src/sys/shim_epoll.c
  66. 129 59
      LibOS/shim/src/sys/shim_exec.c
  67. 5 1
      LibOS/shim/src/sys/shim_exit.c
  68. 4 3
      LibOS/shim/src/sys/shim_fcntl.c
  69. 19 36
      LibOS/shim/src/sys/shim_fork.c
  70. 3 1
      LibOS/shim/src/sys/shim_fs.c
  71. 3 1
      LibOS/shim/src/sys/shim_getcwd.c
  72. 75 112
      LibOS/shim/src/sys/shim_migrate.c
  73. 7 6
      LibOS/shim/src/sys/shim_open.c
  74. 6 1
      LibOS/shim/src/sys/shim_pipe.c
  75. 49 32
      LibOS/shim/src/sys/shim_poll.c
  76. 7 7
      LibOS/shim/src/sys/shim_sigaction.c
  77. 29 36
      LibOS/shim/src/sys/shim_socket.c
  78. 7 6
      LibOS/shim/src/sys/shim_time.c
  79. 1 0
      LibOS/shim/src/sys/shim_vfork.c
  80. 4 0
      LibOS/shim/src/sys/shim_wait.c
  81. 3 3
      LibOS/shim/test/Makefile
  82. 19 8
      LibOS/shim/test/apps/Makefile
  83. 17 16
      LibOS/shim/test/apps/apache/Makefile
  84. 2 2
      LibOS/shim/test/apps/bash/Makefile
  85. 10 12
      LibOS/shim/test/apps/bash/bash_test.sh
  86. 7 6
      LibOS/shim/test/apps/bash/unixbench.sh
  87. 3 3
      LibOS/shim/test/apps/busybox/Makefile
  88. 18 22
      LibOS/shim/test/apps/gcc/Makefile
  89. BIN
      LibOS/shim/test/apps/gcc/gcc-4.8.4.tar.bz2
  90. 4 4
      LibOS/shim/test/apps/gcc/gcc-local.manifest.template
  91. BIN
      LibOS/shim/test/apps/gcc/gmp-4.3.2.tar.bz2
  92. BIN
      LibOS/shim/test/apps/gcc/gmp-5.0.2.tar.bz2
  93. BIN
      LibOS/shim/test/apps/gcc/gmp-5.1.3.tar.bz2
  94. BIN
      LibOS/shim/test/apps/gcc/mpc-0.8.1.tar.gz
  95. BIN
      LibOS/shim/test/apps/gcc/mpc-1.0.1.tar.gz
  96. BIN
      LibOS/shim/test/apps/gcc/mpfr-2.4.2.tar.bz2
  97. BIN
      LibOS/shim/test/apps/gcc/mpfr-3.1.2.tar.bz2
  98. BIN
      LibOS/shim/test/apps/gcc/ppl-0.10.2.tar.gz
  99. BIN
      LibOS/shim/test/apps/gcc/ppl-1.1.tar.gz
  100. 11 11
      LibOS/shim/test/apps/lighttpd/Makefile

+ 1 - 0
LibOS/.packed/glibc.sha384

@@ -0,0 +1 @@
+build/crt1.o build/crti.o build/crtn.o build/ld-linux-x86-64.so.2 build/libc.so.6 build/libdl.so.2 build/liblibos.so.1 build/libm.so.6 build/libpthread.so.0 build/libutil.so.1

BIN
LibOS/.packed/glibc.tar.gz


+ 8 - 8
LibOS/Makefile

@@ -1,24 +1,24 @@
 SYS ?= $(shell gcc -dumpmachine)
 export SYS
 
-GLIBC_SRC = glibc-2.17
+GLIBC_SRC = glibc-2.19
 SHIM_DIR = shim
 BUILD_DIR = build
 GLIBC_TARGET = $(addprefix $(BUILD_DIR)/,libc.so.6 ld-linux-x86-64.so.2 libpthread.so.0 libm.so.6 libdl.so.2 libutil.so.1 crt1.o crti.o crtn.o liblibos.so.1)
 
 all: $(GLIBC_TARGET)
-	make -C $(SHIM_DIR) all
+	$(MAKE) -C $(SHIM_DIR) all
 
 debug: DEBUG=debug
 debug: $(GLIBC_TARGET)
-	make -C $(SHIM_DIR) debug
+	$(MAKE) -C $(SHIM_DIR) debug
 
 # nothing to install
 install:
 
 ifeq ($(SYS),x86_64-linux-gnu)
 $(GLIBC_TARGET): $(BUILD_DIR)/Makefile
-	cd $(BUILD_DIR) && make
+	cd $(BUILD_DIR) && $(MAKE)
 
 $(BUILD_DIR)/Makefile: $(GLIBC_SRC)/configure
 	./buildglibc.py --quiet $(DEBUG)
@@ -31,15 +31,15 @@ $(GLIBC_SRC)/configure:
 
 .PHONY: pack
 pack: $(GLIBC_TARGET)
-	tar -chzf .packed/glibc.tar.gz $^
-	make -C $(SHIM_DIR) pack
+	@../Scripts/pack_binaries.sh glibc $^
+	$(MAKE) -C $(SHIM_DIR) pack
 
 clean:
-	make -C $(SHIM_DIR) clean
+	$(MAKE) -C $(SHIM_DIR) clean
 	rm -rf $(BUILD_DIR)
 else
 $(GLIBC_TARGET): .packed/glibc.tar.gz
-	tar -xmozf $<
+	tar -xmozf $< $@
 
 clean:
 	rm -rf $(BUILD_DIR)

+ 2 - 2
LibOS/buildglibc.py

@@ -26,9 +26,9 @@ def appendText(filename, text) :
 
 try:
     home = os.getcwd()
-    glibc = "glibc-2.17"
+    glibc = "glibc-2.19"
     glibcParent = "" # glibc parent directory
-    glibcDir = ""    # glibc dir (ex. glibc-2.17)
+    glibcDir = ""    # glibc dir (ex. glibc-2.19)
     buildDir = "build"
     installDir = "/usr/local/graphene"
     commandStr = ""

+ 1845 - 0
LibOS/glibc-2.19.patch

@@ -0,0 +1,1845 @@
+diff --git a/Makeconfig b/Makeconfig
+index 1908f27..cf34ba1 100644
+--- a/Makeconfig
++++ b/Makeconfig
+@@ -775,7 +775,8 @@ endif	# $(+cflags) == ""
+ # current directory.
+ +includes = -I$(..)include $(if $(subdir),$(objpfx:%/=-I%)) \
+ 	    $(+sysdep-includes) $(includes) \
+-	    $(patsubst %/,-I%,$(..)) $(libio-include) -I. $(sysincludes)
++	    $(patsubst %/,-I%,$(..)) $(libio-include) -I. $(sysincludes) \
++	    -I$(common-objpfx)../shim/include
+ 
+ # Since libio has several internal header files, we use a -I instead
+ # of many little headers in the include directory.
+@@ -1033,7 +1034,7 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal	    \
+ 	      grp pwd posix io termios resource misc socket sysvipc gmon    \
+ 	      gnulib iconv iconvdata wctype manual shadow gshadow po argp   \
+ 	      crypt localedata timezone rt conform debug		    \
+-	      $(add-on-subdirs) dlfcn elf
++	      $(add-on-subdirs) dlfcn elf libos
+ 
+ ifndef avoid-generated
+ # sysd-sorted itself will contain rules making the sysd-sorted target
+diff --git a/Makefile b/Makefile
+index 51d4690..d72c4b0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -177,6 +177,8 @@ $(inst_includedir)/gnu/stubs.h: $(+force)
+ install-others-nosubdir: $(installed-stubs)
+ endif
+ 
++# For Graphene
++CFLAGS-syscalldb.c = -fPIC
+ 
+ # Since stubs.h is never needed when building the library, we simplify the
+ # hairy installation process by producing it in place only as the last part
+diff --git a/Versions.def b/Versions.def
+index 759c754..e1a270e 100644
+--- a/Versions.def
++++ b/Versions.def
+@@ -41,6 +41,7 @@ libc {
+   GCC_3.0
+ %endif
+   GLIBC_PRIVATE
++  SHIM
+ }
+ libcrypt {
+   GLIBC_2.0
+@@ -50,6 +51,7 @@ libdl {
+   GLIBC_2.1
+   GLIBC_2.3.3
+   GLIBC_2.3.4
++  SHIM
+ }
+ libm {
+   GLIBC_2.0
+@@ -108,6 +110,7 @@ libpthread {
+   GLIBC_2.18
+   GLIBC_2.19
+   GLIBC_PRIVATE
++  SHIM
+ }
+ libresolv {
+   GLIBC_2.0
+@@ -135,6 +138,7 @@ ld {
+   GLIBC_2.3
+   GLIBC_2.4
+   GLIBC_PRIVATE
++  SHIM
+ }
+ libthread_db {
+   GLIBC_2.1.3
+@@ -148,3 +152,6 @@ libanl {
+ libcidn {
+   GLIBC_PRIVATE
+ }
++liblibos {
++  GLIBC_2.12
++}
+diff --git a/configure b/configure
+index fc023d0..b71c1f9 100755
+--- a/configure
++++ b/configure
+@@ -630,7 +630,8 @@ SED
+ MAKEINFO
+ MSGFMT
+ MAKE
+-LD
++LD_GOLD
++LD_BFD
+ AS
+ OBJCOPY
+ OBJDUMP
+@@ -4593,17 +4594,22 @@ if test $ac_verc_fail = yes; then
+   AS=: critic_missing="$critic_missing as"
+ fi
+ 
+-for ac_prog in $LD
++LD_BFD=
++LD_GOLD=
++ld_is_gold="`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"
++if test -z "$ld_is_gold"; then
++  LD_BFD=$LD
++  for ac_prog in $LD_BFD
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+ $as_echo_n "checking for $ac_word... " >&6; }
+-if ${ac_cv_prog_LD+:} false; then :
++if ${ac_cv_prog_LD_BFD+:} false; then :
+   $as_echo_n "(cached) " >&6
+ else
+-  if test -n "$LD"; then
+-  ac_cv_prog_LD="$LD" # Let the user override the test.
++  if test -n "$LD_BFD"; then
++  ac_cv_prog_LD_BFD="$LD_BFD" # Let the user override the test.
+ else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+@@ -4612,7 +4618,7 @@ do
+   test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+   if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+-    ac_cv_prog_LD="$ac_prog"
++    ac_cv_prog_LD_BFD="$ac_prog"
+     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+@@ -4622,26 +4628,26 @@ IFS=$as_save_IFS
+ 
+ fi
+ fi
+-LD=$ac_cv_prog_LD
+-if test -n "$LD"; then
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+-$as_echo "$LD" >&6; }
++LD_BFD=$ac_cv_prog_LD_BFD
++if test -n "$LD_BFD"; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD_BFD" >&5
++$as_echo "$LD_BFD" >&6; }
+ else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ $as_echo "no" >&6; }
+ fi
+ 
+ 
+-  test -n "$LD" && break
++  test -n "$LD_BFD" && break
+ done
+ 
+-if test -z "$LD"; then
++if test -z "$LD_BFD"; then
+   ac_verc_fail=yes
+ else
+   # Found it, now check the version.
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5
+-$as_echo_n "checking version of $LD... " >&6; }
+-  ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU ld.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD_BFD" >&5
++$as_echo_n "checking version of $LD_BFD... " >&6; }
++  ac_prog_version=`$LD_BFD --version 2>&1 | sed -n 's/^.*GNU ld.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
+   case $ac_prog_version in
+     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+     2.1[0-9][0-9]*|2.[2-9][0-9]*|[3-9].*|[1-9][0-9]*)
+@@ -4653,9 +4659,80 @@ $as_echo_n "checking version of $LD... " >&6; }
+ $as_echo "$ac_prog_version" >&6; }
+ fi
+ if test $ac_verc_fail = yes; then
+-  LD=: critic_missing="$critic_missing ld"
++  LD_BFD=:
+ fi
+ 
++else
++# Accept gold 1.11 or higher.
++  LD_GOLD=$LD
++  for ac_prog in $LD_GOLD
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_LD_GOLD+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  if test -n "$LD_GOLD"; then
++  ac_cv_prog_LD_GOLD="$LD_GOLD" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
++    ac_cv_prog_LD_GOLD="$ac_prog"
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++LD_GOLD=$ac_cv_prog_LD_GOLD
++if test -n "$LD_GOLD"; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD_GOLD" >&5
++$as_echo "$LD_GOLD" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++
++  test -n "$LD_GOLD" && break
++done
++
++if test -z "$LD_GOLD"; then
++  ac_verc_fail=yes
++else
++  # Found it, now check the version.
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD_GOLD" >&5
++$as_echo_n "checking version of $LD_GOLD... " >&6; }
++  ac_prog_version=`$LD_GOLD --version 2>&1 | sed -n 's/^.*GNU gold.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
++  case $ac_prog_version in
++    '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
++    1.1[1-9]*|1.[2-9][0-9]*|1.1[0-9][0-9]*|[2-9].*|[1-9][0-9]*)
++       ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
++    *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
++
++  esac
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
++$as_echo "$ac_prog_version" >&6; }
++fi
++if test $ac_verc_fail = yes; then
++  LD_GOLD=:
++fi
++
++fi
++# Neither ld nor gold are new enough.
++if test -z "$LD_BFD" && test -z "$LD_GOLD"; then
++  critic_missing="$critic_missing ld"
++fi
+ 
+ # These programs are version sensitive.
+ 
+@@ -6391,6 +6468,16 @@ $as_echo "$libc_cv_use_default_link" >&6; }
+   use_default_link=$libc_cv_use_default_link
+ fi
+ 
++# The gold linker has no builtin default linker script,
++# and the fallback of editing the builtin linker
++# script is not available. Therefore if use_default_link
++# is `no' then we can't use gold. This check is independent
++# of gold's version and is used to sanity check that the
++# linker continues to produce a useful shared link.
++if test "$ld_is_gold" && test "$use_default_link" = "no"; then
++  as_fn_error $? "$LD did not generate a useful shared link. Try using GNU ld.bfd?" "$LINENO" 5
++fi
++
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker output format" >&5
+ $as_echo_n "checking linker output format... " >&6; }
+ if ${libc_cv_output_format+:} false; then :
+@@ -6409,6 +6496,17 @@ fi
+ $as_echo "$libc_cv_output_format" >&6; }
+ 
+ 
++# The gold linker has no builtin default linker script,
++# and the fallback of parsing the builtin linker
++# script to determine the target is not available.
++# Therefore if libc_cv_output_format is `unknown' then
++# we can't use gold. This check is independent of gold's
++# version and is used to sanity check that the linker
++# continues to support --print-output-format.
++if test "$ld_is_gold" && test "$libc_cv_output_format" = "unknown"; then
++  as_fn_error $? "$LD did not support --print-output-format. Try using GNU ld.bfd?" "$LINENO" 5
++fi
++
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fno-toplevel-reorder -fno-section-anchors" >&5
+ $as_echo_n "checking for -fno-toplevel-reorder -fno-section-anchors... " >&6; }
+ if ${libc_cv_fno_toplevel_reorder+:} false; then :
+diff --git a/dlfcn/Versions b/dlfcn/Versions
+index 97902f0..c1874c1 100644
+--- a/dlfcn/Versions
++++ b/dlfcn/Versions
+@@ -14,4 +14,7 @@ libdl {
+   GLIBC_PRIVATE {
+     _dlfcn_hook;
+   }
++  SHIM {
++    syscalldb;
++  }
+ }
+diff --git a/elf/Makefile b/elf/Makefile
+index 4c58fc9..0ae2fa8 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -21,7 +21,7 @@ subdir		:= elf
+ 
+ include ../Makeconfig
+ 
+-headers		= elf.h bits/elfclass.h link.h bits/link.h
++headers		= elf.h bits/elfclass.h link.h bits/link.h syscalldb.h
+ routines	= $(dl-routines) dl-support dl-iteratephdr \
+ 		  dl-addr enbl-secure dl-profstub \
+ 		  dl-origin dl-libc dl-sym dl-tsd dl-sysdep
+@@ -31,7 +31,8 @@ routines	= $(dl-routines) dl-support dl-iteratephdr \
+ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
+ 				  runtime error init fini debug misc \
+ 				  version profile conflict tls origin scope \
+-				  execstack caller open close trampoline)
++				  execstack caller open close trampoline) \
++		  syscalldb syscallas
+ ifeq (yes,$(use-ldconfig))
+ dl-routines += dl-cache
+ endif
+diff --git a/elf/Versions b/elf/Versions
+index 2383992..03fbd38 100644
+--- a/elf/Versions
++++ b/elf/Versions
+@@ -24,14 +24,15 @@ libc {
+     _dl_sym; _dl_vsym;
+     __libc_dlclose; __libc_dlopen_mode; __libc_dlsym;
+   }
++  SHIM {
++    syscalldb;
++  }
+ }
+ 
+ ld {
+   GLIBC_2.0 {
+     # Function from libc.so which must be shared with libc.
+     __libc_memalign; calloc; free; malloc; realloc;
+-
+-    _r_debug;
+   }
+   GLIBC_2.1 {
+     # functions used in other libraries
+@@ -57,9 +58,12 @@ ld {
+     _rtld_global; _rtld_global_ro;
+ 
+     # Only here for gdb while a better method is developed.
+-    _dl_debug_state;
++    __libc_r_debug; __libc_dl_debug_state;
+ 
+     # Pointer protection.
+     __pointer_chk_guard;
+   }
++  SHIM {
++    syscalldb; glibc_vers_2_17; register_library;
++  }
+ }
+diff --git a/elf/circleload1.c b/elf/circleload1.c
+index 990ff84..ccf92d3 100644
+--- a/elf/circleload1.c
++++ b/elf/circleload1.c
+@@ -5,7 +5,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ static int
+ check_loaded_objects (const char **loaded)
+diff --git a/elf/dl-close.c b/elf/dl-close.c
+index 5bf1de7..a887133 100644
+--- a/elf/dl-close.c
++++ b/elf/dl-close.c
+@@ -473,7 +473,7 @@ _dl_close_worker (struct link_map *map)
+   /* Notify the debugger we are about to remove some loaded objects.  */
+   struct r_debug *r = _dl_debug_initialize (0, nsid);
+   r->r_state = RT_DELETE;
+-  _dl_debug_state ();
++  __libc_dl_debug_state ();
+   LIBC_PROBE (unmap_start, 2, nsid, r);
+ 
+   if (unload_global)
+@@ -739,7 +739,7 @@ _dl_close_worker (struct link_map *map)
+ 
+   /* Notify the debugger those objects are finalized and gone.  */
+   r->r_state = RT_CONSISTENT;
+-  _dl_debug_state ();
++  __libc_dl_debug_state ();
+   LIBC_PROBE (unmap_complete, 2, nsid, r);
+ 
+   /* Recheck if we need to retry, release the lock.  */
+diff --git a/elf/dl-debug.c b/elf/dl-debug.c
+index 4e7c593..3e0bff4 100644
+--- a/elf/dl-debug.c
++++ b/elf/dl-debug.c
+@@ -34,7 +34,7 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
+    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 _r_debug;
++struct r_debug __libc_r_debug __attribute__((weak));
+ 
+ 
+ /* Initialize _r_debug if it has not already been done.  The argument is
+@@ -48,7 +48,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
+   struct r_debug *r;
+ 
+   if (ns == LM_ID_BASE)
+-    r = &_r_debug;
++    r = &__libc_r_debug;
+   else
+     r = &GL(dl_ns)[ns]._ns_debug;
+ 
+@@ -56,9 +56,9 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
+     {
+       /* Tell the debugger where to find the map of loaded objects.  */
+       r->r_version = 1	/* R_DEBUG_VERSION XXX */;
+-      r->r_ldbase = ldbase ?: _r_debug.r_ldbase;
++      r->r_ldbase = ldbase ?: __libc_r_debug.r_ldbase;
+       r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded;
+-      r->r_brk = (ElfW(Addr)) &_dl_debug_state;
++      r->r_brk = (ElfW(Addr)) &__libc_dl_debug_state;
+     }
+ 
+   return r;
+@@ -70,7 +70,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
+    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.  */
+ void
+-_dl_debug_state (void)
++__libc_dl_debug_state (void)
+ {
+ }
+-rtld_hidden_def (_dl_debug_state)
++__attribute__((weak));
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index 1be7a3c..c560ec1 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -39,6 +39,8 @@
+ 
+ #include <dl-dst.h>
+ 
++#include <glibc-version.h>
++
+ /* On some systems, no flag bits are given to specify file mapping.  */
+ #ifndef MAP_FILE
+ # define MAP_FILE	0
+@@ -902,7 +904,7 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
+   if (r != NULL)
+     {
+       r->r_state = RT_CONSISTENT;
+-      _dl_debug_state ();
++      __libc_dl_debug_state ();
+       LIBC_PROBE (map_failed, 2, nsid, r);
+     }
+ 
+@@ -1048,7 +1050,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
+ 	 call _dl_debug_initialize in a static program in case dynamic
+ 	 linking has not been used before.  */
+       r->r_state = RT_ADD;
+-      _dl_debug_state ();
++      __libc_dl_debug_state ();
+       LIBC_PROBE (map_start, 2, nsid, r);
+       make_consistent = true;
+     }
+@@ -1595,6 +1597,9 @@ cannot enable executable stack as shared object requires");
+   DL_AFTER_LOAD (l);
+ #endif
+ 
++  /* register the library to SHIM */
++  register_library(l->l_name, l->l_addr);
++
+   /* Now that the object is fully initialized add it to the object list.  */
+   _dl_add_to_namespace_list (l, nsid);
+ 
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index a9ca6b3..829d212 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -290,7 +290,7 @@ dl_open_worker (void *a)
+   /* Notify the debugger all new objects are now ready to go.  */
+   struct r_debug *r = _dl_debug_initialize (0, args->nsid);
+   r->r_state = RT_CONSISTENT;
+-  _dl_debug_state ();
++  __libc_dl_debug_state ();
+   LIBC_PROBE (map_complete, 3, args->nsid, r, new);
+ 
+   /* Print scope information.  */
+diff --git a/elf/link.h b/elf/link.h
+index d5905d1..f4e108a 100644
+--- a/elf/link.h
++++ b/elf/link.h
+@@ -64,7 +64,7 @@ struct r_debug
+   };
+ 
+ /* This is the instance of that structure used by the dynamic linker.  */
+-extern struct r_debug _r_debug;
++extern struct r_debug __libc_r_debug;
+ 
+ /* This symbol refers to the "dynamic structure" in the `.dynamic' section
+    of whatever module refers to `_DYNAMIC'.  So, to find its own
+diff --git a/elf/loadtest.c b/elf/loadtest.c
+index 727469b..568ddef 100644
+--- a/elf/loadtest.c
++++ b/elf/loadtest.c
+@@ -70,7 +70,7 @@ static const struct
+ 
+ #include <include/link.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ #define OUT \
+   for (map = MAPS; map != NULL; map = map->l_next)		      \
+diff --git a/elf/neededtest.c b/elf/neededtest.c
+index 3cea499..e098d48 100644
+--- a/elf/neededtest.c
++++ b/elf/neededtest.c
+@@ -5,7 +5,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ static int
+ check_loaded_objects (const char **loaded)
+diff --git a/elf/neededtest2.c b/elf/neededtest2.c
+index 17c75f2..5a73a95 100644
+--- a/elf/neededtest2.c
++++ b/elf/neededtest2.c
+@@ -5,7 +5,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ static int
+ check_loaded_objects (const char **loaded)
+diff --git a/elf/neededtest3.c b/elf/neededtest3.c
+index 41970cf..5126615 100644
+--- a/elf/neededtest3.c
++++ b/elf/neededtest3.c
+@@ -5,7 +5,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ static int
+ check_loaded_objects (const char **loaded)
+diff --git a/elf/neededtest4.c b/elf/neededtest4.c
+index 0ae0b7f..f883910 100644
+--- a/elf/neededtest4.c
++++ b/elf/neededtest4.c
+@@ -5,7 +5,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ static int
+ check_loaded_objects (const char **loaded)
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 6dcbabc..431120a 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -356,6 +356,23 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
+   return start_addr;
+ }
+ 
++/* For graphene, check if glibc version match to the compatible SHIM
++   library. If not, tell the user to update glibc. */
++#include "glibc-version.h"
++
++volatile const int glibc_vers_2_17 __attribute__((weak)) = GLIBC_VERSION_2_17;
++
++static void __attribute__((noinline,optimize("-O0")))
++check_glibc_version (void)
++{
++  if (glibc_vers_2_17 != GLIBC_VERSION_2_17)
++    {
++      _dl_fatal_printf ("Warning from Graphene: "
++			"Glibc version is incorrect. Please rebuild Glibc.\n");
++      _exit (1);
++    }
++}
++
+ static ElfW(Addr) __attribute_used__ internal_function
+ _dl_start (void *arg)
+ {
+@@ -546,6 +563,9 @@ _dl_start (void *arg)
+      therefore need not test whether we have to allocate the array
+      for the relocation results (as done in dl-reloc.c).  */
+ 
++  /* For Graphene, check if the glibc version is correct. */
++  check_glibc_version();
++
+   /* Now life is sane; we can call functions and access global data.
+      Set up to use the operating system facilities, and find out from
+      the operating system's program loader where to find the program
+@@ -1233,9 +1253,20 @@ of this helper program; chances are you did not intend to run this program.\n\
+ 	    main_map->l_map_end = allocend;
+ 	  if ((ph->p_flags & PF_X) && allocend > main_map->l_text_end)
+ 	    main_map->l_text_end = allocend;
++
++#if 0
++	  ElfW(Addr) mapend = (allocend + GLRO(dl_pagesize) - 1)
++		               & ~(GLRO(dl_pagesize) - 1);
++	  int prot = ((ph->p_flags & PF_R) ? PROT_READ  : 0)|
++	             ((ph->p_flags & PF_W) ? PROT_WRITE : 0)|
++	             ((ph->p_flags & PF_X) ? PROT_EXEC  : 0);
++	  __mmap ((void *) mapstart, mapend - mapstart,
++		  prot,
++		  MAP_ANON|MAP_PRIVATE|MAP_FIXED|0x20000000,
++		  -1, 0);
++#endif
+ 	}
+ 	break;
+-
+       case PT_TLS:
+ 	if (ph->p_memsz > 0)
+ 	  {
+@@ -1381,13 +1412,31 @@ of this helper program; chances are you did not intend to run this program.\n\
+   /* PT_GNU_RELRO is usually the last phdr.  */
+   size_t cnt = rtld_ehdr->e_phnum;
+   while (cnt-- > 0)
++  {
+     if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
+       {
+ 	GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
+ 	GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
+-	break;
+       }
+ 
++#if 0
++    if (rtld_phdr[cnt].p_type == PT_LOAD)
++      {
++	ElfW(Addr) mapstart = rtld_phdr[cnt].p_vaddr & ~(GLRO(dl_pagesize) - 1);
++	ElfW(Addr) mapend = (rtld_phdr[cnt].p_vaddr + rtld_phdr[cnt].p_memsz
++		             + GLRO(dl_pagesize) - 1)
++		             & ~(GLRO(dl_pagesize) - 1);
++	int prot = ((rtld_phdr[cnt].p_flags & PF_R) ? PROT_READ  : 0)|
++	           ((rtld_phdr[cnt].p_flags & PF_W) ? PROT_WRITE : 0)|
++	           ((rtld_phdr[cnt].p_flags & PF_X) ? PROT_EXEC  : 0);
++	__mmap ((void *) mapstart, mapend - mapstart,
++		prot,
++		MAP_ANON|MAP_PRIVATE|MAP_FIXED|0x20000000,
++		-1, 0);
++      }
++#endif
++  }
++
+   /* Add the dynamic linker to the TLS list if it also uses TLS.  */
+   if (GL(dl_rtld_map).l_tls_blocksize != 0)
+     /* Assign a module ID.  Do this before loading any audit modules.  */
+@@ -1588,7 +1637,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ 
+   /* We start adding objects.  */
+   r->r_state = RT_ADD;
+-  _dl_debug_state ();
++  __libc_dl_debug_state ();
+   LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
+ 
+   /* Auditing checkpoint: we are ready to signal that the initial map
+@@ -2301,7 +2350,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+      the address since by now the variable might be in another object.  */
+   r = _dl_debug_initialize (0, LM_ID_BASE);
+   r->r_state = RT_CONSISTENT;
+-  _dl_debug_state ();
++  __libc_dl_debug_state ();
+   LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
+ 
+ #if defined USE_LDCONFIG && !defined MAP_COPY
+diff --git a/elf/unload.c b/elf/unload.c
+index 4566f22..73046de 100644
+--- a/elf/unload.c
++++ b/elf/unload.c
+@@ -9,7 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ #define OUT \
+   for (map = MAPS; map != NULL; map = map->l_next)			      \
+diff --git a/elf/unload2.c b/elf/unload2.c
+index eef2bfd..a21d2ac 100644
+--- a/elf/unload2.c
++++ b/elf/unload2.c
+@@ -6,7 +6,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+-#define MAPS ((struct link_map *) _r_debug.r_map)
++#define MAPS ((struct link_map *) __libc_r_debug.r_map)
+ 
+ #define OUT \
+   for (map = MAPS; map != NULL; map = map->l_next)			      \
+diff --git a/nptl/Makefile b/nptl/Makefile
+index 57cc8c6..81f1bf4 100644
+--- a/nptl/Makefile
++++ b/nptl/Makefile
+@@ -20,7 +20,7 @@
+ #
+ subdir	:= nptl
+ 
+-headers := pthread.h semaphore.h bits/semaphore.h
++headers := pthread.h semaphore.h bits/semaphore.h syscalldb.h
+ 
+ extra-libs := libpthread
+ extra-libs-others := $(extra-libs)
+diff --git a/nptl/Versions b/nptl/Versions
+index bb11277..4480543 100644
+--- a/nptl/Versions
++++ b/nptl/Versions
+@@ -31,6 +31,9 @@ libc {
+     # Internal libc interface to libpthread
+     __libc_dl_error_tsd;
+   }
++  SHIM {
++    syscalldb;
++  }
+ }
+ 
+ libpthread {
+@@ -262,4 +265,8 @@ libpthread {
+     __pthread_clock_gettime; __pthread_clock_settime;
+     __pthread_unwind; __pthread_get_minstack;
+   }
++
++  SHIM {
++    syscalldb;
++  }
+ }
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index 9d7f52f..72d50ae 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -405,8 +405,11 @@ start_thread (void *arg)
+ # error "to do"
+ #endif
+   assert (freesize < pd->stackblock_size);
++  /* XXX: may not be necessary */
++#if 0
+   if (freesize > PTHREAD_STACK_MIN)
+     __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
++#endif
+ 
+   /* If the thread is detached free the TCB.  */
+   if (IS_DETACHED (pd))
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S
+index 89fda5e..594dd72 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S
+@@ -111,7 +111,8 @@ ENTRY(__pthread_disable_asynccancel)
+ 	xorq	%r10, %r10
+ 	addq	$CANCELHANDLING, %rdi
+ 	LOAD_PRIVATE_FUTEX_WAIT (%esi)
+-	syscall
++	SYSCALL
++
+ 	movl	%fs:CANCELHANDLING, %eax
+ 	jmp	3b
+ END(__pthread_disable_asynccancel)
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c b/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c
+index a036b92..40a1eaf 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c
+@@ -21,10 +21,20 @@
+ #include <sysdep.h>
+ #include <tls.h>
+ 
+-
+-#define ARCH_FORK() \
++/* In Graphene, we prefer to call fork system call directly than clone */
++#if USE_clone_FOR_fork
++# define ARCH_FORK() \
+   INLINE_SYSCALL (clone, 4,						      \
+ 		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
+ 		  NULL, &THREAD_SELF->tid)
++#else
++# define ARCH_FORK() \
++ ({ unsigned long ret = INLINE_SYSCALL (fork, 0);	\
++    if (!ret) {						\
++	pid_t pid = INLINE_SYSCALL (getpid, 0);		\
++	THREAD_SETMEM (THREAD_SELF, pid, pid);		\
++	THREAD_SETMEM (THREAD_SELF, tid, pid);		\
++    } ret; })
++#endif
+ 
+ #include "../fork.c"
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+index f2dca07..e5b3f2f 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+@@ -90,7 +90,7 @@ __lll_lock_wait_private:
+ 
+ 1:	LIBC_PROBE (lll_lock_wait_private, 1, %rdi)
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 2:	movl	%edx, %eax
+ 	xchgl	%eax, (%rdi)	/* NB:	 lock is implied */
+@@ -130,7 +130,7 @@ __lll_lock_wait:
+ 
+ 1:	LIBC_PROBE (lll_lock_wait, 2, %rdi, %rsi)
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 2:	movl	%edx, %eax
+ 	xchgl	%eax, (%rdi)	/* NB:	 lock is implied */
+@@ -185,7 +185,7 @@ __lll_timedlock_wait:
+ 
+ 1:	movl	$SYS_futex, %eax
+ 	movl	$2, %edx
+-	syscall
++	SYSCALL
+ 
+ 2:	xchgl	%edx, (%rdi)	/* NB:   lock is implied */
+ 
+@@ -279,7 +279,7 @@ __lll_timedlock_wait:
+ 	LOAD_FUTEX_WAIT (%esi)
+ 	movq	%r12, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* NB: %edx == 2 */
+ 	xchgl	%edx, (%r12)
+@@ -336,7 +336,7 @@ __lll_unlock_wake_private:
+ 	LOAD_PRIVATE_FUTEX_WAKE (%esi)
+ 	movl	$1, %edx	/* Wake one thread.  */
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	popq	%rdx
+ 	cfi_adjust_cfa_offset(-8)
+@@ -366,7 +366,7 @@ __lll_unlock_wake:
+ 	LOAD_FUTEX_WAKE (%esi)
+ 	movl	$1, %edx	/* Wake one thread.  */
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	popq	%rdx
+ 	cfi_adjust_cfa_offset(-8)
+@@ -435,7 +435,7 @@ __lll_timedwait_tid:
+ #endif
+ 	movq	%r12, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	cmpl	$0, (%rdi)
+ 	jne	1f
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+index 0a26739..8aae14a 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+@@ -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);			      \
+-    __asm __volatile ("syscall"						      \
++    __asm __volatile (SYSCALLDB						      \
+ 		      : "=a" (__status)					      \
+ 		      : "0" (SYS_futex), "D" (futex),			      \
+ 			"S" (__lll_private_flag (FUTEX_WAIT, private)),	      \
+@@ -229,7 +229,7 @@ LLL_STUB_UNWIND_INFO_END
+     int __status;							      \
+     register __typeof (nr) _nr __asm ("edx") = (nr);			      \
+     LIBC_PROBE (lll_futex_wake, 3, futex, nr, private);                       \
+-    __asm __volatile ("syscall"						      \
++    __asm __volatile (SYSCALLDB						      \
+ 		      : "=a" (__status)					      \
+ 		      : "0" (SYS_futex), "D" (futex),			      \
+ 			"S" (__lll_private_flag (FUTEX_WAKE, private)),	      \
+@@ -540,7 +540,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
+     {									      \
+       int ignore;							      \
+       __asm __volatile (LOCK_INSTR "orl %3, (%2)\n\t"			      \
+-			"syscall"					      \
++			SYSCALLDB					      \
+ 			: "=m" (futex), "=a" (ignore)			      \
+ 			: "D" (&(futex)), "i" (FUTEX_OWNER_DIED),	      \
+ 			  "S" (__lll_private_flag (FUTEX_WAKE, private)),     \
+@@ -555,7 +555,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
+      register int __nr_move __asm ("r10") = nr_move;			      \
+      register void *__mutex __asm ("r8") = mutex;			      \
+      register int __val __asm ("r9") = val;				      \
+-     __asm __volatile ("syscall"					      \
++     __asm __volatile (SYSCALLDB					      \
+ 		       : "=a" (__res)					      \
+ 		       : "0" (__NR_futex), "D" ((void *) ftx),		      \
+ 			 "S" (__lll_private_flag (FUTEX_CMP_REQUEUE,	      \
+@@ -581,7 +581,7 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
+     if (_tid != 0)							      \
+       __asm __volatile ("xorq %%r10, %%r10\n\t"				      \
+ 			"1:\tmovq %2, %%rax\n\t"			      \
+-			"syscall\n\t"					      \
++			SYSCALLDB					      \
+ 			"cmpl $0, (%%rdi)\n\t"				      \
+ 			"jne 1b"					      \
+ 			: "=&a" (__ignore)				      \
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
+index 990b6f9..89dbe32 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
+@@ -80,7 +80,7 @@ __lll_robust_lock_wait:
+ 	jnz	2f
+ 
+ 1:	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	movl	(%rdi), %eax
+ 
+@@ -145,7 +145,7 @@ __lll_robust_timedlock_wait:
+ 	jnz	6f
+ 
+ 5:	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	movl	%eax, %ecx
+ 
+ 	movl	(%rdi), %eax
+@@ -257,7 +257,7 @@ __lll_robust_timedlock_wait:
+ 	LOAD_FUTEX_WAIT (%esi)
+ 	movq	%r12, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	movq	%rax, %rcx
+ 
+ 	movl	(%r12), %eax
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
+index eec17f2..4472960 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
+@@ -62,7 +62,7 @@ pthread_barrier_wait:
+ #endif
+ 	xorq	%r10, %r10
+ 8:	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* Don't return on spurious wakeups.  The syscall does not change
+ 	   any register except %eax so there is no need to reload any of
+@@ -109,7 +109,7 @@ pthread_barrier_wait:
+ 	movl	$FUTEX_WAKE, %esi
+ 	orl	PRIVATE(%rdi), %esi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* Increment LEFT.  If this brings the count back to the
+ 	   initial count unlock the object.  */
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
+index 985e0f1..f180ab1 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
+@@ -90,7 +90,7 @@ __pthread_cond_broadcast:
+ 	movl	$SYS_futex, %eax
+ 	movl	$1, %edx
+ 	movl	$0x7fffffff, %r10d
+-	syscall
++	SYSCALL
+ 
+ 	/* For any kind of error, which mainly is EAGAIN, we try again
+ 	   with WAKE.  The general test also covers running on old
+@@ -106,7 +106,7 @@ __pthread_cond_broadcast:
+ 	movl	$SYS_futex, %eax
+ 	movl	$1, %edx
+ 	movl	$0x7fffffff, %r10d
+-	syscall
++	SYSCALL
+ 
+ 	/* For any kind of error, which mainly is EAGAIN, we try again
+ 	   with WAKE.  The general test also covers running on old
+@@ -172,7 +172,7 @@ __pthread_cond_broadcast:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	jmp	10b
+ 	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast
+ versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
+index 53d65b6..8724325 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
+@@ -82,7 +82,7 @@ __pthread_cond_signal:
+ 	addq	$cond_lock, %r8
+ #endif
+ 	movl	$FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
+-	syscall
++	SYSCALL
+ #if cond_lock != 0
+ 	subq	$cond_lock, %r8
+ #endif
+@@ -99,7 +99,7 @@ __pthread_cond_signal:
+ 	movq	%rcx, %r8
+ 	xorq	%r10, %r10
+ 	movl	(%rdi), %r9d	// XXX Can this be right?
+-	syscall
++	SYSCALL
+ 
+ 	leaq	-cond_futex(%rdi), %r8
+ 
+@@ -118,7 +118,7 @@ __pthread_cond_signal:
+ 	movl	$SYS_futex, %eax
+ 	/* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
+ 	movl	$1, %edx  */
+-	syscall
++	SYSCALL
+ 
+ 	/* Unlock.  */
+ 4:	LOCK
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+index 0dc2340..cac13bf 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+@@ -188,7 +188,7 @@ __pthread_cond_timedwait:
+ 	movq	%r12, %rdx
+ 	addq	$cond_futex, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	cmpl	$0, %eax
+ 	sete	%r15b
+@@ -234,7 +234,7 @@ __pthread_cond_timedwait:
+ 	movq	%r12, %rdx
+ 	addq	$cond_futex, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 62:	movq	%rax, %r14
+ 
+ 	movl	(%rsp), %edi
+@@ -321,7 +321,7 @@ __pthread_cond_timedwait:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	subq	$cond_nwaiters, %rdi
+ 
+ 55:	LOCK
+@@ -485,15 +485,8 @@ __pthread_cond_timedwait:
+ 	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the
+ 	   kernel.  */
+ 	leaq	32(%rsp), %rsi
+-#  ifdef SHARED
+-	mov	__vdso_clock_gettime@GOTPCREL(%rip), %RAX_LP
+-	mov	(%rax), %RAX_LP
+-	PTR_DEMANGLE (%RAX_LP)
+-	call	*%rax
+-#  else
+ 	movl	$__NR_clock_gettime, %eax
+-	syscall
+-#  endif
++	SYSCALL
+ 
+ 	/* Compute relative timeout.  */
+ 	movq	(%r13), %rcx
+@@ -560,7 +553,7 @@ __pthread_cond_timedwait:
+ # endif
+ 	addq	$cond_futex, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	movq	%rax, %r14
+ 
+ 	movl	(%rsp), %edi
+@@ -732,7 +725,7 @@ __condvar_cleanup2:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	subq	$cond_nwaiters, %rdi
+ 	movl	$1, %r12d
+ 
+@@ -769,7 +762,7 @@ __condvar_cleanup2:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* Lock the mutex only if we don't own it already.  This only happens
+ 	   in case of PI mutexes, if we got cancelled after a successful
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+index 0e61d0a..60e104b 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+@@ -138,7 +138,7 @@ __pthread_cond_wait:
+ 
+ 	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	cmpl	$0, %eax
+ 	sete	%r8b
+@@ -180,7 +180,7 @@ __pthread_cond_wait:
+ #endif
+ 60:	xorb	%r8b, %r8b
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 62:	movl	(%rsp), %edi
+ 	callq	__pthread_disable_asynccancel
+@@ -239,7 +239,7 @@ __pthread_cond_wait:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	subq	$cond_nwaiters, %rdi
+ 
+ 17:	LOCK
+@@ -455,7 +455,7 @@ __condvar_cleanup1:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	subq	$cond_nwaiters, %rdi
+ 	movl	$1, %ecx
+ 
+@@ -493,7 +493,7 @@ __condvar_cleanup1:
+ 	orl	$FUTEX_WAKE, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* Lock the mutex only if we don't own it already.  This only happens
+ 	   in case of PI mutexes, if we got cancelled after a successful
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
+index 2cbe2fa..d4e229a 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S
+@@ -90,7 +90,7 @@ __pthread_once:
+ # endif
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	jmp	6b
+ 
+ 	/* Preserve the pointer to the control variable.  */
+@@ -123,7 +123,7 @@ __pthread_once:
+ 	orl	%fs:PRIVATE_FUTEX, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 4:	addq	$8, %rsp
+ 	cfi_adjust_cfa_offset(-8)
+@@ -152,7 +152,7 @@ clear_once_control:
+ 	orl	%fs:PRIVATE_FUTEX, %esi
+ #endif
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	movq	%r8, %rdi
+ .LcallUR:
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
+index 3bbb4c7..8ebf317 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S
+@@ -82,7 +82,7 @@ __pthread_rwlock_rdlock:
+ #endif
+ 	addq	$READERS_WAKEUP, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	subq	$READERS_WAKEUP, %rdi
+ 
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
+index 40bcc04..d6c9c82 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
+@@ -109,7 +109,7 @@ pthread_rwlock_timedrdlock:
+ #endif
+ 21:	leaq	READERS_WAKEUP(%r12), %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	movq	%rax, %rdx
+ 
+ #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
+index f57ef52..78a2655 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
+@@ -106,7 +106,7 @@ pthread_rwlock_timedwrlock:
+ #endif
+ 21:	leaq	WRITERS_WAKEUP(%r12), %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 	movq	%rax, %rdx
+ 
+ #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
+index d779f7b..4dec0c0 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S
+@@ -79,7 +79,7 @@ __pthread_rwlock_unlock:
+ #endif
+ 	movl	$SYS_futex, %eax
+ 	movq	%r10, %rdi
+-	syscall
++	SYSCALL
+ 
+ 	xorl	%eax, %eax
+ 	retq
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
+index e444def..ba31821 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S
+@@ -80,7 +80,7 @@ __pthread_rwlock_wrlock:
+ #endif
+ 	addq	$WRITERS_WAKEUP, %rdi
+ 	movl	$SYS_futex, %eax
+-	syscall
++	SYSCALL
+ 
+ 	subq	$WRITERS_WAKEUP, %rdi
+ 
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
+index 1c11600..d276efa 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
+@@ -52,7 +52,7 @@ sem_post:
+ 	movl	$FUTEX_WAKE, %esi
+ 	orl	PRIVATE(%rdi), %esi
+ 	movl	$1, %edx
+-	syscall
++	SYSCALL
+ 
+ 	testq	%rax, %rax
+ 	js	1f
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+index 880610e..06fd57c 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+@@ -97,7 +97,7 @@ sem_timedwait:
+ 	orl	PRIVATE(%rdi), %esi
+ 	movl	$SYS_futex, %eax
+ 	xorl	%edx, %edx
+-	syscall
++	SYSCALL
+ 	movq	%rax, %r9
+ #if VALUE != 0
+ 	leaq	-VALUE(%rdi), %rdi
+@@ -233,7 +233,7 @@ sem_timedwait:
+ # endif
+ 	movl	$SYS_futex, %eax
+ 	xorl	%edx, %edx
+-	syscall
++	SYSCALL
+ 	movq	%rax, %r14
+ 
+ 	movl	16(%rsp), %edi
+diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+index 8f4d068..d9b49e4 100644
+--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
++++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+@@ -81,7 +81,7 @@ sem_wait:
+ 	orl	PRIVATE(%rdi), %esi
+ #endif
+ 	xorl	%edx, %edx
+-	syscall
++	SYSCALL
+ 	movq	%rax, %rcx
+ 
+ 	xchgq	%r8, %rdi
+diff --git a/nptl/sysdeps/x86_64/pthreaddef.h b/nptl/sysdeps/x86_64/pthreaddef.h
+index 18a15a1..ac3d6d3 100644
+--- a/nptl/sysdeps/x86_64/pthreaddef.h
++++ b/nptl/sysdeps/x86_64/pthreaddef.h
+@@ -48,4 +48,5 @@
+ 
+ /* While there is no such syscall.  */
+ #define __exit_thread_inline(val) \
+-  asm volatile ("syscall" :: "a" (__NR_exit), "D" (val))
++  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/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h
+index cbb5e9e..19b18ef 100644
+--- a/nptl/sysdeps/x86_64/tls.h
++++ b/nptl/sysdeps/x86_64/tls.h
+@@ -28,6 +28,7 @@
+ # include <sysdep.h>
+ # include <libc-internal.h>
+ # include <kernel-features.h>
++# include <shim_tls.h>
+ 
+ /* Replacement type for __m128 since this file is included by ld.so,
+    which is compiled with -mno-sse.  It must not change the alignment
+@@ -67,6 +68,10 @@ typedef struct
+ # else
+   int __glibc_reserved1;
+ # endif
++
++  shim_tcb_t shim_tcb;	/* For graphene, we allocate a shim_tcb
++			   in the real tcb. */
++
+   int rtld_must_xmm_save;
+   /* Reservation of some values for the TM ABI.  */
+   void *__private_tm[4];
+@@ -137,6 +142,12 @@ typedef struct
+ # define GET_DTV(descr) \
+   (((tcbhead_t *) (descr))->dtv)
+ 
++/* For Graphene */
++#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
+@@ -154,7 +165,7 @@ typedef struct
+      _head->self = _thrdescr;						      \
+ 									      \
+      /* It is a simple syscall to set the %fs value for the thread.  */	      \
+-     asm volatile ("syscall"						      \
++     asm volatile (SYSCALLDB						      \
+ 		   : "=a" (_result)					      \
+ 		   : "0" ((unsigned long int) __NR_arch_prctl),		      \
+ 		     "D" ((unsigned long int) ARCH_SET_FS),		      \
+diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs
+index 55d537f..57bf12b 100755
+--- a/scripts/mkinstalldirs
++++ b/scripts/mkinstalldirs
+@@ -126,9 +126,9 @@ do
+     esac
+ 
+     if test ! -d "$pathcomp"; then
+-      echo "mkdir $pathcomp"
++      echo "mkdir -p $pathcomp"
+ 
+-      mkdir "$pathcomp" || lasterr=$?
++      mkdir -p "$pathcomp" || lasterr=$?
+ 
+       if test ! -d "$pathcomp"; then
+ 	errstatus=$lasterr
+diff --git a/shlib-versions b/shlib-versions
+index 78b0ad7..5c3dcf2 100644
+--- a/shlib-versions
++++ b/shlib-versions
+@@ -108,3 +108,5 @@ sparc64.*-.*-.*		libBrokenLocale=1	GLIBC_2.2
+ # This defines the libgcc soname version this glibc is to load for
+ # asynchronous cancellation to work correctly.
+ .*-.*-.*		libgcc_s=1
++
++.*-.*-.*		liblibos=1
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index ffeb093..7a9fbcb 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -881,8 +881,7 @@ extern void _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used,
+    any shared object mappings.  The `r_state' member of `struct r_debug'
+    says what change is taking place.  This function's address is
+    the value of the `r_brk' member.  */
+-extern void _dl_debug_state (void);
+-rtld_hidden_proto (_dl_debug_state)
++extern void __libc_dl_debug_state (void) __attribute__((weak));
+ 
+ /* Initialize `struct r_debug' if it has not already been done.  The
+    argument is the run-time load address of the dynamic linker, to be put
+diff --git a/sysdeps/unix/sysv/linux/_exit.c b/sysdeps/unix/sysv/linux/_exit.c
+index 2468228..a9f1cd6 100644
+--- a/sysdeps/unix/sysv/linux/_exit.c
++++ b/sysdeps/unix/sysv/linux/_exit.c
+@@ -29,9 +29,9 @@ _exit (status)
+   while (1)
+     {
+ #ifdef __NR_exit_group
+-      INLINE_SYSCALL (exit_group, 1, status);
++      INLINE_SYSCALL_ASM (exit_group, 1, status);
+ #endif
+-      INLINE_SYSCALL (exit, 1, status);
++      INLINE_SYSCALL_ASM (exit, 1, status);
+ 
+ #ifdef ABORT_INSTRUCTION
+       ABORT_INSTRUCTION;
+diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
+index 49f0384..ee59c00 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
++++ b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
+@@ -84,7 +84,8 @@ ENTRY(____longjmp_chk)
+ 	xorl	%edi, %edi
+ 	lea	-sizeSS(%rsp), %RSI_LP
+ 	movl	$__NR_sigaltstack, %eax
+-	syscall
++	SYSCALL
++
+ 	/* Without working sigaltstack we cannot perform the test.  */
+ 	testl	%eax, %eax
+ 	jne	.Lok2
+diff --git a/sysdeps/unix/sysv/linux/x86_64/clock_gettime.c b/sysdeps/unix/sysv/linux/x86_64/clock_gettime.c
+index f712110..f6bad14 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/clock_gettime.c
++++ b/sysdeps/unix/sysv/linux/x86_64/clock_gettime.c
+@@ -1,5 +1,6 @@
+ #include "bits/libc-vdso.h"
+ 
++#if 0 /* in Graphene, disallow VDSO calls */
+ #ifdef SHARED
+ # define SYSCALL_GETTIME(id, tp) \
+   ({ long int (*f) (clockid_t, struct timespec *) = __vdso_clock_gettime; \
+@@ -16,5 +17,6 @@
+   PTR_DEMANGLE (f);							  \
+   f (id, tp); })
+ #endif
++#endif
+ 
+ #include "../clock_gettime.c"
+diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S
+index 0508730..c011e7a 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/clone.S
++++ b/sysdeps/unix/sysv/linux/x86_64/clone.S
+@@ -59,11 +59,15 @@ ENTRY (__clone)
+ 	jz	SYSCALL_ERROR_LABEL
+ 
+ 	/* Insert the argument onto the new stack.  */
+-	subq	$16,%rsi
+-	movq	%rcx,8(%rsi)
++	subq	$24,%rsi
++	movq	%rcx,16(%rsi)
+ 
+ 	/* Save the function pointer.  It will be popped off in the
+ 	   child in the ebx frobbing below.  */
++	movq	%rdi,8(%rsi)
++
++	/* Push an additional pointer as return address into the stack */
++	leaq	L(clone_return)(%rip),%rdi
+ 	movq	%rdi,0(%rsi)
+ 
+ 	/* Do the system call.  */
+@@ -76,8 +80,9 @@ ENTRY (__clone)
+ 	/* End FDE now, because in the child the unwind info will be
+ 	   wrong.  */
+ 	cfi_endproc;
+-	syscall
++	SYSCALL
+ 
++L(clone_return):
+ 	testq	%rax,%rax
+ 	jl	SYSCALL_ERROR_LABEL
+ 	jz	L(thread_start)
+@@ -99,13 +104,14 @@ L(thread_start):
+ 	movl	$-1, %eax
+ 	jne	2f
+ 	movl	$SYS_ify(getpid), %eax
+-	syscall
++	SYSCALL
+ 2:	movl	%eax, %fs:PID
+ 	movl	%eax, %fs:TID
+ 1:
+ #endif
+ 
+ 	/* Set up arguments for the function call.  */
++	addq	$8,%rsp		/* Skip the return address */
+ 	popq	%rax		/* Function to call.  */
+ 	popq	%rdi		/* Argument.  */
+ 	call	*%rax
+diff --git a/sysdeps/unix/sysv/linux/x86_64/getcontext.S b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
+index 140db03..870fb02 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/getcontext.S
++++ b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
+@@ -75,7 +75,7 @@ ENTRY(__getcontext)
+ #endif
+ 	movl	$_NSIG8,%r10d
+ 	movl	$__NR_rt_sigprocmask, %eax
+-	syscall
++	SYSCALL
+ 	cmpq	$-4095, %rax		/* Check %rax for error.  */
+ 	jae	SYSCALL_ERROR_LABEL	/* Jump to error handler if error.  */
+ 
+diff --git a/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c b/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
+index 440ca7f..571125d 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
++++ b/sysdeps/unix/sysv/linux/x86_64/gettimeofday.c
+@@ -17,6 +17,7 @@
+ 
+ #include <sys/time.h>
+ 
++#if 0 /* In graphene, do not use vsyscall or VDSO call */
+ #ifdef SHARED
+ 
+ # include <dl-vdso.h>
+@@ -42,7 +43,8 @@ asm (".type __gettimeofday, %gnu_indirect_function");
+ asm (".globl __GI___gettimeofday\n"
+      "__GI___gettimeofday = __gettimeofday");
+ 
+-#else
++#endif
++#endif
+ 
+ # include <sysdep.h>
+ # include <errno.h>
+@@ -54,6 +56,5 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
+ }
+ libc_hidden_def (__gettimeofday)
+ 
+-#endif
+ weak_alias (__gettimeofday, gettimeofday)
+ libc_hidden_weak (gettimeofday)
+diff --git a/sysdeps/unix/sysv/linux/x86_64/sched_getcpu.S b/sysdeps/unix/sysv/linux/x86_64/sched_getcpu.S
+index 0fd47f2..0247e2f 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/sched_getcpu.S
++++ b/sysdeps/unix/sysv/linux/x86_64/sched_getcpu.S
+@@ -30,6 +30,7 @@ ENTRY (sched_getcpu)
+ 	sub	$0x8, %rsp
+ 	cfi_adjust_cfa_offset(8)
+ 
++#if 0 /* for Graphene, never do VDSO calls */
+ 	movq	%rsp, %rdi
+ 	xorl	%esi, %esi
+ 	movl	$VGETCPU_CACHE_OFFSET, %edx
+@@ -39,16 +40,19 @@ ENTRY (sched_getcpu)
+ 	movq	__vdso_getcpu(%rip), %rax
+ 	PTR_DEMANGLE (%rax)
+ 	callq	*%rax
+-#else
+-# ifdef __NR_getcpu
++#endif
++#endif
++
++#ifdef __NR_getcpu
+ 	movl	$__NR_getcpu, %eax
+-	syscall
+-#  ifndef __ASSUME_GETCPU_SYSCALL
++	SYSCALL
++#endif
++
++#if 0 /* for Graphene, never do vsyscall */
++# ifndef __ASSUME_GETCPU_SYSCALL
+ 	cmpq	$-ENOSYS, %rax
+ 	jne	1f
+-#  endif
+-# endif
+-# ifndef __ASSUME_GETCPU_SYSCALL
++
+ 	movq	$VSYSCALL_ADDR_vgetcpu, %rax
+ 	callq	*%rax
+ 1:
+diff --git a/sysdeps/unix/sysv/linux/x86_64/setcontext.S b/sysdeps/unix/sysv/linux/x86_64/setcontext.S
+index b726fa0..96bf0ec 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/setcontext.S
++++ b/sysdeps/unix/sysv/linux/x86_64/setcontext.S
+@@ -43,7 +43,7 @@ ENTRY(__setcontext)
+ 	movl	$SIG_SETMASK, %edi
+ 	movl	$_NSIG8,%r10d
+ 	movl	$__NR_rt_sigprocmask, %eax
+-	syscall
++	SYSCALL
+ 	popq	%rdi			/* Reload %rdi, adjust stack.  */
+ 	cfi_adjust_cfa_offset(-8)
+ 	cmpq	$-4095, %rax		/* Check %rax for error.  */
+diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
+index ab23985..39d0bdc 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c
++++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c
+@@ -129,7 +129,8 @@ asm									\
+    "	.type __" #name ",@function\n"					\
+    "__" #name ":\n"							\
+    "	movq $" #syscall ", %rax\n"					\
+-   "	syscall\n"							\
++   "	movq syscalldb@GOTPCREL(%rip), %rbx\n"				\
++   "	call *%rbx\n"							\
+    ".LEND_" #name ":\n"							\
+    ".section .eh_frame,\"a\",@progbits\n"				\
+    ".LSTARTFRAME_" #name ":\n"						\
+diff --git a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
+index b3854fa..fd42f66 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
++++ b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
+@@ -75,7 +75,7 @@ ENTRY(__swapcontext)
+ 	movl	$SIG_SETMASK, %edi
+ 	movl	$_NSIG8,%r10d
+ 	movl	$__NR_rt_sigprocmask, %eax
+-	syscall
++	SYSCALL
+ 	cmpq	$-4095, %rax		/* Check %rax for error.  */
+ 	jae	SYSCALL_ERROR_LABEL	/* Jump to error handler if error.  */
+ 
+diff --git a/sysdeps/unix/sysv/linux/x86_64/syscall.S b/sysdeps/unix/sysv/linux/x86_64/syscall.S
+index 92c2f5b..7b7ee12 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/syscall.S
++++ b/sysdeps/unix/sysv/linux/x86_64/syscall.S
+@@ -34,7 +34,7 @@ ENTRY (syscall)
+ 	movq %r8, %r10
+ 	movq %r9, %r8
+ 	movq 8(%rsp),%r9	/* arg6 is on the stack.  */
+-	syscall			/* Do the system call.  */
++	SYSCALL			/* Do the system call.  */
+ 	cmpq $-4095, %rax	/* Check %rax for error.  */
+ 	jae SYSCALL_ERROR_LABEL	/* Jump to error handler if error.  */
+ 	ret			/* Return to caller.  */
+diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+index 4a9a9d9..3b7434d 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
++++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+@@ -21,6 +21,7 @@
+ /* There is some commonality.  */
+ #include <sysdeps/unix/x86_64/sysdep.h>
+ #include <tls.h>
++#include "syscalldb.h"
+ 
+ #ifdef IS_IN_rtld
+ # include <dl-sysdep.h>		/* Defines RTLD_PRIVATE_ERRNO.  */
+@@ -172,11 +173,18 @@
+ 
+     Syscalls of more than 6 arguments are not supported.  */
+ 
++# undef	SYSCALL
++# define SYSCALL				\
++    pushq %rbx;					\
++    movq syscalldb@GOTPCREL(%rip), %rbx;	\
++    call *%rbx;					\
++    popq %rbx;
++
+ # undef	DO_CALL
+ # define DO_CALL(syscall_name, args)		\
+     DOARGS_##args				\
+     movl $SYS_ify (syscall_name), %eax;		\
+-    syscall;
++    SYSCALL
+ 
+ # define DOARGS_0 /* nothing */
+ # define DOARGS_1 /* nothing */
+@@ -190,9 +198,20 @@
+ /* Define a macro which expands inline into the wrapper code for a system
+    call.  */
+ # undef INLINE_SYSCALL
+-# define INLINE_SYSCALL(name, nr, args...) \
++# define INLINE_SYSCALL(name, nr_args...) \
++  ({									      \
++    unsigned long int resultvar = INTERNAL_SYSCALL (name, , ##nr_args);	      \
++    if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))	      \
++      {									      \
++	__set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));		      \
++	resultvar = (unsigned long int) -1;				      \
++      }									      \
++    (long int) resultvar; })
++
++# undef INLINE_SYSCALL_ASM
++# define INLINE_SYSCALL_ASM(name, nr_args...) \
+   ({									      \
+-    unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args);	      \
++    unsigned long int resultvar = INTERNAL_SYSCALL_ASM (name, , ##nr_args);   \
+     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))	      \
+       {									      \
+ 	__set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));		      \
+@@ -204,9 +223,9 @@
+    into the wrapper code for a system call.  It should be used when size
+    of any argument > size of long int.  */
+ # undef INLINE_SYSCALL_TYPES
+-# define INLINE_SYSCALL_TYPES(name, nr, args...) \
++# define INLINE_SYSCALL_TYPES(name, nr_args...) \
+   ({									      \
+-    unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args);  \
++    unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , ##nr_args); \
+     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))	      \
+       {									      \
+ 	__set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));		      \
+@@ -223,13 +242,20 @@
+     LOAD_ARGS_##nr (args)						      \
+     LOAD_REGS_##nr							      \
+     asm volatile (							      \
+-    "syscall\n\t"							      \
++    "movq syscalldb@GOTPCREL(%%rip), %%rbx\n\t"				      \
++    "call *%%rbx\n\t"							      \
+     : "=a" (resultvar)							      \
+-    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");		      \
++    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx", "bx");	      \
+     (long int) resultvar; })
++# define INTERNAL_SYSCALL_NCS_ASM INTERNAL_SYSCALL_NCS
++
+ # undef INTERNAL_SYSCALL
+-# define INTERNAL_SYSCALL(name, err, nr, args...) \
+-  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++# define INTERNAL_SYSCALL(name, err, nr_args...) \
++  INTERNAL_SYSCALL_NCS (__NR_##name, err, ##nr_args)
++
++# undef INTERNAL_SYSCALL_ASM
++# define INTERNAL_SYSCALL_ASM(name, err, nr_args...) \
++  INTERNAL_SYSCALL_NCS_ASM (__NR_##name, err, ##nr_args)
+ 
+ # define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
+   ({									      \
+@@ -237,9 +263,10 @@
+     LOAD_ARGS_TYPES_##nr (args)						      \
+     LOAD_REGS_TYPES_##nr (args)						      \
+     asm volatile (							      \
+-    "syscall\n\t"							      \
++    "movq syscalldb@GOTPCREL(%%rip), %%rbx\n\t"				      \
++    "call *%%rbx\n\t"							      \
+     : "=a" (resultvar)							      \
+-    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");		      \
++    : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx", "bx");	      \
+     (long int) resultvar; })
+ # undef INTERNAL_SYSCALL_TYPES
+ # define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
+@@ -252,6 +279,7 @@
+ # undef INTERNAL_SYSCALL_ERRNO
+ # define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
+ 
++# if 0 /* for Graphene, never do vsyscall */
+ # ifdef SHARED
+ #  define INLINE_VSYSCALL(name, nr, args...) \
+   ({									      \
+@@ -300,12 +328,13 @@
+     v_ret;								      \
+   })
+ 
+-# else
+-#  define INLINE_VSYSCALL(name, nr, args...) \
+-  INLINE_SYSCALL (name, nr, ##args)
+-#  define INTERNAL_VSYSCALL(name, err, nr, args...) \
+-  INTERNAL_SYSCALL (name, err, nr, ##args)
+ # endif
++# endif
++
++#  define INLINE_VSYSCALL(name, nr_args...) \
++  INLINE_SYSCALL (name, ##nr_args)
++#  define INTERNAL_VSYSCALL(name, err, nr_args...) \
++  INTERNAL_SYSCALL (name, err, ##nr_args)
+ 
+ # define LOAD_ARGS_0()
+ # define LOAD_REGS_0
+diff --git a/sysdeps/unix/sysv/linux/x86_64/time.c b/sysdeps/unix/sysv/linux/x86_64/time.c
+deleted file mode 100644
+index 79f1fab..0000000
+--- a/sysdeps/unix/sysv/linux/x86_64/time.c
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/* Copyright (C) 2001-2014 Free Software Foundation, Inc.
+-   This file is part of the GNU C Library.
+-
+-   The GNU C Library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Lesser General Public
+-   License as published by the Free Software Foundation; either
+-   version 2.1 of the License, or (at your option) any later version.
+-
+-   The GNU C Library is distributed in the hope that it will be useful,
+-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+-   Lesser General Public License for more details.
+-
+-   You should have received a copy of the GNU Lesser General Public
+-   License along with the GNU C Library; if not, see
+-   <http://www.gnu.org/licenses/>.  */
+-
+-#ifdef SHARED
+-/* Redefine time so that the compiler won't complain about the type
+-   mismatch with the IFUNC selector in strong_alias, below.  */
+-#undef time
+-#define time __redirect_time
+-#include <time.h>
+-
+-#include <dl-vdso.h>
+-
+-#define VSYSCALL_ADDR_vtime	0xffffffffff600400
+-
+-/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+-   ifunc symbol properly.  */
+-extern __typeof (__redirect_time) __libc_time;
+-void *time_ifunc (void) __asm__ ("__libc_time");
+-
+-void *
+-time_ifunc (void)
+-{
+-  PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
+-
+-  /* If the vDSO is not available we fall back on the old vsyscall.  */
+-  return _dl_vdso_vsym ("__vdso_time", &linux26) ?: (void *) VSYSCALL_ADDR_vtime;
+-}
+-__asm (".type __libc_time, %gnu_indirect_function");
+-
+-#undef time
+-strong_alias (__libc_time, time)
+-libc_hidden_ver (__libc_time, time)
+-
+-#else
+-
+-# include <time.h>
+-# include <sysdep.h>
+-
+-time_t
+-time (time_t *t)
+-{
+-  INTERNAL_SYSCALL_DECL (err);
+-  return INTERNAL_SYSCALL (time, err, 1, t);
+-}
+-
+-#endif
+diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S
+index d3b450a..76bda33 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/vfork.S
++++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S
+@@ -38,7 +38,7 @@ ENTRY (__vfork)
+ 
+ 	/* Stuff the syscall number in RAX and enter into the kernel.  */
+ 	movl	$SYS_ify (vfork), %eax
+-	syscall
++	SYSCALL
+ 
+ 	/* Push back the return PC.  */
+ 	pushq	%rdi
+diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
+index 504c95f..dcfc259 100644
+--- a/sysdeps/x86_64/dl-machine.h
++++ b/sysdeps/x86_64/dl-machine.h
+@@ -529,7 +529,8 @@ elf_machine_lazy_rel (struct link_map *map,
+ 	value = ((ElfW(Addr) (*) (void)) value) ();
+       *reloc_addr = value;
+     }
+-  else
++  /* for graphene, get around R_X86_64_NONE */
++  else if (__builtin_expect (r_type != R_X86_64_NONE, 1))
+     _dl_reloc_bad_type (map, r_type, 1);
+ }
+ 

+ 1 - 0
LibOS/glibc-2.19/elf/syscallas.S

@@ -0,0 +1 @@
+../syscallas.S

+ 1 - 0
LibOS/glibc-2.19/elf/syscalldb.c

@@ -0,0 +1 @@
+../syscalldb.c

+ 56 - 0
LibOS/glibc-2.19/libos/Makefile

@@ -0,0 +1,56 @@
+# Copyright (C) 1996-2001,2002,2003,2004,2005,2006
+#	Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+# Makefile for the libos library.
+
+subdir		:= libos
+
+# Installed header files.
+headers		:= 
+
+# Internal header files.
+distribute	:= errno.h
+
+liblibos-routines := checkpoint sandbox msgpersist benchmark
+
+# Build the -llibos library.
+
+extra-libs	:= liblibos
+extra-libs-others = $(extra-libs)
+
+include ../Makeconfig
+
+ifeq ($(versioning),yes)
+liblibos-routines	+=
+liblibos-shared-only-routines :=
+endif
+
+tests =
+
+modules-names =
+
+extra-test-objs += $(modules-names:=.os)
+generated := $(modules-names:=.so)
+
+include ../Rules
+
+# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
+# This ensures they will load libc.so for needed symbols if loaded by
+# a statically-linked program that hasn't already loaded it.
+$(objpfx)liblibos.so: $(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a

+ 15 - 0
LibOS/glibc-2.19/libos/Versions

@@ -0,0 +1,15 @@
+liblibos {
+  GLIBC_2.12 {
+    # checkpoint.c
+    checkpoint;
+
+    # sandbox.c
+    sandbox_create; sandbox_attach; sandbox_current;
+
+    # msgpersist.c
+    msgpersist;
+
+    # benchmark.c
+    benchmark_rpc; send_rpc; recv_rpc;
+  }
+}

+ 27 - 0
LibOS/glibc-2.19/libos/benchmark.c

@@ -0,0 +1,27 @@
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <kernel-features.h>
+#include <sysdep.h>
+#include <shim_unistd.h>
+
+#ifdef __NR_benchmark_rpc
+int benchmark_rpc(pid_t pid, int times, const void * buf, size_t size)
+{
+	return INLINE_SYSCALL (benchmark_rpc, 4, pid, times, buf, size);
+}
+#endif
+
+#ifdef __NR_send_rpc
+size_t send_rpc (pid_t pid, const void * buf, size_t size)
+{
+	return INLINE_SYSCALL (send_rpc, 3, pid, buf, size);
+}
+#endif
+
+#ifdef __NR_recv_rpc
+size_t recv_rpc (pid_t * pid, void * buf, size_t size)
+{
+	return INLINE_SYSCALL (recv_rpc, 3, pid, buf, size);
+}
+#endif

+ 13 - 0
LibOS/glibc-2.19/libos/checkpoint.c

@@ -0,0 +1,13 @@
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <kernel-features.h>
+#include <sysdep.h>
+#include <shim_unistd.h>
+
+#ifdef __NR_checkpoint
+int checkpoint (const char * filename)
+{
+	return INLINE_SYSCALL (checkpoint, 1, filename);
+}
+#endif

+ 13 - 0
LibOS/glibc-2.19/libos/msgpersist.c

@@ -0,0 +1,13 @@
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <kernel-features.h>
+#include <sysdep.h>
+#include <shim_unistd.h>
+
+#ifdef __NR_msgpersist
+int msgpersist (int msqid, int cmd)
+{
+	return INLINE_SYSCALL (msgpersist, 2, msqid, cmd);
+}
+#endif

+ 27 - 0
LibOS/glibc-2.19/libos/sandbox.c

@@ -0,0 +1,27 @@
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <kernel-features.h>
+#include <sysdep.h>
+#include <shim_unistd.h>
+
+#ifdef __NR_sandbox_create
+long sandbox_create(int flags, const char *fs_sb, struct net_sb *net_sb)
+{
+	return INLINE_SYSCALL (sandbox_create, 3, flags, fs_sb, net_sb);
+}
+#endif
+
+#ifdef __NR_sandbox_attach
+int sandbox_attach(unsigned int sbid)
+{
+	return INLINE_SYSCALL (sandbox_attach, 1, sbid);
+}
+#endif
+
+#ifdef __NR_sandbox_current
+long sandbox_current(void)
+{
+	return INLINE_SYSCALL (sandbox_current, 0);
+}
+#endif

+ 11 - 0
LibOS/glibc-2.19/syscallas.S

@@ -0,0 +1,11 @@
+#include <syscalldb.h>
+
+.weak syscalldb
+.type syscalldb,@function
+
+syscalldb:
+	.cfi_startproc
+	syscall
+	retq
+	.cfi_endproc
+	.size syscalldb,.-syscalldb

+ 10 - 0
LibOS/glibc-2.19/syscalldb.c

@@ -0,0 +1,10 @@
+#include "syscalldb.h"
+#include <stdarg.h>
+
+int register_library (const char * name, unsigned long load_address)
+	__attribute__((weak));
+
+int register_library (const char * name, unsigned long load_address)
+{
+	return 0;
+}

+ 15 - 0
LibOS/glibc-2.19/syscalldb.h

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

+ 1 - 0
LibOS/glibc-2.19/sysdeps/unix/sysv/linux/x86_64/syscalldb.h

@@ -0,0 +1 @@
+../../../../../syscalldb.h

+ 266 - 404
LibOS/shim/include/shim_checkpoint.h

@@ -48,16 +48,16 @@ extern char __migratable;
 extern char __migratable_end;
 
 /* TSAI 7/11/2012:
-   The migration scheme we are expecting is to support an easy syntax to
+   The checkpoint scheme we are expecting is to support an easy syntax to
    implement migration procedure. A migration procedure can be written
    in teh following syntax:
 
-   BEGIN_MIGRATE_DEFINITION(exec)
+   BEGIN_CP_DEFINITION(exec)
    {
-       DEFINE_MIGRATE(thread, );
-       DEFINE_MIGRATE(handle_map, );
+       DEFINE_CP(thread, ...);
+       DEFINE_CP(handle_map, ...);
    }
-   void *checkpoint = DO_MIGRATE(exec);
+   void * checkpoint = DO_CHECKPOINT(exec);
 
    The structure of checkpoint data will be a counting-down stack-like
    memory segment, with enough space reserved below for 1. in case the
@@ -66,32 +66,14 @@ extern char __migratable_end;
 
    Below is the figure for our checkpoint structure:
 
-   (later added by PAL:  argc        program arguments
-                         argv[0]
-                         argv[1]
-                         ...
-                         envp[0]     env variables
-                         envp[1]
-                         ...
-                         NULL-end
-                         auxv[0]     aux vectors
-                         auxv[1]
-                         ...
-                         auxv[n]     AT_NULL
    Low Bytes -------------------------------------------------
-                checkpoint base (identified by a magic number)
-             -------------------------------------------------
                 checkpoint_entry[0]
+                data section for checkpoint 0
                 checkpoint_entry[1]
+                data section for checkpoint 1
                 checkpoint_entry[2]
                 ...
                 checkpoint_entry[n]  CP_NULL
-              ------------------------------------------------
-                data section for checkpoint 0
-                data section for checkpoint 1
-                data section for checkpoint 2
-                ...
-                data section for checkpoint n-1
    High Bytes ------------------------------------------------
 
 
@@ -107,457 +89,340 @@ struct shim_cp_entry
     } cp_un;
 };
 
-struct shim_gipc_entry {
-    struct shim_gipc_entry * next;
-    enum { ABS_ADDR, REL_ADDR, ANY_ADDR } addr_type;
+struct shim_mem_entry {
+    struct shim_mem_entry * prev;
     void * addr;
-    int npages;
+    int size;
+    void ** paddr;
     int prot;
-    struct shim_vma * vma;
+    void * data;
+};
+
+struct shim_gipc_entry {
+    struct shim_mem_entry mem;
 #if HASH_GIPC == 1
     unsigned long first_hash;
 #endif
 };
 
-#define SET_GIPC_REL_ADDR(gipc)                                             \
-    do {                                                                    \
-         (gipc)->addr_type = REL_ADDR;                                      \
-         (gipc)->addr = (void *) ((gipc)->addr - (void *) &__load_address); \
-    } while (0)
-
-struct shim_mem_entry {
-    void * addr;
-    int size;
-    int prot;
-    bool need_alloc, need_prot;
-    struct shim_vma * vma;
-    void * data;
+struct shim_palhdl_entry {
+    struct shim_palhdl_entry * prev;
+    PAL_HANDLE handle;
+    struct shim_qstr * uri;
+    PAL_HANDLE * phandle;
 };
 
 struct shim_cp_store {
-    void * cpaddr;
-    void * cpdata;
-    size_t cpsize;
-    void * addr_map;
-    bool use_gipc;
-    struct shim_gipc_entry * gipc_entries, * gipc_entries_tail;
-    int gipc_nentries;
-};
+    /* checkpoint data mapping */
+    void * cp_map;
+    struct shim_handle * cp_file;
 
-#define INIT_CP_STORE_GIPC(store)                       \
-    do {                                                \
-        (store)->use_gipc = false;                      \
-        (store)->gipc_entries = NULL;                   \
-        (store)->gipc_entries_tail = NULL;              \
-        (store)->gipc_nentries = 0;                     \
-    } while (0)
+    /* allocation method for check point area */
+    void * (*alloc) (struct shim_cp_store * store, void * mem, int size);
 
-#define INIT_CP_STORE(store)                            \
-    do {                                                \
-        (store)->cpaddr = NULL;                         \
-        (store)->cpdata = NULL;                         \
-        (store)->cpsize = 0;                            \
-        (store)->addr_map = create_addr_map();          \
-        INIT_CP_STORE_GIPC(store);                      \
-    } while (0)
+    /* check point area */
+    ptr_t base, offset, bound;
+
+    /* entries of gipc records */
+    bool use_gipc;
+    struct shim_gipc_entry * last_gipc_entry;
+    int gipc_nentries;
 
-#define MIGRATE_FUNC_ARGS                                                   \
-    struct shim_cp_store * store, struct shim_cp_entry ** ent, ptr_t base,  \
-    unsigned long * offset, void * obj, size_t size, void ** objp,          \
-    bool recursive, bool dry
+    /* entries of out-of-band data */
+    struct shim_mem_entry * last_mem_entry;
+    int mem_nentries;
+    int mem_size;
 
-#define MIGRATE_FUNC_RET size_t
+    /* entries of pal handles to send */
+    struct shim_palhdl_entry * last_palhdl_entry;
+    int palhdl_nentries;
+};
 
-#define RESUME_FUNC_ARGS                                                    \
-    struct shim_cp_entry ** ent, ptr_t base, size_t cpsize, long cprebase
+#define CP_FUNC_ARGS                                    \
+    struct shim_cp_store * store, void * obj, int size, void ** objp
 
-#define RESUME_FUNC_RET int
+#define RS_FUNC_ARGS                                    \
+    struct shim_cp_entry * entry, ptr_t base, ptr_t * offset, long rebase
 
-typedef MIGRATE_FUNC_RET (*migrate_func) (MIGRATE_FUNC_ARGS);
-typedef RESUME_FUNC_RET (*resume_func) (RESUME_FUNC_ARGS);
+#define DEFINE_CP_FUNC(name) int cp_##name (CP_FUNC_ARGS)
+#define DEFINE_RS_FUNC(name) int rs_##name (RS_FUNC_ARGS)
 
-extern const char *       __migrate_name;
-extern const migrate_func __migrate_func;
-extern const resume_func  __resume_func;
+typedef int (*cp_func) (CP_FUNC_ARGS);
+typedef int (*rs_func) (RS_FUNC_ARGS);
 
-#define CP_NULL   0
-#define CP_IGNORE 1
-#define CP_BASE   2
-#define CP_ADDR   3
-#define CP_SIZE   4
-#define CP_PID    5
-#define CP_UID    6
-#define CP_GID    7
-#define CP_FD     8
-#define CP_BOOL   9
-#define CP_PALHDL 10
+extern const char *  __cp_name;
+extern const cp_func __cp_func;
+extern const rs_func __rs_func;
 
-#define CP_FUNC_BASE   11
+enum {
+    CP_NULL = 0,
+    CP_IGNORE,
+    CP_OOB,
+    CP_ADDR,
+    CP_SIZE,
+    CP_FUNC_BASE,
+};
 
-#define CP_FUNC_INDEX(name)                                             \
-    ({  extern const migrate_func migrate_func_##name;                  \
-        &migrate_func_##name - &__migrate_func;  })
+#define CP_FUNC_INDEX(name)                                         \
+    ({ extern const cp_func cp_func_##name; &cp_func_##name - &__cp_func; })
 
 #define CP_FUNC(name)   CP_FUNC_BASE + CP_FUNC_INDEX(name)
-#define CP_FUNC_NAME(type)      (&__migrate_name)[(type) - CP_FUNC_BASE]
-
-#define ADD_ENTRY(type, value)                                      \
-    do {                                                            \
-        USED += sizeof(struct shim_cp_entry);                       \
-        if (!dry) {                                                 \
-            struct shim_cp_entry * tmp = (*ent)++;                  \
-            tmp->cp_type = CP_##type;                               \
-            tmp->cp_un.cp_val = (ptr_t) (value);                    \
+#define CP_FUNC_NAME(type)      (&__cp_name)[(type) - CP_FUNC_BASE]
+
+#define __ADD_CP_OFFSET(size)                                       \
+    ({                                                              \
+        ptr_t _off = store->offset;                                 \
+        if (store->offset + (size) > store->bound) {                \
+            int new_bound = store->bound * 2;                       \
+                                                                    \
+            while (store->offset + (size) > new_bound)              \
+                new_bound *= 2;                                     \
                                                                     \
-            if (DEBUG_CHECKPOINT)                                   \
-                debug("ADD CP_" #type "(%p) :%d\n",                 \
-                      tmp->cp_un.cp_val,                            \
-                      tmp - (struct shim_cp_entry *) base);         \
-        } else {                                                    \
-            if (DEBUG_CHECKPOINT)                                   \
-                debug("(dry) ADD CP_" #type "\n");                  \
+            void * buf = store->alloc(store,                        \
+                                      (void *) store->base + store->bound, \
+                                      new_bound - store->bound);    \
+            if (!buf)                                               \
+                return -ENOMEM;                                     \
+                                                                    \
+            store->bound = new_bound;                               \
         }                                                           \
-    } while(0)
+        store->offset += size;                                      \
+    _off;  })
 
-#define ADD_OFFSET(size)                                            \
+#define ADD_CP_ENTRY(type, value)                                   \
     ({                                                              \
-        int _size = ((size) + 7) & ~7;                              \
-        USED += _size;                                              \
-        if (!dry)                                                   \
-            *offset -= _size;                                       \
+        struct shim_cp_entry * tmp =                                \
+                (void *) base +                                     \
+                __ADD_CP_OFFSET(sizeof(struct shim_cp_entry));      \
+        tmp->cp_type = CP_##type;                                   \
+        tmp->cp_un.cp_val = (ptr_t) (value);                        \
         if (DEBUG_CHECKPOINT)                                       \
-            debug("%sADD OFFSET(%d)\n",                             \
-                  dry ? "(dry) " : "", _size);                      \
-        dry ? 0 : *offset;                                          \
-    })
-
-#define ADD_FUNC_ENTRY(value)                                       \
-    do {                                                            \
-        USED += sizeof(struct shim_cp_entry);                       \
-        if (!dry) {                                                 \
-            struct shim_cp_entry * tmp = (*ent)++;                  \
-            tmp->cp_type = CP_FUNC_TYPE;                            \
-            tmp->cp_un.cp_val = (ptr_t) value;                      \
-                                                                    \
-            if (DEBUG_CHECKPOINT)                                   \
-                debug("ADD CP_FUNC_%s(%p) :%d\n", CP_FUNC_NAME,     \
-                      tmp->cp_un.cp_val,                            \
-                      tmp - (struct shim_cp_entry *) base);         \
-        } else {                                                    \
-            if (DEBUG_CHECKPOINT)                                   \
-                debug("(dry) ADD CP_FUNC_%s\n", CP_FUNC_NAME);      \
-        }                                                           \
-    } while(0)
+            debug("ADD CP_" #type "(%p) >%d\n", tmp->cp_un.cp_val,  \
+                  store->offset);                                   \
+    tmp; })
 
+#define ADD_CP_OFFSET(size)                                         \
+    ({                                                              \
+        int _size = ((size) + sizeof(void *) - 1) &                 \
+                    ~(sizeof(void *) - 1);                          \
+        struct shim_cp_entry * oob =                                \
+                (void *) base +                                     \
+                __ADD_CP_OFFSET(sizeof(struct shim_cp_entry));      \
+        oob->cp_type = CP_OOB;                                      \
+        oob->cp_un.cp_val = (ptr_t) _size;                          \
+        ptr_t _off = (ptr_t) __ADD_CP_OFFSET(_size);                \
+        if (DEBUG_CHECKPOINT)                                       \
+            debug("ADD OFFSET(%d) >%d\n", (size), store->offset);   \
+    _off; })
 
-#define GET_ENTRY(type)                                             \
-    ({  struct shim_cp_entry * tmp = (*ent)++;                      \
-                                                                    \
-        while (tmp->cp_type != CP_##type)                           \
-            tmp = (*ent)++;                                         \
-                                                                    \
-        /* debug("GET CP_" #type "(%p) :%d\n",                      \
-                 tmp->cp_un.cp_val,                                 \
-                 tmp - (struct shim_cp_entry *) base); */           \
-                                                                    \
-        tmp->cp_un.cp_val;                                          \
-     })
+#define ADD_CP_FUNC_ENTRY(value)                                    \
+    ({                                                              \
+        struct shim_cp_entry * tmp =                                \
+                (void *) base +                                     \
+                __ADD_CP_OFFSET(sizeof(struct shim_cp_entry));      \
+        tmp->cp_type = CP_FUNC_TYPE;                                \
+        tmp->cp_un.cp_val = (ptr_t) (value);                        \
+        if (DEBUG_CHECKPOINT)                                       \
+            debug("ADD %s(%p) >%d\n", CP_FUNC_NAME, (value),        \
+                  store->offset);                                   \
+    tmp; })
+
+#define NEXT_CP_ENTRY()                                             \
+    ({  struct shim_cp_entry * tmp;                                 \
+        while (1) {                                                 \
+            tmp = (void *) base + *offset;                          \
+            if (tmp->cp_type == CP_NULL) {                          \
+                tmp = NULL;                                         \
+                break;                                              \
+            }                                                       \
+            *offset += sizeof(struct shim_cp_entry);                \
+            if (tmp->cp_type == CP_OOB)                             \
+                *offset += tmp->cp_un.cp_val;                       \
+            else                                                    \
+                break;                                              \
+        }                                                           \
+    tmp; })
 
-#define GET_FUNC_ENTRY()                                            \
-    ({  struct shim_cp_entry * tmp = (*ent)++;                      \
-                                                                    \
-        while (tmp->cp_type != CP_FUNC_TYPE)                        \
-            tmp = (*ent)++;                                         \
-                                                                    \
-        /* debug("GET CP_FUNC_%s(%p) :%d\n", CP_FUNC_NAME,          \
-                 tmp->cp_un.cp_val,                                 \
-                 tmp - (struct shim_cp_entry *) base); */           \
+#define GET_CP_ENTRY(type)                                          \
+    ({  struct shim_cp_entry * tmp = NEXT_CP_ENTRY();               \
                                                                     \
-        tmp->cp_un.cp_val;                                          \
-     })
-
-
-#define DEFINE_MIGRATE_FUNC(name)                                   \
-    const char * migrate_name_##name                                \
-        __attribute__((section(".migrate_name." #name))) = #name;   \
+        while (tmp->cp_type != CP_##type)                           \
+            tmp = NEXT_CP_ENTRY();                                  \
                                                                     \
-    extern MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS);     \
-    const migrate_func migrate_func_##name                          \
-        __attribute__((section(".migrate." #name))) = &migrate_##name;\
+        /* debug("GET CP_" #type "(%p)\n",tmp->cp_un.cp_val); */    \
+    tmp->cp_un.cp_val; })
+
+#define GET_CP_FUNC_ENTRY()                                         \
+    ({  /* debug("GET CP_FUNC_%s(%p) :%d\n", CP_FUNC_NAME,          \
+                 entry->cp_un.cp_val); */                           \
+    entry->cp_un.cp_val; })
+
+#define BEGIN_CP_FUNC(name)                                         \
+    const char * cp_name_##name                                     \
+            __attribute__((section(".cp_name." #name))) = #name;    \
+    extern DEFINE_CP_FUNC(name);                                    \
+    extern DEFINE_RS_FUNC(name);                                    \
+    const cp_func cp_func_##name                                    \
+            __attribute__((section(".cp_func." #name))) = &cp_##name; \
+    const rs_func rs_func_##name                                    \
+            __attribute__((section(".rs_func." #name))) = &rs_##name; \
                                                                     \
-    extern RESUME_FUNC_RET resume_##name (RESUME_FUNC_ARGS);        \
-    const resume_func resume_func_##name                            \
-        __attribute__((section(".resume." #name))) = &resume_##name;\
+    DEFINE_PROFILE_INTERVAL(cp_##name, checkpoint_func);            \
+    DEFINE_PROFILE_INTERVAL(rs_##name, resume_func);                \
                                                                     \
-    DEFINE_PROFILE_INTERVAL(migrate_##name, migrate_func);          \
-    DEFINE_PROFILE_INTERVAL(resume_##name,  resume_func);           \
-
-
-#define MIGRATE_FUNC_BODY(name)                                 \
-    MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS)         \
-    {                                                           \
-        int CP_FUNC_TYPE __attribute__((unused))                \
-                                    = CP_FUNC(name);            \
-        const char * CP_FUNC_NAME __attribute__((unused))       \
-                                    = #name;                    \
-        size_t USED = 0;                                        \
-        BEGIN_PROFILE_INTERVAL();                               \
-        ASSIGN_PROFILE_INTERVAL(migrate_##name);
-
-#define END_MIGRATE_FUNC                                        \
-        if (!dry) SAVE_PROFILE_INTERVAL_ASSIGNED();             \
-        return USED;                                            \
+    DEFINE_CP_FUNC(name)                                            \
+    {                                                               \
+        int CP_FUNC_TYPE __attribute__((unused)) = CP_FUNC(name);   \
+        const char * CP_FUNC_NAME __attribute__((unused)) = #name;  \
+        ptr_t base __attribute__((unused)) = store->base;           \
+        BEGIN_PROFILE_INTERVAL();                                   \
+        ASSIGN_PROFILE_INTERVAL(cp_##name);
+
+#define END_CP_FUNC(name)                                           \
+        SAVE_PROFILE_INTERVAL_ASSIGNED();                           \
+        return 0;                                                   \
     }
 
-
-#define RESUME_FUNC_BODY(name)                                  \
-    RESUME_FUNC_RET resume_##name (RESUME_FUNC_ARGS)            \
-    {                                                           \
-        int CP_FUNC_TYPE __attribute__((unused))                \
-                                    = CP_FUNC(name);            \
-        const char * CP_FUNC_NAME __attribute__((unused))       \
-                                    = #name;                    \
-        BEGIN_PROFILE_INTERVAL();                               \
-        ASSIGN_PROFILE_INTERVAL(resume_##name);
-
-#define END_RESUME_FUNC \
-        SAVE_PROFILE_INTERVAL_ASSIGNED();                       \
-        return 0;                                               \
+#define END_CP_FUNC_NO_RS(name)                                     \
+    END_CP_FUNC(name)                                               \
+    BEGIN_RS_FUNC(name) {} END_RS_FUNC(name)
+
+#define BEGIN_RS_FUNC(name)                                         \
+    DEFINE_RS_FUNC(name)                                            \
+    {                                                               \
+        int CP_FUNC_TYPE __attribute__((unused)) = CP_FUNC(name);   \
+        const char * CP_FUNC_NAME __attribute__((unused)) = #name;  \
+        BEGIN_PROFILE_INTERVAL();                                   \
+        ASSIGN_PROFILE_INTERVAL(rs_##name);
+
+#define END_RS_FUNC(name)                                           \
+        SAVE_PROFILE_INTERVAL_ASSIGNED();                           \
+        return 0;                                                   \
     }
 
-#define RESUME_REBASE(obj)                                      \
+#define CP_REBASE(obj)                                          \
     do {                                                        \
         void * _ptr = &(obj);                                   \
         size_t _size = sizeof(obj);                             \
         void ** _p;                                             \
         for (_p = _ptr ; _p < (void **)(_ptr + _size) ; _p++)   \
             if (*_p)                                            \
-                *_p += cprebase;                                \
+                *_p += rebase;                                  \
     } while (0)
 
-
-struct shim_addr_map {
-    ptr_t addr;
-    unsigned long offset;
-    size_t size;
-};
-
-void * create_addr_map (void);
-void destroy_addr_map (void * map);
-
-struct shim_addr_map *
-get_addr_map_entry (void * map, ptr_t addr, size_t size, bool create);
-
-#define DO_MIGRATE_SIZE(name, obj, size, objp, recur)                       \
-    do {                                                                    \
-        extern MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS);         \
-                                                                            \
-        USED += migrate_##name (store, ent, base, offset,                   \
-                  obj, size, (void **) objp, recur, dry);                   \
+#define DO_CP_SIZE(name, obj, size, objp)                       \
+    do {                                                        \
+        extern DEFINE_CP_FUNC(name);                            \
+        int ret = cp_##name(store, obj, size, (void **) objp);  \
+        if (ret < 0) return ret;                                \
     } while (0)
 
 
-#define __DO_MIGRATE(name, obj, objp, recur)                                \
-    do {                                                                    \
-        extern MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS);         \
-                                                                            \
-        USED += migrate_##name (store, ent, base, offset,                   \
-                  obj, sizeof(*(obj)), (void **) objp, recur, dry);         \
-    } while (0)
+#define DO_CP(name, obj, objp)                                  \
+        DO_CP_SIZE(name, obj, sizeof(*obj), objp)
 
-#define DO_MIGRATE_MEMBER(name, obj, newobj, member, recur)                 \
-    do {                                                                    \
-        typeof(obj->member) *(objp) = (newobj) ?                            \
-                                      &(newobj)->member : NULL;             \
-                                                                            \
-        DO_MIGRATE(name, (obj)->member, (objp), (recur));                   \
-    } while (0);
+#define DO_CP_MEMBER(name, obj, newobj, member)                 \
+        DO_CP(name, (obj)->member, &((newobj)->member));
 
-#define DO_MIGRATE(name, obj, objp, recur)                                  \
-    do {                                                                    \
-        if (!obj)                                                           \
-            break;                                                          \
-                                                                            \
-        struct shim_addr_map * _e = get_addr_map_entry (store->addr_map,    \
-                                (ptr_t) (obj), sizeof(*(obj)), 0);          \
-                                                                            \
-        if (_e && !ENTRY_JUST_CREATED(_e->offset) && !(recur))              \
-        {                                                                   \
-            if (!dry && objp)                                               \
-                *((typeof(obj) *) objp) = (typeof(obj))                     \
-                                          (base + _e->offset);              \
-            break;                                                          \
-        }                                                                   \
-                                                                            \
-        if (dry ? !_e || (recur) : _e != NULL)                              \
-            __DO_MIGRATE(name, (obj), (objp), (recur));                     \
-    } while (0)
+#define DO_CP_IN_MEMBER(name, obj, member)                      \
+        DO_CP(name, &((obj)->member), NULL)
 
-#define DO_MIGRATE_MEMBER_IF_RECURSIVE(name, obj, newobj, member, recur)    \
-    do {                                                                    \
-        typeof(obj->member) *(objp) = (newobj) ?                            \
-                                      &(newobj)->member : NULL;             \
-                                                                            \
-        DO_MIGRATE_IF_RECURSIVE(name, (obj)->member, (objp), (recur));      \
-    } while (0);
-
-#define DO_MIGRATE_IF_RECURSIVE(name, obj, objp, recur)                     \
-    do {                                                                    \
-        extern MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS);         \
-        if (!obj)                                                           \
-            break;                                                          \
-                                                                            \
-        struct shim_addr_map * _e = get_addr_map_entry (store->addr_map,    \
-                                (ptr_t) (obj), sizeof(*(obj)), 0);          \
-                                                                            \
-        if (!_e && !recursive)                                              \
-        {                                                                   \
-            if (!dry && objp) *objp = NULL;                                 \
-            break;                                                          \
-        }                                                                   \
-                                                                            \
-        if (_e && !ENTRY_JUST_CREATED(_e->offset) && !(recur))              \
-        {                                                                   \
-            if (!dry && objp)                                               \
-                *((typeof(obj) *) objp) = (typeof(obj))                     \
-                                          (base + _e->offset);              \
-            break;                                                          \
-        }                                                                   \
-                                                                            \
-        /* 3 condition we need to run a recursive search                    \
-               _e && !recursive && dry && recur                             \
-               !_e && recursive && dry                                      \
-               _e && !dry               */                                  \
-        if (dry ?                                                           \
-            (_e ? !recursive && (recur) : recursive) : _e != NULL)          \
-                __DO_MIGRATE(name, (obj), (objp), (recur));                 \
-    } while (0)
-
-#define DO_MIGRATE_IN_MEMBER(name, obj, newobj, member, recur)              \
-    __DO_MIGRATE(name, dry ? &(obj)->member : &(newobj)->member,            \
-                 NULL, (recur))
+struct shim_cp_map_entry { void * addr; ptr_t off; };
 
-#define CHECKPOINT_ADDR (NULL)
+void * create_cp_map (void);
+void destroy_cp_map (void * map);
 
-#define MAP_UNALLOCATED 0x8000000000000000
-#define MAP_UNASSIGNED  0x4000000000000000
-#define MAP_UNUSABLE (MAP_UNALLOCATED|MAP_UNASSIGNED)
+struct shim_cp_map_entry *
+get_cp_map_entry (void * map, void * addr, bool create);
 
-#define ENTRY_JUST_CREATED(off) (off & MAP_UNUSABLE)
-
-static inline __attribute__((always_inline))
-ptr_t add_to_migrate_map (void * map, void * obj, ptr_t off,
-                          size_t size, bool dry)
-{
-    struct shim_addr_map * e = get_addr_map_entry(map,
-                    (ptr_t) obj, size, 1);
-
-    ptr_t result = e->offset;
-    if (dry) {
-        if (result & MAP_UNALLOCATED)
-            e->offset = MAP_UNASSIGNED;
-        else
-            result = 0;
-    } else {
-        if (result & MAP_UNUSABLE) {
-            assert(size);
-            assert(off >= size);
-            e->offset = off - size;
-            e->size = size;
-        }
-    }
+#define GET_FROM_CP_MAP(obj)                                    \
+    ({                                                          \
+        struct shim_cp_map_entry * e =                          \
+                get_cp_map_entry(store->cp_map, (obj), false);  \
+    e ? e->off : 0; })
 
-    return result;
-}
-
-#define ADD_TO_MIGRATE_MAP(obj, off, size) \
-        add_to_migrate_map(store->addr_map, (obj), dry ? 0 : (off), (size), dry)
-
-#define MIGRATE_DEF_ARGS    \
-        struct shim_cp_store * store, void * data, size_t size, bool dry
+#define ADD_TO_CP_MAP(obj, off)                                 \
+    do {                                                        \
+        struct shim_cp_map_entry * e =                          \
+                get_cp_map_entry(store->cp_map, (obj), true);   \
+        e->off = off;                                           \
+    } while (0)
 
 #define BEGIN_MIGRATION_DEF(name, ...)                                  \
-    auto size_t migrate_def_##name (MIGRATE_DEF_ARGS, ##__VA_ARGS__)    \
+    int migrate_##name (struct shim_cp_store * store, ##__VA_ARGS__)    \
     {                                                                   \
-        size_t USED = 0;                                                \
-        unsigned long offset = size;                                    \
-        struct shim_cp_entry * ENTRY = (struct shim_cp_entry *) data;   \
-        struct shim_cp_entry * *ent = &ENTRY;                           \
-        uintptr_t base = (uintptr_t) data;
-
+        int ret = 0;                                                    \
+        ptr_t base = store->base;
 
-#define END_MIGRATION_DEF                                       \
-        ADD_ENTRY(NULL, 0);                                     \
-        return USED;                                            \
+#define END_MIGRATION_DEF(name)                                         \
+        ADD_CP_ENTRY(NULL, 0);                                          \
+        return 0;                                                       \
     }
 
-
-#define DEFINE_MIGRATE(name, obj, size, recursive)                          \
-    do {                                                                    \
-        extern MIGRATE_FUNC_RET migrate_##name (MIGRATE_FUNC_ARGS);         \
-                                                                            \
-        USED += migrate_##name(store, ent, dry ? 0 : base,                  \
-                  dry ? 0 : &offset, (obj), (size), NULL, recursive, dry);  \
+#define DEFINE_MIGRATE(name, obj, size)                                 \
+    do {                                                                \
+        extern DEFINE_CP_FUNC(name);                                    \
+        if ((ret = cp_##name(store, (obj), (size), NULL)) < 0)          \
+            return ret;                                                 \
     } while (0)
 
 #define DEBUG_RESUME      0
 #define DEBUG_CHECKPOINT  0
 
-#ifndef malloc_method
-#define malloc_method(size) system_malloc(size)
+#if DEBUG_RESUME == 1
+# define DEBUG_RS(fmt, ...)                                              \
+    debug("GET %s(%p): " fmt "\n", CP_FUNC_NAME, entry->cp_un.cp_val,    \
+          ##__VA_ARGS__)
+#else
+# define DEBUG_RS(...) do {} while (0)
 #endif
 
 #include <shim_profile.h>
 
-#define START_MIGRATE(store, name, preserve, ...)                           \
-    ({  int _ret = 0;                                                       \
+#define START_MIGRATE(store, name, ...)                                     \
+    ({  int ret = 0;                                                        \
         do {                                                                \
-            size_t size;                                                    \
-            void * data;                                                    \
-                                                                            \
             BEGIN_PROFILE_INTERVAL();                                       \
                                                                             \
-            size = migrate_def_##name((store), NULL, 0, true, ##__VA_ARGS__) \
-                   + (preserve);                                            \
-            SAVE_PROFILE_INTERVAL(checkpoint_predict_size);                 \
-            ADD_PROFILE_OCCURENCE(checkpoint_total_size, size);             \
-            INC_PROFILE_OCCURENCE(checkpoint_count);                        \
+            if (!((store)->cp_map = create_cp_map())) {                     \
+                ret = -ENOMEM;                                              \
+                goto out;                                                   \
+            }                                                               \
+            SAVE_PROFILE_INTERVAL(checkpoint_create_map);                   \
                                                                             \
-            data = malloc_method(size);                                     \
-            SAVE_PROFILE_INTERVAL(checkpoint_alloc_memory);                 \
-            debug("allocate checkpoint: %p\n", data);                       \
+            ret = migrate_##name((store), ##__VA_ARGS__);                   \
+            if (ret < 0)                                                    \
+                goto out;                                                   \
                                                                             \
-            if (!data) {                                                    \
-                destroy_addr_map((store)->addr_map);                        \
-                (store)->addr_map = NULL;                                   \
-                SAVE_PROFILE_INTERVAL(checkpoint_destroy_addr_map);         \
-                _ret = -ENOMEM;                                             \
-                break;                                                      \
-            }                                                               \
-            (store)->cpaddr = data;                                         \
-            (store)->cpdata = data + (preserve);                            \
-            (store)->cpsize = size;                                         \
+            SAVE_PROFILE_INTERVAL(checkpoint_copy);                         \
+            ADD_PROFILE_OCCURENCE(checkpoint_total_size, (store)->offset);  \
+            INC_PROFILE_OCCURENCE(checkpoint_count);                        \
                                                                             \
-            migrate_def_##name((store), data + (preserve), size - (preserve), \
-                               false, ##__VA_ARGS__);                       \
-            SAVE_PROFILE_INTERVAL(checkpoint_copy_object);                  \
             debug("complete checkpointing data\n");                         \
-                                                                            \
-            destroy_addr_map((store)->addr_map);                            \
-            SAVE_PROFILE_INTERVAL(checkpoint_destroy_addr_map);             \
+        out:                                                                \
+            destroy_cp_map((store)->cp_map);                                \
+            SAVE_PROFILE_INTERVAL(checkpoint_destroy_map);                  \
         } while (0);                                                        \
-        _ret; })
+        ret; })
 
 struct newproc_cp_header {
     struct cp_header {
-        unsigned long cpsize;
-        void * cpaddr;
-        unsigned long cpoffset;
-    } data;
+        unsigned long size;
+        void * addr;
+        unsigned long offset;
+    } hdr;
+    struct mem_header {
+        unsigned long entoffset;
+        int nentries;
+    } mem;
+    struct palhdl_header {
+        unsigned long entoffset;
+        int nentries;
+    } palhdl;
     struct gipc_header {
-        PAL_NUM gipc_key;
-        unsigned long gipc_entoffset;
-        int gipc_nentries;
+        char uri[16];
+        unsigned long entoffset;
+        int nentries;
     } gipc;
 };
 
@@ -578,30 +443,27 @@ struct newproc_response {
 
 int do_migration (struct newproc_cp_header * hdr, void ** cpptr);
 
-int restore_checkpoint (void * cpdata, struct cp_header * hdr, int type);
-int restore_gipc (PAL_HANDLE gipc, struct gipc_header * hdr, void * cpdata,
-                  long cprebase);
-int send_checkpoint_by_gipc (PAL_HANDLE gipc_store,
-                             struct shim_cp_store * cpstore);
-int send_handles_on_stream (PAL_HANDLE stream, void * cpdata);
+int restore_checkpoint (struct cp_header * cphdr, struct mem_header * memhdr,
+                        ptr_t base, int type);
 
 int do_migrate_process (int (*migrate) (struct shim_cp_store *,
-                                        struct shim_process *,
-                                        struct shim_thread *, va_list),
-                        struct shim_handle * exec, const char ** argv,
+                                        struct shim_thread *,
+                                        struct shim_process *, va_list),
+                        struct shim_handle * exec,
+                        const char ** argv,
                         struct shim_thread * thread, ...);
 
 int init_from_checkpoint_file (const char * filename,
                                struct newproc_cp_header * hdr,
                                void ** cpptr);
+
 int restore_from_file (const char * filename, struct newproc_cp_header * hdr,
                        void ** cpptr);
 
 void restore_context (struct shim_context * context);
 
-#define CHECKPOINT_REQUESTED        ((IDTYPE) -1)
-
 int create_checkpoint (const char * cpdir, IDTYPE * session);
-int join_checkpoint (struct shim_thread * cur, ucontext_t * context);
+int join_checkpoint (struct shim_thread * cur, ucontext_t * context,
+                     IDTYPE sid);
 
 #endif /* _SHIM_CHECKPOINT_H_ */

+ 5 - 1
LibOS/shim/include/shim_defs.h

@@ -4,11 +4,15 @@
 #ifndef _SHIM_DEFS_H_
 #define _SHIM_DEFS_H_
 
-#define HASH_GIPC                   (0)
+#define MIGRATE_MORE_GIPC           0
+
+#define HASH_GIPC                   0
 
 #define DEFAULT_HEAP_MIN_SIZE       (256 * 1024 * 1024) /* 256MB */
 #define DEFAULT_MEM_MAX_NPAGES      (1024 * 1024)       /* 4GB */
 #define DEFAULT_BRK_MAX_SIZE        (256 * 1024)        /* 256KB */
 #define DEFAULT_SYS_STACK_SIZE      (256 * 1024)        /* 256KB */
 
+#define CP_INIT_VMA_SIZE            (64 * 1024 * 1024)  /* 64MB */
+
 #endif /* _SHIM_DEFS_H_ */

+ 35 - 25
LibOS/shim/include/shim_fs.h

@@ -34,8 +34,6 @@
 #include <pal.h>
 #include <linux_list.h>
 
-#include <sys/stat.h>
-
 struct shim_handle;
 
 #define FS_POLL_RD         0x01
@@ -143,9 +141,6 @@ struct shim_dentry {
     struct list_head children;
     struct list_head siblings;
 
-    struct shim_dentry * symlink;   /* point to symlink target, or
-                                       sources (aliases) of linking */
-    struct list_head alias;
     struct shim_mount * mounted;
     void * data;
     unsigned long ino;
@@ -242,7 +237,6 @@ extern struct shim_dentry * dentry_root;
 
 #define NO_MODE     ((mode_t) -1)
 
-#define O_ACCMODE   (O_RDONLY|O_WRONLY|O_RDWR)
 #define ACC_MODE(x) ((((x) == O_RDONLY || (x) == O_RDWR) ? MAY_READ : 0) | \
                      (((x) == O_WRONLY || (x) == O_RDWR) ? MAY_WRITE : 0))
 
@@ -338,40 +332,56 @@ int directory_open (struct shim_handle * hdl, struct shim_dentry * dent,
 void get_dentry (struct shim_dentry * dent);
 void put_dentry (struct shim_dentry * dent);
 
+static inline __attribute__((always_inline))
+void fast_pathcpy (char * dst, const char * src, int size, char ** ptr)
+{
+    char * d = dst;
+    const char * s = src;
+    for (int i = 0 ; i < size ; i++, s++, d++)
+        *d = *s;
+    *ptr = d;
+}
+
 static inline __attribute__((always_inline))
 char * dentry_get_path (struct shim_dentry * dent, bool on_stack,
                         int * sizeptr)
 {
     struct shim_mount * fs = dent->fs;
-    int bufsize = (fs ? fs->path.len + 1 : 0) + dent->rel_path.len;
-    char * buffer = on_stack ? __alloca(bufsize) : malloc(bufsize);
-    char * c = buffer;
+    char * buffer, * c;
+    int bufsize = dent->rel_path.len + 1;
 
-    if (!buffer)
-        return NULL;
+    if (fs)
+        bufsize += fs->path.len + 1;
 
-    if (fs && !qstrempty(&fs->path)) {
-        memcpy(c, qstrgetstr(&fs->path), fs->path.len);
-        c += fs->path.len;
+    if (on_stack) {
+        c = buffer = __alloca(bufsize);
+    } else {
+        if (!(c = buffer = malloc(bufsize)))
+            return NULL;
     }
 
+    if (fs && !qstrempty(&fs->path))
+        fast_pathcpy(c, qstrgetstr(&fs->path), fs->path.len, &c);
+
     if (dent->rel_path.len) {
-        if (c == buffer || *(c - 1) != '/')
-            *(c++) = '/';
-        memcpy(c, qstrgetstr(&dent->rel_path), dent->rel_path.len);
-        c += dent->rel_path.len;
-    } else {
-        if (c != buffer && *(c - 1) == '/')
-            c--;
-        if (c == buffer)
-            *(c++) = '/';
+        const char * path = qstrgetstr(&dent->rel_path);
+        int len = dent->rel_path.len;
+
+        if (c > buffer && *(c - 1) == '/') {
+            if (*path == '/')
+                path++;
+        } else {
+            if (*path != '/')
+                *(c++) = '/';
+        }
+
+        fast_pathcpy(c, path, len, &c);
     }
 
-    *c = 0;
-
     if (sizeptr)
         *sizeptr = c - buffer;
 
+    *c = 0;
     return buffer;
 }
 

+ 25 - 7
LibOS/shim/include/shim_handle.h

@@ -33,14 +33,12 @@
 #include <pal.h>
 #include <linux_list.h>
 
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <linux/shm.h>
-#include <linux/msg.h>
+#include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/un.h>
-#include <netinet/in.h>
+
+#include <asm/fcntl.h>
 
 /* start definition of shim handle */
 enum shim_handle_type {
@@ -74,7 +72,7 @@ struct shim_file_data {
     struct shim_atomic  version;
     bool                queried;
     enum shim_file_type type;
-    mode_t              mode;
+    mode_t     mode;
     struct shim_atomic  size;
     struct shim_qstr    host_uri;
     unsigned long       atime;
@@ -133,6 +131,23 @@ struct shim_pipe_handle {
 #endif
 };
 
+#define SOCK_STREAM     1
+#define SOCK_DGRAM      2
+#define SOCK_NONBLOCK   04000
+#define SOCK_CLOEXEC    02000000
+
+#define SOL_TCP         6
+
+#define PF_LOCAL        1
+#define PF_UNIX         PF_LOCAL
+#define PF_FILE         PF_LOCAL
+#define PF_INET         2
+#define PF_INET6        10
+
+#define AF_UNIX         PF_UNIX
+#define AF_INET         PF_INET
+#define AF_INET6        PF_INET6
+
 enum shim_sock_state {
     SOCK_CREATED,
     SOCK_BOUND,
@@ -395,4 +410,7 @@ int init_important_handles (void);
 
 size_t get_file_size (struct shim_handle * file);
 
+int do_handle_read (struct shim_handle * hdl, void * buf, int count);
+int do_handle_write (struct shim_handle * hdl, const void * buf, int count);
+
 #endif /* _SHIM_HANDLE_H_ */

+ 38 - 17
LibOS/shim/include/shim_signal.h

@@ -31,20 +31,20 @@ struct shim_signal_handle {
 /* Clear all signals from SET.  */
 #  define __sigemptyset(set)                                    \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            sigset_t *__set = (set);                            \
+            __sigset_t *__set = (set);                          \
             while (--__cnt >= 0) __set->__val[__cnt] = 0;       \
             0; }))
 
 /* Set all signals in SET.  */
 #  define __sigfillset(set)                                     \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            sigset_t *__set = (set);                            \
+            __sigset_t *__set = (set);                          \
             while (--__cnt >= 0) __set->__val[__cnt] = ~0UL;    \
             0; }))
 
 #   define __sigisemptyset(set)                                 \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            const sigset_t *__set = (set);                      \
+            const __sigset_t *__set = (set);                    \
             int __ret = __set->__val[--__cnt];                  \
             while (!__ret && --__cnt >= 0)                      \
                 __ret = __set->__val[__cnt];                    \
@@ -52,9 +52,9 @@ struct shim_signal_handle {
 
 #   define __sigandset(dest, left, right)                       \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            sigset_t *__dest = (dest);                          \
-            const sigset_t *__left = (left);                    \
-            const sigset_t *__right = (right);                  \
+            __sigset_t *__dest = (dest);                        \
+            const __sigset_t *__left = (left);                  \
+            const __sigset_t *__right = (right);                \
             while (--__cnt >= 0)                                \
                 __dest->__val[__cnt] = (__left->__val[__cnt]    \
                                         & __right->__val[__cnt]); \
@@ -62,9 +62,9 @@ struct shim_signal_handle {
 
 #   define __sigorset(dest, left, right)                        \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            sigset_t *__dest = (dest);                          \
-            const sigset_t *__left = (left);                    \
-            const sigset_t *__right = (right);                  \
+            __sigset_t *__dest = (dest);                        \
+            const __sigset_t *__left = (left);                  \
+            const __sigset_t *__right = (right);                \
             while (--__cnt >= 0)                                \
                 __dest->__val[__cnt] = (__left->__val[__cnt]    \
                                         | __right->__val[__cnt]); \
@@ -72,9 +72,9 @@ struct shim_signal_handle {
 
 #   define __signotset(dest, left, right)                       \
     (__extension__ ({ int __cnt = _SIGSET_NWORDS;               \
-            sigset_t *__dest = (dest);                          \
-            const sigset_t *__left = (left);                    \
-            const sigset_t *__right = (right);                  \
+            __sigset_t *__dest = (dest);                        \
+            const __sigset_t *__left = (left);                  \
+            const __sigset_t *__right = (right);                \
             while (--__cnt >= 0)                                \
                 __dest->__val[__cnt] = (__left->__val[__cnt]    \
                                         & ~__right->__val[__cnt]); \
@@ -111,6 +111,28 @@ struct shim_signal_log {
     struct shim_signal * logs[MAX_SIGNAL_LOG];
 };
 
+extern const char * const siglist[NUM_KNOWN_SIGS + 1];
+
+static inline const char * signal_name (int sig)
+{
+    if (sig <= NUM_KNOWN_SIGS)
+        return siglist[sig];
+
+    if (sig >= NUM_SIGS)
+        return "BAD SIGNAL";
+
+    char * str = __alloca(6);
+
+    str[0] = 'S';
+    str[1] = 'I';
+    str[2] = 'G';
+    str[3] = '0' + sig / 10;
+    str[4] = '0' + sig % 10;
+    str[5] = 0;
+
+    return str;
+}
+
 struct shim_thread;
 
 int init_signal (void);
@@ -118,13 +140,12 @@ int init_signal (void);
 void __store_context (shim_tcb_t * tcb, PAL_CONTEXT * pal_context,
                       struct shim_signal * signal);
 
-void append_signal (struct shim_thread * thread, int sig, siginfo_t * info);
+void append_signal (struct shim_thread * thread, int sig, siginfo_t * info,
+                    bool wakeup);
 void deliver_signal (siginfo_t * info, PAL_CONTEXT * context);
 
-sigset_t * get_sig_mask (struct shim_thread * thread);
-sigset_t * set_sig_mask (struct shim_thread * thread, sigset_t * new_set);
-
-extern const char * const siglist[NUM_KNOWN_SIGS + 1];
+__sigset_t * get_sig_mask (struct shim_thread * thread);
+__sigset_t * set_sig_mask (struct shim_thread * thread, __sigset_t * new_set);
 
 int do_kill_thread (IDTYPE sender, IDTYPE tgid, IDTYPE tid, int sig,
                     bool use_ipc);

+ 16 - 16
LibOS/shim/include/shim_table.h

@@ -329,7 +329,7 @@ int shim_do_munmap (void * addr, size_t len);
 void * shim_do_brk (void * brk);
 int shim_do_sigaction (int signum, const struct __kernel_sigaction * act,
                        struct __kernel_sigaction * oldact);
-int shim_do_sigprocmask (int how, const sigset_t * set, sigset_t * oldset);
+int shim_do_sigprocmask (int how, const __sigset_t * set, __sigset_t * oldset);
 int shim_do_sigreturn (int __unused);
 int shim_do_ioctl (int fd, int cmd, unsigned long arg);
 size_t shim_do_pread64 (int fd, char * buf, size_t count, loff_t pos);
@@ -429,7 +429,7 @@ int shim_do_setrlimit (int resource, struct __kernel_rlimit * rlim);
 int shim_do_chroot (const char * filename);
 pid_t shim_do_gettid (void);
 int shim_do_tkill (int pid, int sig);
-int shim_do_time (time_t * tloc);
+time_t shim_do_time (time_t * tloc);
 int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
                    unsigned int * uaddr2, int val3);
 int shim_do_set_tid_address (int * tidptr);
@@ -454,14 +454,14 @@ int shim_do_fchmodat (int dfd, const char * filename, mode_t mode);
 int shim_do_faccessat (int dfd, const char * filename, mode_t mode);
 int shim_do_pselect6 (int nfds, fd_set * readfds, fd_set * writefds,
                       fd_set * exceptfds, const struct __kernel_timespec * tsp,
-                      const sigset_t * sigmask);
+                      const __sigset_t * sigmask);
 int shim_do_ppoll (struct pollfd * fds, int nfds, struct timespec * tsp,
-                   const sigset_t * sigmask, size_t sigsetsize);
+                   const __sigset_t * sigmask, size_t sigsetsize);
 int shim_do_set_robust_list (struct robust_list_head * head, size_t len);
 int shim_do_get_robust_list (pid_t pid, struct robust_list_head ** head,
                              size_t * len);
 int shim_do_epoll_pwait (int epfd, struct __kernel_epoll_event * events,
-                         int maxevents, int timeout, const sigset_t * sigmask,
+                         int maxevents, int timeout, const __sigset_t * sigmask,
                          size_t sigsetsize);
 int shim_do_accept4 (int sockfd, struct sockaddr * addr, socklen_t * addrlen,
                      int flags);
@@ -496,7 +496,7 @@ int shim_munmap (void * addr, size_t len);
 void * shim_brk (void * brk);
 int shim_rt_sigaction (int signum, const struct __kernel_sigaction * act,
                        struct __kernel_sigaction * oldact);
-int shim_rt_sigprocmask (int how, const sigset_t * set, sigset_t * oldset);
+int shim_rt_sigprocmask (int how, const __sigset_t * set, __sigset_t * oldset);
 int shim_rt_sigreturn (int __unused);
 int shim_ioctl (int fd, int cmd, unsigned long arg);
 size_t shim_pread64 (int fd, char * buf, size_t count, loff_t pos);
@@ -619,17 +619,17 @@ int shim_setfsgid (gid_t gid);
 int shim_getsid (pid_t pid);
 int shim_capget (cap_user_header_t header, cap_user_data_t dataptr);
 int shim_capset (cap_user_header_t header, const cap_user_data_t data);
-int shim_rt_sigpending (sigset_t * set, size_t sigsetsize);
-int shim_rt_sigtimedwait (const sigset_t * uthese, siginfo_t * uinfo,
+int shim_rt_sigpending (__sigset_t * set, size_t sigsetsize);
+int shim_rt_sigtimedwait (const __sigset_t * uthese, siginfo_t * uinfo,
                           const struct timespec * uts, size_t sigsetsize);
 int shim_rt_sigqueueinfo (int pid, int sig, siginfo_t * uinfo);
-int shim_rt_sigsuspend (const sigset_t * mask);
+int shim_rt_sigsuspend (const __sigset_t * mask);
 int shim_sigaltstack (const stack_t * ss, stack_t * oss);
 int shim_utime (char * filename, struct utimbuf * times);
 int shim_mknod (const char * filename, int mode, unsigned dev);
 int shim_uselib (const char * library);
 int shim_personality (unsigned int personality);
-int shim_ustat (unsigned dev, struct ustat * ubuf);
+int shim_ustat (unsigned dev, struct __kernel_ustat * ubuf);
 int shim_statfs (const char * path, struct statfs * buf);
 int shim_fstatfs (int fd, struct statfs * buf);
 int shim_sysfs (int option, unsigned long arg1, unsigned long arg2);
@@ -696,7 +696,7 @@ int shim_removexattr (const char * path, const char * name);
 int shim_lremovexattr (const char * path, const char * name);
 int shim_fremovexattr (int fd, const char * name);
 int shim_tkill (int pid, int sig);
-int shim_time (time_t * tloc);
+time_t shim_time (time_t * tloc);
 int shim_futex (unsigned int * uaddr, int op, int val, void * utime,
                 unsigned int * uaddr2, int val3);
 int shim_sched_setaffinity (pid_t pid, size_t len,
@@ -790,9 +790,9 @@ int shim_fchmodat (int dfd, const char * filename, mode_t mode);
 int shim_faccessat (int dfd, const char * filename, int mode);
 int shim_pselect6 (int nfds, fd_set * readfds, fd_set * writefds,
                    fd_set * exceptfds, const struct __kernel_timespec * tsp,
-                   const sigset_t * sigmask);
+                   const __sigset_t * sigmask);
 int shim_ppoll (struct pollfd * fds, int nfds, struct timespec * tsp,
-                const sigset_t * sigmask, size_t sigsetsize);
+                const __sigset_t * sigmask, size_t sigsetsize);
 int shim_unshare (int unshare_flags);
 int shim_set_robust_list (struct robust_list_head * head, size_t len);
 int shim_get_robust_list (pid_t pid, struct robust_list_head ** head,
@@ -808,9 +808,9 @@ int shim_move_pages (pid_t pid, unsigned long nr_pages, void ** pages,
 int shim_utimensat (int dfd, const char * filename, struct timespec *
                     utimes, int flags);
 int shim_epoll_pwait (int epfd, struct __kernel_epoll_event * events,
-                      int maxevents, int timeout, const sigset_t * sigmask,
+                      int maxevents, int timeout, const __sigset_t * sigmask,
                       size_t sigsetsize);
-int shim_signalfd (int ufd, sigset_t * user_mask, size_t sizemask);
+int shim_signalfd (int ufd, __sigset_t * user_mask, size_t sizemask);
 int shim_timerfd_create (int clockid, int flags);
 int shim_eventfd (int count);
 int shim_fallocate (int fd, int mode, loff_t offset, loff_t len);
@@ -820,7 +820,7 @@ int shim_timerfd_settime (int ufd, int flags,
 int shim_timerfd_gettime (int ufd, struct __kernel_itimerspec * otmr);
 int shim_accept4 (int sockfd, struct sockaddr * addr, socklen_t * addrlen,
                   int flags);
-int shim_signalfd4 (int ufd, sigset_t * user_mask, size_t sizemask, int flags);
+int shim_signalfd4 (int ufd, __sigset_t * user_mask, size_t sizemask, int flags);
 int shim_eventfd2 (int count, int flags);
 int shim_epoll_create1 (int flags);
 int shim_dup3 (int oldfd, int newfd, int flags);

+ 26 - 7
LibOS/shim/include/shim_thread.h

@@ -53,10 +53,10 @@ struct shim_thread {
     int * set_child_tid, * clear_child_tid;
 
     /* signal handling */
-    sigset_t signal_mask;
+    __sigset_t signal_mask;
     struct shim_signal_handle signal_handles[NUM_SIGS];
     struct shim_atomic has_signal;
-    struct shim_signal_log signal_logs[NUM_SIGS];
+    struct shim_signal_log * signal_logs;
 
     /* futex robust list */
     void * robust_list;
@@ -84,6 +84,10 @@ struct shim_thread {
 
     REFTYPE ref_count;
     LOCKTYPE lock;
+
+#ifdef PROFILE
+    unsigned long exit_time;
+#endif
 };
 
 struct shim_simple_thread {
@@ -101,6 +105,10 @@ struct shim_simple_thread {
 
     REFTYPE ref_count;
     LOCKTYPE lock;
+
+#ifdef PROFILE
+    unsigned long exit_time;
+#endif
 };
 
 int init_thread (void);
@@ -121,7 +129,7 @@ void put_thread (struct shim_thread * thread);
 void get_simple_thread (struct shim_simple_thread * thread);
 void put_simple_thread (struct shim_simple_thread * thread);
 
-void allocate_tls (void * tcb_location, struct shim_thread * thread);
+void allocate_tls (void * tcb_location, bool user, struct shim_thread * thread);
 void populate_tls (void * tcb_location, bool user);
 
 void debug_setprefix (shim_tcb_t * tcb);
@@ -159,14 +167,25 @@ void set_cur_thread (struct shim_thread * thread)
     (type *)( (char *)__mptr - offsetof(type,member) );})
 #endif
 
-    if (tcb->tp)
-        put_thread(tcb->tp);
+    if (thread) {
+        if (tcb->tp && tcb->tp != thread)
+            put_thread(tcb->tp);
 
-    tcb->tp = thread;
+        if (tcb->tp != thread)
+            get_thread(thread);
 
-    if (thread) {
+        tcb->tp = thread;
         thread->tcb = container_of(tcb, __libc_tcb_t, shim_tcb);
         tid = thread->tid;
+
+        if (!IS_INTERNAL(thread) && !thread->signal_logs)
+            thread->signal_logs = malloc(sizeof(struct shim_signal_log) *
+                                         NUM_SIGS);
+    } else if (tcb->tp) {
+        put_thread(tcb->tp);
+        tcb->tp = NULL;
+    } else {
+        bug();
     }
 
     if (tcb->tid != tid) {

+ 195 - 23
LibOS/shim/include/shim_types.h

@@ -4,20 +4,12 @@
 #ifndef _SHIM_TYPES_H_
 #define _SHIM_TYPES_H_
 
-#define _GNU_SOURCE
-#include <features.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ustat.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include <asm/statfs.h>
-#include <asm/ldt.h>
-#include <netinet/in.h>
+
+#define __KERNEL__
+
 #include <linux/types.h>
 #include <linux/utsname.h>
 #include <linux/times.h>
@@ -30,7 +22,29 @@
 #include <linux/aio_abi.h>
 #include <linux/perf_event.h>
 
-typedef unsigned int __u32;
+#include <asm/posix_types.h>
+#include <asm/statfs.h>
+#include <asm/stat.h>
+#include <asm/ldt.h>
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+#include <asm/poll.h>
+
+typedef unsigned int        __u32;
+
+typedef unsigned long int   nfds_t;
+typedef unsigned long int   nlink_t;
+
+typedef __kernel_caddr_t    caddr_t;
+typedef __kernel_mode_t     mode_t;
+typedef __kernel_loff_t     loff_t;
+typedef __kernel_time_t     time_t;
+typedef __kernel_old_dev_t  dev_t;
+typedef __kernel_ino_t      ino_t;
+typedef __kernel_clockid_t  clockid_t;
+typedef __kernel_key_t      key_t;
+typedef __kernel_timer_t    timer_t;
+typedef __kernel_fd_set     fd_set;
 
 /* linux/time.h */
 struct __kernel_timespec {
@@ -141,6 +155,12 @@ struct __kernel_sigaction {
 /* linux/aio_abi.h (for io_setup which has no glibc wrapper) */
 typedef unsigned long aio_context_t;
 
+/* bits/sigset.h */
+# define _SIGSET_NWORDS	(1024 / (8 * sizeof (unsigned long int)))
+typedef struct {
+    unsigned long int __val[_SIGSET_NWORDS];
+} __sigset_t;
+
 /* linux/rlimit.h */
 struct __kernel_rusage {
     struct __kernel_timeval ru_utime;    /* user time used */
@@ -182,16 +202,162 @@ __attribute__((packed));
 ;
 #endif
 
-/* buts/socket.h */
-#ifndef __USE_GNU
+/* sys/ucontext.h */
+/* Type for general register.  */
+typedef long int greg_t;
+
+/* Number of general registers.  */
+#define NGREG    23
+
+/* Container for all general registers.  */
+typedef greg_t gregset_t[NGREG];
+
+/* Number of each register in the `gregset_t' array.  */
+enum
+{
+    REG_R8 = 0,
+# define REG_R8     REG_R8
+    REG_R9,
+# define REG_R9     REG_R9
+    REG_R10,
+# define REG_R10    REG_R10
+    REG_R11,
+# define REG_R11    REG_R11
+    REG_R12,
+# define REG_R12    REG_R12
+    REG_R13,
+# define REG_R13    REG_R13
+    REG_R14,
+# define REG_R14    REG_R14
+    REG_R15,
+# define REG_R15    REG_R15
+    REG_RDI,
+# define REG_RDI    REG_RDI
+    REG_RSI,
+# define REG_RSI    REG_RSI
+    REG_RBP,
+# define REG_RBP    REG_RBP
+    REG_RBX,
+# define REG_RBX    REG_RBX
+    REG_RDX,
+# define REG_RDX    REG_RDX
+    REG_RAX,
+# define REG_RAX    REG_RAX
+    REG_RCX,
+# define REG_RCX    REG_RCX
+    REG_RSP,
+# define REG_RSP    REG_RSP
+    REG_RIP,
+# define REG_RIP    REG_RIP
+    REG_EFL,
+# define REG_EFL    REG_EFL
+    REG_CSGSFS,        /* Actually short cs, gs, fs, __pad0.  */
+# define REG_CSGSFS REG_CSGSFS
+    REG_ERR,
+# define REG_ERR    REG_ERR
+    REG_TRAPNO,
+# define REG_TRAPNO REG_TRAPNO
+    REG_OLDMASK,
+# define REG_OLDMASK REG_OLDMASK
+    REG_CR2
+# define REG_CR2    REG_CR2
+};
+
+struct _libc_fpxreg {
+    unsigned short int significand[4];
+    unsigned short int exponent;
+    unsigned short int padding[3];
+};
+
+struct _libc_xmmreg {
+    __uint32_t    element[4];
+};
+
+struct _libc_fpstate {
+    /* 64-bit FXSAVE format.  */
+    __uint16_t          cwd;
+    __uint16_t          swd;
+    __uint16_t          ftw;
+    __uint16_t          fop;
+    __uint64_t          rip;
+    __uint64_t          rdp;
+    __uint32_t          mxcsr;
+    __uint32_t          mxcr_mask;
+    struct _libc_fpxreg st[8];
+    struct _libc_xmmreg _xmm[16];
+    __uint32_t          padding[24];
+};
+
+/* Structure to describe FPU registers.  */
+typedef struct _libc_fpstate *fpregset_t;
+
+/* Context to describe whole processor state.  */
+typedef struct {
+    gregset_t gregs;
+    /* Note that fpregs is a pointer.  */
+    fpregset_t fpregs;
+    unsigned long __reserved1 [8];
+} mcontext_t;
+
+/* Userlevel context.  */
+typedef struct ucontext {
+    unsigned long int uc_flags;
+    struct ucontext *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    __sigset_t uc_sigmask;
+    struct _libc_fpstate __fpregs_mem;
+} ucontext_t;
+
+/* bits/ustat.h */
+struct __kernel_ustat
+  {
+    __daddr_t f_tfree;		/* Number of free blocks.  */
+    __ino_t f_tinode;		/* Number of free inodes.  */
+    char f_fname[6];
+    char f_fpack[6];
+  };
+
+/* bits/socket.h */
+struct msghdr {
+    void *msg_name;         /* Address to send to/receive from.  */
+    socklen_t msg_namelen;  /* Length of address data.  */
+
+    struct iovec *msg_iov;  /* Vector of data to send/receive into.  */
+    size_t msg_iovlen;      /* Number of elements in the vector.  */
+
+    void *msg_control;      /* Ancillary data (eg BSD filedesc passing). */
+    size_t msg_controllen;  /* Ancillary data buffer length.
+                               !! The type should be socklen_t but the
+                               definition of the kernel is incompatible
+                               with this.  */
+
+    int msg_flags;          /* Flags on received message.  */
+};
+
 /* For `recvmmsg'.  */
 struct mmsghdr {
     struct msghdr msg_hdr;  /* Actual message header.  */
     unsigned int msg_len;   /* Number of received bytes for the entry.  */
 };
-#endif
+
+/* POSIX.1g specifies this type name for the `sa_family' member.  */
+typedef unsigned short int sa_family_t;
+
+/* This macro is used to declare the initial common members
+   of the data types used for socket addresses, `struct sockaddr',
+   `struct sockaddr_in', `struct sockaddr_un', etc.  */
+
+#define	__SOCKADDR_COMMON(sa_prefix) \
+  sa_family_t sa_prefix##family
 
 
+/* Structure describing a generic socket address.  */
+struct sockaddr {
+    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
+    char sa_data[14];           /* Address data.  */
+};
+
 /* linux/mqueue.h */
 struct __kernel_mq_attr {
     long    mq_flags;       /* message queue flags */
@@ -201,6 +367,12 @@ struct __kernel_mq_attr {
     long    __reserved[4];  /* ignored for input, zeroed for output */
 };
 
+/* bits/uio.h */
+/* Structure for scatter/gather I/O.  */
+struct iovec {
+    void * iov_base;    /* Pointer to data.  */
+    size_t iov_len;     /* Length of data.  */
+};
 
 /* bits/sched.h */
 /* Type for array elements in 'cpu_set_t'.  */
@@ -250,14 +422,14 @@ struct linux_dirent_tail {
 
 struct __kernel_addrinfo
 {
-  int ai_flags;			/* Input flags.  */
-  int ai_family;		/* Protocol family for socket.  */
-  int ai_socktype;		/* Socket type.  */
-  int ai_protocol;		/* Protocol for socket.  */
-  socklen_t ai_addrlen;		/* Length of socket address.  */
-  struct sockaddr *ai_addr;	/* Socket address for socket.  */
-  char *ai_canonname;		/* Canonical name for service location.  */
-  struct addrinfo *ai_next;	/* Pointer to next in list.  */
+  int ai_flags;                 /* Input flags.  */
+  int ai_family;                /* Protocol family for socket.  */
+  int ai_socktype;              /* Socket type.  */
+  int ai_protocol;              /* Protocol for socket.  */
+  socklen_t ai_addrlen;         /* Length of socket address.  */
+  struct sockaddr *ai_addr;     /* Socket address for socket.  */
+  char *ai_canonname;           /* Canonical name for service location.  */
+  struct addrinfo *ai_next;     /* Pointer to next in list.  */
 };
 
 #include "elf.h"

+ 9 - 0
LibOS/shim/include/shim_unistd.h

@@ -62,6 +62,15 @@ struct nameinfo {
 
 int checkpoint (const char * filename);
 
+struct sigcp {
+    int si_session;
+};
+
+#define si_cp_session(info) \
+    (((struct sigcp *) (info)->_sifields._pad)->si_session)
+
+#define SIGCP                   33
+
 #define SHIM_NSYSCALLS          311
 
 #endif /* _SHIM_UNISTD_H_ */

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

@@ -210,7 +210,7 @@ int message_confirm (const char * message, const char * options);
 int getrand (void * buffer, size_t size);
 
 /* ELF binary loading */
-int check_elf_object (struct shim_handle ** file);
+int check_elf_object (struct shim_handle * file);
 int load_elf_object (struct shim_handle * file, void * addr, size_t mapped);
 int load_elf_interp (struct shim_handle * exec);
 int free_elf_interp (void);

+ 15 - 18
LibOS/shim/include/shim_vma.h

@@ -42,13 +42,12 @@ struct shim_handle;
 struct shim_vma {
     REFTYPE                 ref_count;
     void *                  addr;
-    size_t                  length;
+    int                     length;
     int                     prot;
     int                     flags;
     int                     offset;
     struct shim_handle *    file;
     struct list_head        list;
-    size_t                  received;
     char                    comment[VMA_COMMENT_LEN];
 };
 
@@ -61,16 +60,14 @@ struct shim_vma {
                                      so it has to be checkpointed during
                                      migration */
 
-#define NEED_MIGRATE_MEMORY(vma)                            \
-        (((vma)->flags & VMA_TAINTED || !(vma)->file) &&    \
+#define NEED_MIGRATE_MEMORY(vma)                                \
+        (((vma)->flags & VMA_TAINTED || !(vma)->file) &&        \
         !((vma)->flags & VMA_UNMAPPED))
 
-#if 0
-#define NEED_MIGRATE_MEMORY_IF_GIPC(vma)                    \
-        (!((vma)->flags & VMA_UNMAPPED) &&                  \
+#define NEED_MIGRATE_MEMORY_IF_GIPC(vma)                        \
+        (!((vma)->flags & VMA_UNMAPPED) &&                      \
+         !(!(vma)->prot && !((vma)->flags & VMA_TAINTED)) &&    \
          !((vma)->file && ((vma)->flags & MAP_SHARED)))
-#endif
-#define NEED_MIGRATE_MEMORY_IF_GIPC(vma) NEED_MIGRATE_MEMORY((vma))
 
 static inline PAL_FLG PAL_PROT (int prot, int flags)
 {
@@ -92,28 +89,28 @@ static inline PAL_FLG PAL_PROT (int prot, int flags)
 int init_vma (void);
 
 /* Bookkeeping mmap() system call */
-int bkeep_mmap (void * addr, size_t length, int prot, int flags,
-                struct shim_handle * file, int offset,
-                const char * comment);
+int bkeep_mmap (void * addr, int length, int prot, int flags,
+                struct shim_handle * file, int offset, const char * comment);
 
 /* Bookkeeping munmap() system call */
-int bkeep_munmap (void * addr, size_t length, const int * flags);
+int bkeep_munmap (void * addr, int length, const int * flags);
 
 /* Bookkeeping mprotect() system call */
-int bkeep_mprotect (void * addr, size_t length, int prot, const int * flags);
+int bkeep_mprotect (void * addr, int length, int prot, const int * flags);
 
 /* Get vma bookkeeping handle */
 void get_vma (struct shim_vma * vma);
 void put_vma (struct shim_vma * vma);
 
-int lookup_supervma (const void * addr, size_t len, struct shim_vma ** vma);
-int lookup_overlap_vma (const void * addr, size_t len, struct shim_vma ** vma);
+int lookup_supervma (const void * addr, int len, struct shim_vma ** vma);
+int lookup_overlap_vma (const void * addr, int len, struct shim_vma ** vma);
 
 struct shim_vma * next_vma (struct shim_vma * vma);
 
-void * get_unmapped_vma (size_t len, int flags);
+void * get_unmapped_vma (int len, int flags);
+void * get_unmapped_vma_for_cp (int len);
 
-int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size);
+int dump_all_vmas (struct shim_thread * thread, char * buf, int size);
 
 void unmap_all_vmas (void);
 

File diff suppressed because it is too large
+ 0 - 0
LibOS/shim/src/.packed/shim.sha384


BIN
LibOS/shim/src/.packed/shim.tar.gz


+ 9 - 8
LibOS/shim/src/Makefile

@@ -42,7 +42,7 @@ objs	= $(addprefix bookkeep/shim_,handle vma thread signal) \
 	  $(addprefix shim_,init table syscalls checkpoint random malloc \
 	  async parser debug) syscallas start \
 	  $(patsubst %.c,%,$(wildcard sys/*.c))
-graphene_lib = ../../../Pal/lib/graphene-lib.a
+graphene_lib = .lib/graphene-lib.a
 pal_lib = $(abspath ../../../Pal/src/libpal.so)
 headers = ../include/*.h ../../../Pal/lib/*.h ../../../Pal/include/pal/*.h
 
@@ -57,9 +57,6 @@ ifeq ($(PROFILING), 1)
 CFLAGS += -DPROFILE
 endif
 
-$(graphene_lib):
-	make -C ../../../Pal/lib $(debug)
-
 ifeq ($(SYS),x86_64-linux-gnu)
 libsysdb.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	     $(graphene_lib) $(pal_lib)
@@ -74,16 +71,20 @@ libsysdb_debug.so: $(addsuffix .o,$(filter-out syscallas,$(objs))) \
 	$(LD) $(LDFLAGS-debug) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 
+.PHONY: $(graphene_lib)
+$(graphene_lib):
+	$(MAKE) -C ../../../Pal/lib $(debug) target=$(shell pwd)/.lib/
+
 libsysdb.a: $(addsuffix .o,$(objs))
 	@echo [ $@ ]
 	$(AR) $(ARFLAGS) $@ $^
 
 .PHONY: pack
-pack: $(shim_target)
-	tar -czf .packed/shim.tar.gz $^
+pack: $(shim_target) $(addsuffix .o,$(objs))
+	@../../../Scripts/pack_binaries.sh shim $^
 else
 $(shim_target): .packed/shim.tar.gz
-	tar -xmozf $<
+	tar -xmozf $< $@
 endif
 
 %.asm: %.c $(headers)
@@ -113,4 +114,4 @@ elf/shim_rtld.o: $(wildcard elf/*.h)
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 clean:
-	rm -f $(addsuffix .o,$(objs)) $(shim_target)
+	rm -rf $(addsuffix .o,$(objs)) $(shim_target) .lib

+ 85 - 148
LibOS/shim/src/bookkeep/shim_handle.c

@@ -32,8 +32,6 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
-
 static LOCKTYPE handle_mgr_lock;
 
 #define HANDLE_MGR_ALLOC        32
@@ -465,7 +463,7 @@ void close_handle (struct shim_handle * hdl)
                 dir->dotdot = NULL;
             }
 
-            while (*dir->ptr) {
+            while (dir->ptr && *dir->ptr) {
                 struct shim_dentry * dent = *dir->ptr;
                 put_dentry(dent);
                 *(dir->ptr++) = NULL;
@@ -747,154 +745,108 @@ done:
     return ret;
 }
 
-DEFINE_MIGRATE_FUNC(handle)
-
-MIGRATE_FUNC_BODY(handle)
+BEGIN_CP_FUNC(handle)
 {
     assert(size == sizeof(struct shim_handle));
 
     struct shim_handle * hdl = (struct shim_handle *) obj;
     struct shim_handle * new_hdl = NULL;
 
-    lock(hdl->lock);
-
-   struct shim_mount * fs = hdl->fs, * new_fs = NULL;
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-    if (fs && fs->mount_point)
-        __DO_MIGRATE(mount, fs, &new_fs, 0);
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_handle));
+        ADD_TO_CP_MAP(obj, off);
+        new_hdl = (struct shim_handle *) (base + off);
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset,
-                                           sizeof(struct shim_handle));
+        lock(hdl->lock);
+        struct shim_mount * fs = hdl->fs;
+        *new_hdl = *hdl;
 
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_handle));
+        if (fs && fs->fs_ops && fs->fs_ops->checkout)
+            fs->fs_ops->checkout(new_hdl);
 
-        if (!dry) {
-            new_hdl = (struct shim_handle *) (base + off);
-            memcpy(new_hdl, hdl, sizeof(struct shim_handle));
+        new_hdl->dentry = NULL;
+        REF_SET(new_hdl->opened, 0);
+        REF_SET(new_hdl->ref_count, 0);
+        clear_lock(new_hdl->lock);
 
-            if (fs && fs->fs_ops && fs->fs_ops->checkout)
-                fs->fs_ops->checkout(new_hdl);
+        DO_CP_IN_MEMBER(qstr, new_hdl, path);
+        DO_CP_IN_MEMBER(qstr, new_hdl, uri);
 
-            new_hdl->dentry = NULL;
-            new_hdl->fs = new_fs;
-            REF_SET(new_hdl->opened, 0);
-            REF_SET(new_hdl->ref_count, 0);
-            clear_lock(new_hdl->lock);
+        if (fs && hdl->dentry) {
+            DO_CP_MEMBER(mount, hdl, new_hdl, fs);
+        } else {
+            new_hdl->fs = NULL;
         }
 
-        DO_MIGRATE_IN_MEMBER(qstr, hdl, new_hdl, path, false);
-        DO_MIGRATE_IN_MEMBER(qstr, hdl, new_hdl, uri,  false);
+        if (hdl->dentry)
+            DO_CP_MEMBER(dentry, hdl, new_hdl, dentry);
 
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct shim_handle));
-        ADD_ENTRY(PALHDL, new_hdl->pal_handle ?
-                  *offset + offsetof(struct shim_handle, pal_handle) : 0);
+        if (new_hdl->pal_handle) {
+            struct shim_palhdl_entry * entry;
+            DO_CP(palhdl, hdl->pal_handle, &entry);
+            entry->uri = &new_hdl->uri;
+            entry->phandle = &new_hdl->pal_handle;
+        }
 
-    } else if (!dry) {
+        unlock(hdl->lock);
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_hdl = (struct shim_handle *) (base + off);
     }
 
-    if (new_hdl && objp)
+    if (objp)
         *objp = (void *) new_hdl;
 
-    if (new_hdl)
-        assert(new_hdl->uri.len < 1024);
-
-    unlock(hdl->lock);
 }
-END_MIGRATE_FUNC
-
-DEFINE_PROFILE_CATAGORY(inside_resume_handle, resume_func);
-DEFINE_PROFILE_INTERVAL(dentry_lookup_for_handle, inside_resume_handle);
+END_CP_FUNC(handle)
 
-RESUME_FUNC_BODY(handle)
+BEGIN_RS_FUNC(handle)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_handle));
-    GET_ENTRY(PALHDL);
+    struct shim_handle * hdl = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    BEGIN_PROFILE_INTERVAL();
-
-    struct shim_handle * hdl = (struct shim_handle *) (base + off);
-
-    RESUME_REBASE(hdl->fs);
+    CP_REBASE(hdl->fs);
+    CP_REBASE(hdl->dentry);
 
     create_lock(hdl->lock);
 
-    if (!qstrempty(&hdl->path)) {
-        UPDATE_PROFILE_INTERVAL();
-        int ret = path_lookupat(NULL, qstrgetstr(&hdl->path), LOOKUP_OPEN,
-                                &hdl->dentry);
-        if (ret < 0)
-            return -EACCES;
-
-        get_dentry(hdl->dentry);
-        SAVE_PROFILE_INTERVAL(dentry_lookup_for_handle);
-    }
-
     if (!hdl->fs) {
-        if (hdl->dentry) {
-            set_handle_fs(hdl, hdl->dentry->fs);
-        } else {
-            struct shim_mount * fs = NULL;
-            assert(hdl->fs_type);
-            search_builtin_fs(hdl->fs_type, &fs);
-            if (fs)
-                set_handle_fs(hdl, fs);
-        }
+        assert(hdl->fs_type);
+        search_builtin_fs(hdl->fs_type, &hdl->fs);
+        if (!hdl->fs)
+            return -EINVAL;
     }
 
     if (hdl->fs && hdl->fs->fs_ops &&
         hdl->fs->fs_ops->checkin)
         hdl->fs->fs_ops->checkin(hdl);
 
-#ifdef DEBUG_RESUME
-    debug("handle: path=%s,fs_type=%s,uri=%s,flags=%03o\n",
-          qstrgetstr(&hdl->path), hdl->fs_type, qstrgetstr(&hdl->uri),
-          hdl->flags);
-#endif
+    DEBUG_RS("path=%s,type=%s,uri=%s,flags=%03o",
+             qstrgetstr(&hdl->path), hdl->fs_type, qstrgetstr(&hdl->uri),
+             hdl->flags);
 }
-END_RESUME_FUNC
+END_RS_FUNC(handle)
 
-DEFINE_MIGRATE_FUNC(fd_handle)
-
-MIGRATE_FUNC_BODY(fd_handle)
+BEGIN_CP_FUNC(fd_handle)
 {
     assert(size == sizeof(struct shim_fd_handle));
 
     struct shim_fd_handle * fdhdl = (struct shim_fd_handle *) obj;
     struct shim_fd_handle * new_fdhdl = NULL;
 
-    ADD_OFFSET(sizeof(struct shim_fd_handle));
-    ADD_FUNC_ENTRY(*offset);
-    ADD_ENTRY(SIZE, sizeof(struct shim_fd_handle));
-
-    if (!dry) {
-        new_fdhdl = (struct shim_fd_handle *) (base + *offset);
-        memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
-    }
+    ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_fd_handle));
+    new_fdhdl = (struct shim_fd_handle *) (base + off);
+    memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
+    DO_CP(handle, fdhdl->handle, &new_fdhdl->handle);
+    ADD_CP_FUNC_ENTRY(off);
 
-    if (new_fdhdl && objp)
+    if (objp)
         *objp = (void *) new_fdhdl;
-
-    struct shim_handle ** phdl = dry ? NULL : &(new_fdhdl->handle);
-    struct shim_handle * hdl = fdhdl->handle;
-
-    DO_MIGRATE_IF_RECURSIVE(handle, hdl, phdl, recursive);
 }
-END_MIGRATE_FUNC
-
-RESUME_FUNC_BODY(fd_handle)
-{
-    GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_fd_handle));
-}
-END_RESUME_FUNC
-
-DEFINE_MIGRATE_FUNC(handle_map)
+END_CP_FUNC_NO_RS(fd_handle)
 
-MIGRATE_FUNC_BODY(handle_map)
+BEGIN_CP_FUNC(handle_map)
 {
     assert(size >= sizeof(struct shim_handle_map));
 
@@ -910,82 +862,67 @@ MIGRATE_FUNC_BODY(handle_map)
     size = sizeof(struct shim_handle_map) +
            (sizeof(struct shim_fd_handle *) * fd_size);
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset, size);
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-    if (ENTRY_JUST_CREATED(off)) {
-        ADD_OFFSET(size);
-        ADD_FUNC_ENTRY(*offset);
-        ADD_ENTRY(SIZE, size);
-
-        if (!dry) {
-            new_handle_map = (struct shim_handle_map *) (base + *offset);
+    if (!off) {
+        off = ADD_CP_OFFSET(size);
+        new_handle_map = (struct shim_handle_map *) (base + off);
 
-            memcpy(new_handle_map, handle_map,
-                   sizeof(struct shim_handle_map));
+        memcpy(new_handle_map, handle_map,
+               sizeof(struct shim_handle_map));
 
-            ptr_array = (void *) new_handle_map +
-                                 sizeof(struct shim_handle_map);
+        ptr_array = (void *) new_handle_map + sizeof(struct shim_handle_map);
 
-            new_handle_map->fd_size = fd_size;
-            new_handle_map->map = fd_size ? ptr_array : NULL;
+        new_handle_map->fd_size = fd_size;
+        new_handle_map->map = fd_size ? ptr_array : NULL;
 
-            REF_SET(new_handle_map->ref_count, 0);
-            clear_lock(new_handle_map->lock);
-        }
+        REF_SET(new_handle_map->ref_count, 0);
+        clear_lock(new_handle_map->lock);
 
         for (int i = 0 ; i < fd_size ; i++) {
-            if (HANDLE_ALLOCATED(handle_map->map[i])) {
-                struct shim_fd_handle ** new_hdl = dry ? NULL :
-                    &(ptr_array[i]);
-                __DO_MIGRATE(fd_handle, handle_map->map[i],
-                             new_hdl, 1);
-            } else if (!dry)
+            if (HANDLE_ALLOCATED(handle_map->map[i]))
+                DO_CP(fd_handle, handle_map->map[i], &ptr_array[i]);
+            else
                 ptr_array[i] = NULL;
         }
-    } else if (!dry)
+
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_handle_map = (struct shim_handle_map *) (base + off);
+    }
 
     unlock(handle_map->lock);
 
-    if (new_handle_map && objp)
+    if (objp)
         *objp = (void *) new_handle_map;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(handle_map)
 
-RESUME_FUNC_BODY(handle_map)
+BEGIN_RS_FUNC(handle_map)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) >= sizeof(struct shim_handle_map));
-    struct shim_handle_map * handle_map =
-                    (struct shim_handle_map *) (base + off);
+    struct shim_handle_map * handle_map = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    RESUME_REBASE(handle_map->map);
+    CP_REBASE(handle_map->map);
     assert(handle_map->map);
 
-#ifdef DEBUG_RESUME
-    debug("handle_map: size=%d,top=%d\n", handle_map->fd_size,
-          handle_map->fd_top);
-#endif
+    DEBUG_RS("size=%d,top=%d", handle_map->fd_size, handle_map->fd_top);
 
     create_lock(handle_map->lock);
     lock(handle_map->lock);
 
     if (handle_map->fd_top != FD_NULL)
         for (int i = 0 ; i <= handle_map->fd_top ; i++) {
-            RESUME_REBASE(handle_map->map[i]);
+            CP_REBASE(handle_map->map[i]);
             if (HANDLE_ALLOCATED(handle_map->map[i])) {
-                RESUME_REBASE(handle_map->map[i]->handle);
+                CP_REBASE(handle_map->map[i]->handle);
                 struct shim_handle * hdl = handle_map->map[i]->handle;
                 assert(hdl);
                 open_handle(hdl);
-#ifdef DEBUG_RESUME
-                debug("handle_map[%d]: %s\n", i,
-                      !qstrempty(&hdl->uri) ? qstrgetstr(&hdl->uri) :
-                      hdl->fs_type);
-#endif
+                DEBUG_RS("[%d]%s", i, qstrempty(&hdl->uri) ? hdl->fs_type :
+                                      qstrgetstr(&hdl->uri));
             }
         }
 
     unlock(handle_map->lock);
 }
-END_RESUME_FUNC
+END_RS_FUNC(handle_map)

+ 28 - 54
LibOS/shim/src/bookkeep/shim_signal.c

@@ -31,12 +31,16 @@
 #include <shim_vma.h>
 #include <shim_checkpoint.h>
 #include <shim_signal.h>
+#include <shim_unistd.h>
 
 #include <pal.h>
 
 static struct shim_signal **
 allocate_signal_log (struct shim_thread * thread, int sig)
 {
+    if (!thread->signal_logs)
+        return NULL;
+
     struct shim_signal_log * log = &thread->signal_logs[sig - 1];
     int head, tail, old_tail;
 
@@ -135,6 +139,10 @@ void __store_context (shim_tcb_t * tcb, PAL_CONTEXT * pal_context,
 void deliver_signal (siginfo_t * info, PAL_CONTEXT * context)
 {
     shim_tcb_t * tcb = SHIM_GET_TLS();
+
+    if (!tcb || !tcb->tp)
+        return;
+
     struct shim_thread * cur_thread = (struct shim_thread *) tcb->tp;
     int sig = info->si_signo;
 
@@ -310,40 +318,6 @@ static void suspend_upcall (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
     if (IS_INTERNAL_TID(get_cur_tid()))
         goto ret_exception;
 
-    if (ask_for_checkpoint) {
-        int ans =  message_confirm("checkpoint execution "
-                                   "(\'k\' to kill the process)",
-                                   "yk");
-
-        if (ans == 'K' || ans == 'k')
-            goto kill;
-
-        if (ans != 'Y' && ans != 'y')
-            goto ret_exception;
-
-        shim_tcb_t * tcb = SHIM_GET_TLS();
-        assert(tcb && tcb->tp);
-        struct shim_signal signal;
-        __store_context(tcb, context, &signal);
-
-        IDTYPE session = 0;
-        char cpdir[20];
-
-        if (create_dir("checkpoint-", cpdir, 20, NULL) < 0)
-            goto ret_exception;
-
-        sys_printf("creating checkpoint \"%s\"...\n", cpdir);
-
-        if (create_checkpoint(cpdir, &session) < 0)
-            goto ret_exception;
-
-        ipc_checkpoint_send(cpdir, session);
-        kill_all_threads(tcb->tp, CHECKPOINT_REQUESTED, SIGINT);
-        join_checkpoint(tcb->tp, &signal.context);
-        goto ret_exception;
-    }
-
-kill:
     deliver_signal(ALLOC_SIGINFO(SIGINT, si_pid, 0), NULL);
 
 ret_exception:
@@ -356,7 +330,9 @@ static void resume_upcall (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
         goto ret_exception;
 
     shim_tcb_t * tcb = SHIM_GET_TLS();
-    assert(tcb && tcb->tp);
+
+    if (!tcb || !tcb->tp)
+        return;
 
     __disable_preempt(tcb);
 
@@ -384,7 +360,7 @@ int init_signal (void)
     return 0;
 }
 
-sigset_t * get_sig_mask (struct shim_thread * thread)
+__sigset_t * get_sig_mask (struct shim_thread * thread)
 {
     if (!thread)
         thread = get_cur_thread();
@@ -394,7 +370,7 @@ sigset_t * get_sig_mask (struct shim_thread * thread)
     return &(thread->signal_mask);
 }
 
-sigset_t * set_sig_mask (struct shim_thread * thread, sigset_t * set)
+__sigset_t * set_sig_mask (struct shim_thread * thread, __sigset_t * set)
 {
     if (!thread)
         thread = get_cur_thread();
@@ -402,7 +378,7 @@ sigset_t * set_sig_mask (struct shim_thread * thread, sigset_t * set)
     assert(thread);
 
     if (set)
-        memcpy(&thread->signal_mask, set, sizeof(sigset_t));
+        memcpy(&thread->signal_mask, set, sizeof(__sigset_t));
 
     return &thread->signal_mask;
 }
@@ -415,18 +391,13 @@ __handle_one_signal (shim_tcb_t * tcb, int sig, struct shim_signal * signal)
     struct shim_thread * thread = (struct shim_thread *) tcb->tp;
     struct shim_signal_handle * sighdl = &thread->signal_handles[sig - 1];
     void (*handler) (int, siginfo_t *, void *) = NULL;
-    //void (*restorer) (void) = NULL;
 
-    if (signal->info.si_signo == SIGINT &&
-        signal->info.si_pid == CHECKPOINT_REQUESTED) {
-        join_checkpoint(thread, &signal->context);
+    if (signal->info.si_signo == SIGCP) {
+        join_checkpoint(thread, &signal->context, si_cp_session(&signal->info));
         return;
     }
 
-    if (sig <= NUM_KNOWN_SIGS)
-        debug("handle %s\n", siglist[sig]);
-    else
-        debug("handle signal %d\n", sig);
+    debug("%s handled\n", signal_name(sig));
 
     lock(thread->lock);
 
@@ -518,8 +489,11 @@ void __handle_signal (shim_tcb_t * tcb, int sig, ucontext_t * uc)
 void handle_signal (bool delayed_only)
 {
     shim_tcb_t * tcb = SHIM_GET_TLS();
+
+    if (!tcb || !tcb->tp)
+        return;
+
     struct shim_thread * thread = (struct shim_thread *) tcb->tp;
-    assert(tcb && tcb->tp);
 
     /* Fast path */
     if (!thread->has_signal.counter)
@@ -540,7 +514,8 @@ out:
     __enable_preempt(tcb);
 }
 
-void append_signal (struct shim_thread * thread, int sig, siginfo_t * info)
+void append_signal (struct shim_thread * thread, int sig, siginfo_t * info,
+                    bool wakeup)
 {
     struct shim_signal * signal = malloc(sizeof(struct shim_signal));
     if (!signal)
@@ -558,8 +533,10 @@ void append_signal (struct shim_thread * thread, int sig, siginfo_t * info)
 
     if (signal_log) {
         *signal_log = signal;
-        debug("resuming thread %u\n", thread->tid);
-        DkThreadResume(thread->pal_handle);
+        if (wakeup) {
+            debug("resuming thread %u\n", thread->tid);
+            DkThreadResume(thread->pal_handle);
+        }
     } else {
         sys_printf("signal queue is full (TID = %u, SIG = %d)\n",
                    thread->tid, sig);
@@ -569,10 +546,7 @@ void append_signal (struct shim_thread * thread, int sig, siginfo_t * info)
 
 static void sighandler_kill (int sig, siginfo_t * info, void * ucontext)
 {
-    if (sig <= NUM_KNOWN_SIGS)
-        debug("killed by %s\n", siglist[sig]);
-    else
-        debug("killed by signal %d\n", sig);
+    debug("killed by %s\n", signal_name(sig));
 
     if (!info->si_pid)
         switch(sig) {

+ 87 - 199
LibOS/shim/src/bookkeep/shim_thread.c

@@ -31,22 +31,8 @@
 #include <shim_checkpoint.h>
 
 #include <pal.h>
-
 #include <linux_list.h>
 
-#define THREAD_MGR_ALLOC    4
-
-static LOCKTYPE thread_mgr_lock;
-
-#define system_lock()   lock(thread_mgr_lock)
-#define system_unlock() unlock(thread_mgr_lock)
-#define PAGE_SIZE       allocsize
-
-#define OBJ_TYPE struct shim_thread
-#include <memmgr.h>
-
-static MEM_MGR thread_mgr = NULL;
-
 static IDTYPE tid_alloc_idx __attribute_migratable = 0;
 
 static LIST_HEAD(thread_list);
@@ -62,14 +48,8 @@ PAL_HANDLE thread_start_event = NULL;
 int init_thread (void)
 {
     create_lock(thread_list_lock);
-    create_lock(thread_mgr_lock);
-
-    thread_mgr = create_mem_mgr(init_align_up(THREAD_MGR_ALLOC));
-    if (!thread_mgr)
-        return -ENOMEM;
 
     struct shim_thread * cur_thread = get_cur_thread();
-
     if (cur_thread)
         return 0;
 
@@ -77,7 +57,6 @@ int init_thread (void)
         return -ENOMEM;
 
     cur_thread->in_vm = cur_thread->is_alive = true;
-    get_thread(cur_thread);
     set_cur_thread(cur_thread);
     add_thread(cur_thread);
     cur_thread->pal_handle = PAL_CB(first_thread);
@@ -115,7 +94,7 @@ shim_tcb_t * __get_cur_tcb (void)
     return SHIM_GET_TLS();
 }
 
-static IDTYPE get_pid (void)
+IDTYPE get_pid (void)
 {
     IDTYPE idx;
 
@@ -157,38 +136,9 @@ static IDTYPE get_internal_pid (void)
     return idx;
 }
 
-static inline int init_mem_mgr (void)
-{
-    if (thread_mgr)
-        return 0;
-
-    MEM_MGR mgr = create_mem_mgr(init_align_up(THREAD_MGR_ALLOC));
-    MEM_MGR old_mgr = NULL;
-
-    lock(thread_mgr_lock);
-
-    if (mgr) {
-        if (thread_mgr) {
-            old_mgr = mgr;
-            mgr = thread_mgr;
-        } else {
-            thread_mgr = mgr;
-        }
-    }
-
-    unlock(thread_mgr_lock);
-
-    if (old_mgr)
-        destroy_mem_mgr(old_mgr);
-
-    return mgr ? 0 : -ENOMEM;
-}
-
 struct shim_thread * alloc_new_thread (void)
 {
-    struct shim_thread * thread =
-            get_mem_obj_from_mgr_enlarge(thread_mgr,
-                                         size_align_up(THREAD_MGR_ALLOC));
+    struct shim_thread * thread = malloc(sizeof(struct shim_thread));
     if (!thread)
         return NULL;
 
@@ -203,9 +153,6 @@ struct shim_thread * alloc_new_thread (void)
 
 struct shim_thread * get_new_thread (IDTYPE new_tid)
 {
-    if (init_mem_mgr() < 0)
-        return NULL;
-
     if (!new_tid) {
         new_tid = get_pid();
         assert(new_tid);
@@ -270,6 +217,8 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
         }
     }
 
+    thread->signal_logs = malloc(sizeof(struct shim_signal_log) *
+                                 NUM_SIGS);
     thread->vmid = cur_process.vmid;
     create_lock(thread->lock);
     thread->scheduler_event = DkNotificationEventCreate(1);
@@ -280,9 +229,6 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
 
 struct shim_thread * get_new_internal_thread (void)
 {
-    if (init_mem_mgr() < 0)
-        return NULL;
-
     IDTYPE new_tid = get_internal_pid();
     assert(new_tid);
 
@@ -368,7 +314,7 @@ void put_thread (struct shim_thread * thread)
         if (MEMORY_MIGRATED(thread))
             memset(thread, 0, sizeof(struct shim_thread));
         else
-            free_mem_obj_to_mgr(thread_mgr, thread);
+            free(thread);
     }
 }
 
@@ -608,118 +554,73 @@ void switch_dummy_thread (struct shim_thread * thread)
                  : "memory");
 }
 
-DEFINE_MIGRATE_FUNC(thread)
-
-MIGRATE_FUNC_BODY(thread)
+BEGIN_CP_FUNC(thread)
 {
     assert(size == sizeof(struct shim_thread));
 
     struct shim_thread * thread = (struct shim_thread *) obj;
     struct shim_thread * new_thread = NULL;
 
-    if (recursive) {
-        struct shim_vma * vma = NULL;
-        lookup_supervma(thread->stack, thread->stack_top - thread->stack,
-                        &vma);
-        assert(vma);
-        DO_MIGRATE(vma, vma, NULL, true);
-    }
-
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset, size);
-
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_thread));
-
-        if (!dry) {
-            new_thread = (struct shim_thread *) (base + off);
-            memcpy(new_thread, thread, sizeof(struct shim_thread));
-
-            INIT_LIST_HEAD(&new_thread->children);
-            INIT_LIST_HEAD(&new_thread->siblings);
-            INIT_LIST_HEAD(&new_thread->exited_children);
-            INIT_LIST_HEAD(&new_thread->list);
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-            new_thread->in_vm  = false;
-            new_thread->parent = NULL;
-            new_thread->dummy  = NULL;
-            new_thread->handle_map = NULL;
-            new_thread->root   = NULL;
-            new_thread->cwd    = NULL;
-            new_thread->robust_list = NULL;
-
-            if (!recursive)
-                new_thread->tcb = NULL;
-
-            REF_SET(new_thread->ref_count, 0);
-        }
-
-        for (int i = 0 ; i < NUM_SIGS ; i++) {
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_thread));
+        ADD_TO_CP_MAP(obj, off);
+        new_thread = (struct shim_thread *) (base + off);
+        memcpy(new_thread, thread, sizeof(struct shim_thread));
+
+        INIT_LIST_HEAD(&new_thread->children);
+        INIT_LIST_HEAD(&new_thread->siblings);
+        INIT_LIST_HEAD(&new_thread->exited_children);
+        INIT_LIST_HEAD(&new_thread->list);
+
+        new_thread->in_vm  = false;
+        new_thread->parent = NULL;
+        new_thread->dummy  = NULL;
+        new_thread->handle_map = NULL;
+        new_thread->root   = NULL;
+        new_thread->cwd    = NULL;
+        new_thread->signal_logs = NULL;
+        new_thread->robust_list = NULL;
+        REF_SET(new_thread->ref_count, 0);
+
+        for (int i = 0 ; i < NUM_SIGS ; i++)
             if (thread->signal_handles[i].action) {
-                ADD_OFFSET(sizeof(struct __kernel_sigaction));
-
-                if (!dry) {
-                    new_thread->signal_handles[i].action
-                            = (struct __kernel_sigaction *) (base + *offset);
-
-                    memcpy(new_thread->signal_handles[i].action,
-                           thread->signal_handles[i].action,
-                           sizeof(struct __kernel_sigaction));
-                }
+                ptr_t soff = ADD_CP_OFFSET(sizeof(struct __kernel_sigaction));
+                new_thread->signal_handles[i].action
+                        = (struct __kernel_sigaction *) (base + soff);
+                memcpy(new_thread->signal_handles[i].action,
+                       thread->signal_handles[i].action,
+                       sizeof(struct __kernel_sigaction));
             }
-        }
-
-        DO_MIGRATE_MEMBER(handle, thread, new_thread, exec, 0);
-        DO_MIGRATE_MEMBER_IF_RECURSIVE(handle_map, thread, new_thread,
-                                       handle_map, 1);
-
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct shim_thread));
-
-        int rlen, clen;
-        const char * rpath = dentry_get_path(thread->root, true, &rlen);
-        const char * cpath = dentry_get_path(thread->cwd, true, &clen);
-        char * new_rpath, * new_cpath;
 
-        ADD_OFFSET(rlen + 1);
-        ADD_ENTRY(ADDR, (new_rpath = (void *) (base + *offset)));
-        ADD_OFFSET(clen + 1);
-        ADD_ENTRY(ADDR, (new_cpath = (void *) (base + *offset)));
-
-        if (!dry) {
-            memcpy(new_rpath, rpath, rlen + 1);
-            memcpy(new_cpath, cpath, clen + 1);
-        }
-
-    } else if (!dry) {
+        DO_CP_MEMBER(handle, thread, new_thread, exec);
+        DO_CP_MEMBER(handle_map, thread, new_thread, handle_map);
+        DO_CP_MEMBER(dentry, thread, new_thread, root);
+        DO_CP_MEMBER(dentry, thread, new_thread, cwd);
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_thread = (struct shim_thread *) (base + off);
     }
 
-    if (new_thread && objp)
+    if (objp)
         *objp = (void *) new_thread;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(thread)
 
-RESUME_FUNC_BODY(thread)
+BEGIN_RS_FUNC(thread)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    size_t size = GET_ENTRY(SIZE);
-    assert(size == sizeof(struct shim_thread));
-    struct shim_thread * thread = (struct shim_thread *) (base + off);
-
-    RESUME_REBASE(thread->children);
-    RESUME_REBASE(thread->siblings);
-    RESUME_REBASE(thread->exited_children);
-    RESUME_REBASE(thread->list);
-    RESUME_REBASE(thread->exec);
-    RESUME_REBASE(thread->handle_map);
-    RESUME_REBASE(thread->signal_handles);
-
-    const char * rpath = (const char *) GET_ENTRY(ADDR);
-    const char * cpath = (const char *) GET_ENTRY(ADDR);
-    RESUME_REBASE(rpath);
-    RESUME_REBASE(cpath);
-    path_lookupat(NULL, rpath, LOOKUP_OPEN, &thread->root);
-    path_lookupat(NULL, cpath, LOOKUP_OPEN, &thread->cwd);
+    struct shim_thread * thread = (void *) (base + GET_CP_FUNC_ENTRY());
+
+    CP_REBASE(thread->children);
+    CP_REBASE(thread->siblings);
+    CP_REBASE(thread->exited_children);
+    CP_REBASE(thread->list);
+    CP_REBASE(thread->exec);
+    CP_REBASE(thread->handle_map);
+    CP_REBASE(thread->root);
+    CP_REBASE(thread->cwd);
+    CP_REBASE(thread->signal_handles);
 
     create_lock(thread->lock);
     thread->scheduler_event = DkNotificationEventCreate(1);
@@ -734,39 +635,36 @@ RESUME_FUNC_BODY(thread)
     if (thread->handle_map)
         get_handle_map(thread->handle_map);
 
-#ifdef DEBUG_RESUME
-    debug("thread: "
-          "tid=%d,tgid=%d,parent=%d,stack=%p,frameptr=%p,tcb=%p\n",
-          thread->tid, thread->tgid,
-          thread->parent ? thread->parent->tid : thread->tid,
-          thread->stack, thread->frameptr, thread->tcb);
-#endif
-}
-END_RESUME_FUNC
+    if (thread->root)
+        get_dentry(thread->root);
 
-DEFINE_MIGRATE_FUNC(running_thread)
+    if (thread->cwd)
+        get_dentry(thread->cwd);
 
-MIGRATE_FUNC_BODY(running_thread)
+    DEBUG_RS("tid=%d,tgid=%d,parent=%d,stack=%p,frameptr=%p,tcb=%p",
+             thread->tid, thread->tgid,
+             thread->parent ? thread->parent->tid : thread->tid,
+             thread->stack, thread->frameptr, thread->tcb);
+}
+END_RS_FUNC(thread)
+
+BEGIN_CP_FUNC(running_thread)
 {
     assert(size == sizeof(struct shim_thread));
 
     struct shim_thread * thread = (struct shim_thread *) obj;
     struct shim_thread * new_thread = NULL;
-    struct shim_thread ** thread_obj = &new_thread;
 
-    DO_MIGRATE(thread, thread, thread_obj, recursive);
-    ADD_FUNC_ENTRY(new_thread);
+    DO_CP(thread, thread, &new_thread);
+    ADD_CP_FUNC_ENTRY((ptr_t) new_thread - base);
 
     if (!thread->user_tcb && thread->tcb) {
-        ADD_OFFSET(sizeof(__libc_tcb_t));
-        if (!dry) {
-            __libc_tcb_t * new_tcb = (void *) (base + *offset);
-            new_thread->tcb = new_tcb;
-            memcpy(new_tcb, thread->tcb, sizeof(__libc_tcb_t));
-        }
+        ptr_t toff = ADD_CP_OFFSET(sizeof(__libc_tcb_t));
+        new_thread->tcb = (void *) (base + toff);
+        memcpy(new_thread->tcb, thread->tcb, sizeof(__libc_tcb_t));
     }
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(running_thread)
 
 int resume_wrapper (void * param)
 {
@@ -779,7 +677,7 @@ int resume_wrapper (void * param)
     assert(tcb->context.sp);
 
     thread->in_vm = thread->is_alive = true;
-    allocate_tls(libc_tcb, thread);
+    allocate_tls(libc_tcb, thread->user_tcb, thread);
     debug_setbuf(tcb, true);
     debug("set tcb to %p\n", libc_tcb);
 
@@ -789,16 +687,17 @@ int resume_wrapper (void * param)
     return 0;
 }
 
-RESUME_FUNC_BODY(running_thread)
+BEGIN_RS_FUNC(running_thread)
 {
-    struct shim_thread * thread = (void *) GET_FUNC_ENTRY();
-    RESUME_REBASE(thread);
+    struct shim_thread * thread = (void *) (base + GET_CP_FUNC_ENTRY());
     struct shim_thread * cur_thread = get_cur_thread();
     thread->in_vm = true;
-    get_thread(thread);
 
     if (!thread->user_tcb)
-        RESUME_REBASE(thread->tcb);
+        CP_REBASE(thread->tcb);
+
+    thread->signal_logs = malloc(sizeof(struct shim_signal_log) *
+                                 NUM_SIGS);
 
     if (cur_thread) {
         PAL_HANDLE handle = DkThreadCreate(resume_wrapper, thread, 0);
@@ -813,7 +712,7 @@ RESUME_FUNC_BODY(running_thread)
             shim_tcb_t * tcb = &libc_tcb->shim_tcb;
             assert(tcb->context.sp);
             tcb->debug_buf = SHIM_GET_TLS()->debug_buf;
-            allocate_tls(libc_tcb, thread);
+            allocate_tls(libc_tcb, thread->user_tcb, thread);
             debug_setprefix(tcb);
             debug("after resume, set tcb to %p\n", libc_tcb);
         } else {
@@ -824,34 +723,23 @@ RESUME_FUNC_BODY(running_thread)
         thread->pal_handle = PAL_CB(first_thread);
     }
 
-#ifdef DEBUG_RESUME
-    debug("thread %d is attached to the current process\n", thread->tid);
-#endif
+    DEBUG_RS("tid=%d", thread->tid);
 }
-END_RESUME_FUNC
+END_RS_FUNC(running_thread)
 
-DEFINE_MIGRATE_FUNC(all_running_threads)
-
-MIGRATE_FUNC_BODY(all_running_threads)
+BEGIN_CP_FUNC(all_running_threads)
 {
     struct shim_thread * thread;
-
     lock(thread_list_lock);
 
     list_for_each_entry(thread, &thread_list, list) {
         if (!thread->in_vm || !thread->is_alive)
             continue;
 
-        DO_MIGRATE(running_thread, thread, NULL, recursive);
-        DO_MIGRATE(handle_map, thread->handle_map, NULL, recursive);
+        DO_CP(running_thread, thread, NULL);
+        DO_CP(handle_map, thread->handle_map, NULL);
     }
 
     unlock(thread_list_lock);
 }
-END_MIGRATE_FUNC
-
-RESUME_FUNC_BODY(all_running_threads)
-{
-    /* useless */
-}
-END_RESUME_FUNC
+END_CP_FUNC_NO_RS(all_running_threads)

+ 261 - 200
LibOS/shim/src/bookkeep/shim_vma.c

@@ -58,35 +58,35 @@ static LIST_HEAD(vma_list);
 static LOCKTYPE vma_list_lock;
 
 static inline int test_vma_equal (struct shim_vma * tmp,
-                                  const void * addr, size_t length)
+                                  const void * addr, int length)
 {
     return tmp->addr == addr &&
            tmp->addr + tmp->length == addr + length;
 }
 
 static inline int test_vma_contain (struct shim_vma * tmp,
-                                    const void * addr, size_t length)
+                                    const void * addr, int length)
 {
     return tmp->addr <= addr &&
            tmp->addr + tmp->length >= addr + length;
 }
 
 static inline int test_vma_startin (struct shim_vma * tmp,
-                                    const void * addr, size_t length)
+                                    const void * addr, int length)
 {
     return tmp->addr >= addr &&
            tmp->addr < addr + length;
 }
 
 static inline int test_vma_endin (struct shim_vma * tmp,
-                                  const void * addr, size_t length)
+                                  const void * addr, int length)
 {
     return tmp->addr + tmp->length > addr &&
            tmp->addr + tmp->length <= addr + length;
 }
 
 static inline int test_vma_overlap (struct shim_vma * tmp,
-                                    const void * addr, size_t length)
+                                    const void * addr, int length)
 {
     return test_vma_contain (tmp, addr + 1, 0) ||
            test_vma_contain (tmp, addr + length - 1, 0) ||
@@ -129,10 +129,10 @@ static inline void assert_vma (void)
     }
 }
 
-static struct shim_vma * __lookup_vma (const void * addr, size_t len);
-static struct shim_vma * __lookup_supervma (const void * addr, size_t length,
+static struct shim_vma * __lookup_vma (const void * addr, int len);
+static struct shim_vma * __lookup_supervma (const void * addr, int length,
                                             struct shim_vma ** prev);
-static struct shim_vma * __lookup_overlap_vma (const void * addr, size_t length,
+static struct shim_vma * __lookup_overlap_vma (const void * addr, int length,
                                                struct shim_vma ** prev);
 
 void get_vma (struct shim_vma * vma)
@@ -173,12 +173,11 @@ static void __remove_vma (struct shim_vma * vma)
     put_vma(vma);
 }
 
-static int __bkeep_mmap (void * addr, size_t length,
-                         int prot, int flags,
+static int __bkeep_mmap (void * addr, int length, int prot, int flags,
                          struct shim_handle * file, int offset,
                          const char * comment);
 
-static int __bkeep_mprotect (void * addr, size_t length, int prot,
+static int __bkeep_mprotect (void * addr, int length, int prot,
                              const int * flags);
 
 static struct shim_vma * get_new_vma (void)
@@ -222,7 +221,7 @@ static inline void __set_comment (struct shim_vma * vma, const char * comment)
     memcpy(vma->comment, comment, len + 1);
 }
 
-static int __bkeep_mmap (void * addr, size_t length,
+static int __bkeep_mmap (void * addr, int length,
                          int prot, int flags,
                          struct shim_handle * file, int offset,
                          const char * comment)
@@ -326,9 +325,8 @@ err:
     return ret;
 }
 
-int bkeep_mmap (void * addr, size_t length, int prot, int flags,
-                struct shim_handle * file, int offset,
-                const char * comment)
+int bkeep_mmap (void * addr, int length, int prot, int flags,
+                struct shim_handle * file, int offset, const char * comment)
 {
     if (!addr || !length)
         return -EINVAL;
@@ -347,7 +345,7 @@ int bkeep_mmap (void * addr, size_t length, int prot, int flags,
  * We need to split the area aur reduce the size
  * Check the address falls between alread allocated area or not
  */
-static int __bkeep_munmap (void * addr, size_t length, const int * flags)
+static int __bkeep_munmap (void * addr, int length, const int * flags)
 {
     struct shim_vma * tmp, * n;
 
@@ -417,7 +415,7 @@ static int __bkeep_munmap (void * addr, size_t length, const int * flags)
     return 0;
 }
 
-int bkeep_munmap (void * addr, size_t length, const int * flags)
+int bkeep_munmap (void * addr, int length, const int * flags)
 {
     if (!addr || !length)
         return -EINVAL;
@@ -430,7 +428,7 @@ int bkeep_munmap (void * addr, size_t length, const int * flags)
     return ret;
 }
 
-static int __bkeep_mprotect (void * addr, size_t length, int prot,
+static int __bkeep_mprotect (void * addr, int length, int prot,
                              const int * flags)
 {
     struct shim_vma * tmp = __lookup_vma(addr, length);
@@ -592,7 +590,7 @@ static int __bkeep_mprotect (void * addr, size_t length, int prot,
     return 0;
 }
 
-int bkeep_mprotect (void * addr, size_t length, int prot, const int * flags)
+int bkeep_mprotect (void * addr, int length, int prot, const int * flags)
 {
     if (!addr || !length)
         return -EINVAL;
@@ -622,7 +620,7 @@ static void __set_heap_top (void * bottom, void * top)
     debug("heap top adjusted to %p\n", heap_top);
 }
 
-void * get_unmapped_vma (size_t length, int flags)
+void * get_unmapped_vma (int length, int flags)
 {
     struct shim_vma * new = get_new_vma(), * tmp = NULL;
     if (!new)
@@ -664,9 +662,49 @@ void * get_unmapped_vma (size_t length, int flags)
     return new->addr;
 }
 
+#define NTRIES  4
+
+void * get_unmapped_vma_for_cp (int length)
+{
+    struct shim_vma * new = get_new_vma(), * prev = NULL;
+    if (!new)
+        return NULL;
+
+    lock(vma_list_lock);
+
+    unsigned long top = (unsigned long) PAL_CB(user_address.end) - length;
+    unsigned long bottom = (unsigned long) heap_top;
+    void * addr;
+
+    if (bottom >= top)
+        return NULL;
+
+    for (int i = 0 ; i < NTRIES ; i++) {
+        unsigned long rand;
+        while (getrand(&rand, sizeof(unsigned long)) < sizeof(unsigned long));
+        rand %= (unsigned long) (top - bottom) / allocsize;
+        addr = (void *) bottom + rand * allocsize;
+        if (!__lookup_overlap_vma(addr, length, &prev))
+            break;
+        addr = NULL;
+    }
+
+    if (!addr)
+        return NULL;
+
+    new->addr   = addr;
+    new->length = length;
+    new->flags  = MAP_ANONYMOUS|VMA_UNMAPPED|VMA_INTERNAL;
+    new->prot   = PROT_READ|PROT_WRITE;
+
+    list_add(&new->list, prev ? &prev->list : &vma_list);
+    unlock(vma_list_lock);
+    return addr;
+}
+
 /* This might not give the same vma but we might need to
    split after we find something */
-static struct shim_vma * __lookup_overlap_vma (const void * addr, size_t length,
+static struct shim_vma * __lookup_overlap_vma (const void * addr, int length,
                                                struct shim_vma ** pprev)
 {
     struct shim_vma * tmp, * prev = NULL;
@@ -691,7 +729,7 @@ static struct shim_vma * __lookup_overlap_vma (const void * addr, size_t length,
     return NULL;
 }
 
-int lookup_overlap_vma (const void * addr, size_t length,
+int lookup_overlap_vma (const void * addr, int length,
                         struct shim_vma ** vma)
 {
     struct shim_vma * tmp = NULL;
@@ -707,7 +745,7 @@ int lookup_overlap_vma (const void * addr, size_t length,
     return tmp ? 0: -ENOENT;
 }
 
-static struct shim_vma * __lookup_vma (const void * addr, size_t length)
+static struct shim_vma * __lookup_vma (const void * addr, int length)
 {
     struct shim_vma * tmp;
     struct shim_vma * prev __attribute__((unused)) = NULL;
@@ -724,7 +762,7 @@ static struct shim_vma * __lookup_vma (const void * addr, size_t length)
     return NULL;
 }
 
-static struct shim_vma * __lookup_supervma (const void * addr, size_t length,
+static struct shim_vma * __lookup_supervma (const void * addr, int length,
                                             struct shim_vma ** pprev)
 {
     struct shim_vma * tmp, * prev = NULL;
@@ -749,7 +787,7 @@ static struct shim_vma * __lookup_supervma (const void * addr, size_t length,
     return NULL;
 }
 
-int lookup_supervma (const void * addr, size_t length, struct shim_vma ** vma)
+int lookup_supervma (const void * addr, int length, struct shim_vma ** vma)
 {
     struct shim_vma * tmp = NULL;
 
@@ -802,12 +840,45 @@ struct shim_vma * next_vma (struct shim_vma * vma)
     return tmp;
 }
 
-int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size)
+/* to speed up the checkpointing, go organize the VMAs */
+void __shrink_vmas (void)
 {
-    lock(vma_list_lock);
+    struct shim_vma * vma, * n, * last;
+
+    list_for_each_entry_safe(vma, n, &vma_list, list) {
+        if (!last)
+            goto unmap;
+
+        if (last->addr + last->length != vma->addr ||
+            last->prot != vma->prot ||
+            last->flags != vma->flags ||
+            last->file != vma->file)
+            goto unmap;
+
+        if (last->file && last->offset + last->length != vma->offset)
+            goto unmap;
+
+        debug("shrink vma %p-%p and %p-%p\n", last->addr,
+              last->addr + last->length, vma->addr, vma->addr + vma->length);
+
+        last->length += vma->length;
+        __remove_vma(vma);
+        continue;
+next:
+        last = vma;
+        continue;
+unmap:
+        if (vma->prot == PROT_NONE && !(vma->flags & VMA_TAINTED))
+            vma->flags |= VMA_UNMAPPED;
+        goto next;
+    }
+}
 
+int dump_all_vmas (struct shim_thread * thread, char * buf, int size)
+{
     struct shim_vma * vma;
     int cnt = 0;
+    lock(vma_list_lock);
 
     list_for_each_entry(vma, &vma_list, list) {
         void * start = vma->addr, * end = vma->addr + vma->length;
@@ -832,20 +903,18 @@ int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size)
                 name = qstrgetstr(&vma->file->path);
 
             cnt += snprintf(buf + cnt, size - cnt,
-                            start > (void *) 0xffffffff ? "%lx" : "%08x", start);
-
+                            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);
+                            vma->offset, dev_major, dev_minor, ino, name);
         } else {
             cnt += snprintf(buf + cnt, size - cnt,
-                            start > (void *) 0xffffffff ? "%lx" : "%08x", start);
-
+                            start > (void *) 0xffffffff ? "%lx" : "%08x",
+                            start);
             cnt += snprintf(buf + cnt, size - cnt,
                             end > (void *) 0xffffffff ? "-%lx" : "-%08x", end);
 
@@ -874,7 +943,6 @@ void unmap_all_vmas (void)
     struct shim_thread * cur_thread = get_cur_thread();
     struct shim_vma * tmp, * n;
     void * start = NULL, * end = NULL;
-
     lock(vma_list_lock);
 
     list_for_each_entry_safe(tmp, n, &vma_list, list) {
@@ -919,113 +987,122 @@ void unmap_all_vmas (void)
     unlock(vma_list_lock);
 }
 
-DEFINE_MIGRATE_FUNC(vma)
-
-MIGRATE_FUNC_BODY(vma)
+BEGIN_CP_FUNC(vma)
 {
     assert(size == sizeof(struct shim_vma));
 
     struct shim_vma * vma = (struct shim_vma *) obj;
     struct shim_vma * new_vma = NULL;
-    struct shim_handle * file = NULL;
     PAL_FLG pal_prot = PAL_PROT(vma->prot, 0);
 
-    if (vma->file && recursive)
-        __DO_MIGRATE(handle, vma->file, &file, 1);
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset, size);
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_vma));
+        ADD_TO_CP_MAP(obj, off);
 
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_vma));
+        new_vma = (struct shim_vma *) (base + off);
+        memcpy(new_vma, vma, sizeof(struct shim_vma));
 
-        if (!dry) {
-            new_vma = (struct shim_vma *) (base + off);
-            memcpy(new_vma, vma, sizeof(struct shim_vma));
+        if (vma->file)
+            DO_CP(handle, vma->file, &new_vma->file);
 
-            new_vma->file = file;
-            new_vma->received = 0;
-            REF_SET(new_vma->ref_count, 0);
-            INIT_LIST_HEAD(&new_vma->list);
+        REF_SET(new_vma->ref_count, 0);
+        INIT_LIST_HEAD(&new_vma->list);
+
+        void * need_mapped = vma->addr;
+
+#if MIGRATE_MORE_GIPC == 1
+        if (store->use_gipc) {
+            if (!NEED_MIGRATE_MEMORY_IF_GIPC(vma))
+                goto no_mem;
+        } else {
+            if (!NEED_MIGRATE_MEMORY(vma))
+                goto no_mem;
         }
+#else
+        if (!NEED_MIGRATE_MEMORY(vma))
+            goto no_mem;
+#endif
 
-        if (recursive && NEED_MIGRATE_MEMORY(vma)) {
-            void * send_addr = vma->addr;
-            size_t send_size = vma->length;
+        void * send_addr = vma->addr;
+        int    send_size = vma->length;
+        bool protected = false;
 
-            if (vma->file) {
-                size_t file_len = get_file_size(vma->file);
-                if (file_len >= 0 &&
-                    vma->offset + vma->length > file_len)
-                    send_size = file_len > vma->offset ?
-                                file_len - vma->offset : 0;
-            }
+        if (vma->file) {
+            int file_len = get_file_size(vma->file);
+            if (file_len >= 0 &&
+                vma->offset + vma->length > file_len)
+                send_size = file_len > vma->offset ?
+                    file_len - vma->offset : 0;
+        }
 
-            if (send_size) {
-                bool protected = false;
-                if (store->use_gipc) {
-#if HASH_GIPC == 1
-                    if (!dry && !(prot & PAL_PROT_READ)) {
-                        protected = true;
-                        DkVirtualMemoryProtect(send_addr, send_size,
-                                               pal_prot|PAL_PROT_READ);
-                    }
-#endif /* HASH_GIPC == 1 */
-                    struct shim_gipc_entry * gipc;
-                    DO_MIGRATE_SIZE(gipc, send_addr, send_size, &gipc, false);
-                    if (!dry) {
-                        gipc->prot = vma->prot;
-                        gipc->vma  = new_vma;
-                    }
+        if (!send_size)
+            goto no_mem;
+
+        if (store->use_gipc) {
 #if HASH_GIPC == 1
-                    if (protected)
-                        DkVirtualMemoryProtect(send_addr, send_size, pal_prot);
+            if (!(pal_prot & PAL_PROT_READ)) {
+                protected = true;
+                DkVirtualMemoryProtect(send_addr,
+                                       send_size,
+                                       pal_prot|PAL_PROT_READ);
+            }
 #endif /* HASH_GIPC == 1 */
-                } else {
-                    if (!dry && !(vma->prot & PROT_READ)) {
-                        protected = true;
-                        DkVirtualMemoryProtect(send_addr, send_size,
-                                               pal_prot|PAL_PROT_READ);
-                    }
-
-                    struct shim_mem_entry * mem;
-                    DO_MIGRATE_SIZE(memory, send_addr, send_size, &mem, false);
-                    if (!dry) {
-                        mem->prot = vma->prot;
-                        mem->vma = new_vma;
-                        mem->need_alloc = true;
-                    }
-
-                    if (protected)
-                        DkVirtualMemoryProtect(send_addr, send_size, pal_prot);
-                }
+            struct shim_gipc_entry * gipc;
+            DO_CP_SIZE(gipc, send_addr, send_size, &gipc);
+            gipc->mem.prot = pal_prot;
+        } else {
+            if (!(pal_prot & PROT_READ)) {
+                protected = true;
+                DkVirtualMemoryProtect(send_addr,
+                                       send_size,
+                                       pal_prot|PAL_PROT_READ);
             }
+
+            struct shim_mem_entry * mem;
+            DO_CP_SIZE(memory, send_addr, send_size, &mem);
+            mem->prot = pal_prot;
         }
 
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct shim_vma));
+        need_mapped = vma->addr + vma->length;
 
-    } else if (!dry)
+        if (protected)
+            DkVirtualMemoryProtect(send_addr, send_size, pal_prot);
+
+no_mem:
+        ADD_CP_FUNC_ENTRY(off);
+        ADD_CP_ENTRY(ADDR, need_mapped);
+    } else {
         new_vma = (struct shim_vma *) (base + off);
+    }
 
-    if (new_vma && objp)
+    if (objp)
         *objp = (void *) new_vma;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(vma)
 
-RESUME_FUNC_BODY(vma)
+DEFINE_PROFILE_CATAGORY(inside_rs_vma, resume_func);
+DEFINE_PROFILE_INTERVAL(vma_lookup_overlap, inside_rs_vma);
+DEFINE_PROFILE_INTERVAL(vma_add_bookkeep,   inside_rs_vma);
+DEFINE_PROFILE_INTERVAL(vma_map_file,       inside_rs_vma);
+DEFINE_PROFILE_INTERVAL(vma_map_anonymous,  inside_rs_vma);
+
+BEGIN_RS_FUNC(vma)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_vma));
-    struct shim_vma * vma = (struct shim_vma *) (base + off);
+    struct shim_vma * vma = (void *) (base + GET_CP_FUNC_ENTRY());
     struct shim_vma * tmp, * prev = NULL;
+    void * need_mapped = (void *) GET_CP_ENTRY(ADDR);
     int ret = 0;
 
-    RESUME_REBASE(vma->file);
-    RESUME_REBASE(vma->list);
+    CP_REBASE(vma->file);
+    CP_REBASE(vma->list);
 
     lock(vma_list_lock);
 
+    BEGIN_PROFILE_INTERVAL();
     tmp = __lookup_overlap_vma(vma->addr, vma->length, &prev);
+    SAVE_PROFILE_INTERVAL(vma_lookup_overlap);
 
     if (tmp) {
         if ((ret = __bkeep_munmap(vma->addr, vma->length, &vma->flags)) < 0)
@@ -1039,122 +1116,106 @@ RESUME_FUNC_BODY(vma)
     get_vma(vma);
     list_add(&vma->list, prev ? &prev->list : &vma_list);
     assert_vma();
+    SAVE_PROFILE_INTERVAL(vma_add_bookkeep);
 
     unlock(vma_list_lock);
 
-    int allocated = vma->received;
-
-    if (vma->flags & VMA_UNMAPPED)
-#ifdef DEBUG_RESUME
-        goto no_map;
-#else
-        return 0;
-#endif
-
-    if (vma->file)
-        get_handle(vma->file);
-
-    if (allocated < vma->length && vma->file) {
-        /* first try, use hstat to force it resumes pal handle */
-        assert(vma->file->fs && vma->file->fs->fs_ops &&
-               vma->file->fs->fs_ops->mmap);
-
-        void * addr = vma->addr + allocated;
+    if (!(vma->flags & VMA_UNMAPPED)) {
+        if (vma->file) {
+            struct shim_mount * fs = vma->file->fs;
+            get_handle(vma->file);
+
+            if (need_mapped < vma->addr + vma->length) {
+                /* first try, use hstat to force it resumes pal handle */
+                assert(vma->file->fs && vma->file->fs->fs_ops &&
+                       vma->file->fs->fs_ops->mmap);
+
+                void * addr = need_mapped;
+                int ret = fs->fs_ops->mmap(vma->file, &addr,
+                                           vma->addr + vma->length -
+                                           need_mapped,
+                                           vma->prot,
+                                           vma->flags,
+                                           vma->offset +
+                                           (need_mapped - vma->addr));
 
-        int ret = vma->file->fs->fs_ops->mmap(vma->file, &addr,
-                                              vma->length - allocated,
-                                              vma->prot|PAL_PROT_WRITECOPY,
-                                              vma->flags,
-                                              vma->offset + allocated);
+                if (ret < 0)
+                    return ret;
+                if (!addr)
+                    return -ENOMEM;
+                if (addr != need_mapped)
+                    return -EACCES;
 
-        if (ret < 0)
-            return ret;
-        if (!addr)
-            return -ENOMEM;
-        if (addr != vma->addr + allocated)
-            return -EACCES;
+                need_mapped += vma->length;
+                SAVE_PROFILE_INTERVAL(vma_map_file);
+            }
+        }
 
-        allocated = vma->length;
-    }
+        if (need_mapped < vma->addr + vma->length) {
+            int pal_alloc_type = (vma->flags & MAP_32BIT) ? PAL_ALLOC_32BIT : 0;
+            int pal_prot = vma->prot;
+            if (DkVirtualMemoryAlloc(need_mapped,
+                                     vma->addr + vma->length - need_mapped,
+                                     pal_alloc_type, pal_prot)) {
+                need_mapped += vma->length;
+                SAVE_PROFILE_INTERVAL(vma_map_anonymous);
+            }
+        }
 
-    if (allocated < vma->length) {
-        int pal_alloc_type = ((vma->flags & MAP_32BIT) ? PAL_ALLOC_32BIT : 0);
-        int pal_prot = vma->prot;
-        if (DkVirtualMemoryAlloc(vma->addr + allocated, vma->length - allocated,
-                                 pal_alloc_type, pal_prot))
-            allocated = vma->length;
+        if (need_mapped < vma->addr + vma->length)
+            sys_printf("vma %p-%p cannot be allocated!\n", need_mapped,
+                       vma->addr + vma->length);
     }
 
-    if (allocated < vma->length)
-        debug("vma %p-%p cannot be allocated!\n", vma->addr + allocated,
-              vma->addr + vma->length);
-
-    vma->received = allocated;
-
-#ifdef DEBUG_RESUME
-    if (vma->file) {
-        const char * type = "", * name = "";
-
-        if (!qstrempty(&vma->file->path)) {
-            type = ",path=";
-            name = qstrgetstr(&vma->file->path);
-        } else if (!qstrempty(&vma->file->uri)) {
-            type = ",uri=";
-            name = qstrgetstr(&vma->file->uri);
-        }
+    if (vma->file)
+        get_handle(vma->file);
 
-        debug("vma: %p-%p,size=%d,prot=%08x,flags=%08x,offset=%d%s%s\n",
-              vma->addr, vma->addr + vma->length, vma->length,
-              vma->prot, vma->flags, vma->offset, type, name);
-    } else {
-no_map:
-        debug("vma: %p-%p,size=%d,prot=%08x,flags=%08x,offset=%d\n",
-              vma->addr, vma->addr + vma->length, vma->length,
-              vma->prot, vma->flags, vma->offset);
-    }
-#endif /* DEBUG_RESUME */
+    if (vma->file)
+        DEBUG_RS("%p-%p,size=%d,prot=%08x,flags=%08x,off=%d,path=%s,uri=%s",
+                 vma->addr, vma->addr + vma->length, vma->length,
+                 vma->prot, vma->flags, vma->offset,
+                 qstrgetstr(&vma->file->path), qstrgetstr(&vma->file->uri));
+    else
+        DEBUG_RS("%p-%p,size=%d,prot=%08x,flags=%08x,off=%d",
+                 vma->addr, vma->addr + vma->length, vma->length,
+                 vma->prot, vma->flags, vma->offset);
 }
-END_RESUME_FUNC
-
-DEFINE_MIGRATE_FUNC(all_vmas)
+END_RS_FUNC(vma)
 
-MIGRATE_FUNC_BODY(all_vmas)
+BEGIN_CP_FUNC(all_vmas)
 {
+    struct shim_vma * tmp, ** vmas;
+    int nvmas = 0, cnt = 0;
+
     lock(vma_list_lock);
 
-    if (!list_empty(&vma_list)) {
-        struct shim_vma * tmp =
-                list_first_entry(&vma_list, struct shim_vma, list);
+    __shrink_vmas();
 
-        while (tmp) {
-            if (tmp->flags & VMA_INTERNAL)
-                goto next;
+    list_for_each_entry(tmp, &vma_list, list)
+        if (!(tmp->flags & VMA_INTERNAL))
+            nvmas++;
 
-            get_vma(tmp);
-            unlock(vma_list_lock);
+    if (!nvmas) {
+        unlock(vma_list_lock);
+        return 0;
+    }
 
-            DO_MIGRATE(vma, tmp, NULL, recursive);
+    vmas = __alloca(sizeof(struct shim_vam *) * nvmas);
 
-            lock(vma_list_lock);
-            put_vma(tmp);
-
-next:
-            if (tmp->list.next == &vma_list)
-                break;
-
-            tmp = list_entry(tmp->list.next, struct shim_vma, list);
+    list_for_each_entry(tmp, &vma_list, list)
+        if (!(tmp->flags & VMA_INTERNAL)) {
+            get_vma(tmp);
+            vmas[cnt++] = tmp;
         }
-    }
 
     unlock(vma_list_lock);
-}
-END_MIGRATE_FUNC
 
-RESUME_FUNC_BODY(all_vmas)
-{
-    /* useless */
+    for (cnt = 0 ; cnt < nvmas ; cnt++) {
+        DO_CP(vma, vmas[cnt], NULL);
+        put_vma(vmas[cnt]);
+    }
 }
-END_RESUME_FUNC
+END_CP_FUNC_NO_RS(all_vmas)
 
 void debug_print_vma_list (void)
 {

+ 1 - 1
LibOS/shim/src/elf/dl-machine-x86_64.h

@@ -58,7 +58,7 @@ elf_machine_matches_host (const Elf64_Ehdr * ehdr)
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-#define DEBUG_RELOC
+//#define DEBUG_RELOC
 
 static bool
 elf_machine_rela (struct link_map * l, ElfW(Rela) * reloc, Elf64_Sym * sym,

+ 67 - 173
LibOS/shim/src/elf/shim_rtld.c

@@ -37,7 +37,7 @@
 #include <shim_profile.h>
 
 #include <errno.h>
-#include <fcntl.h>
+
 #include <asm/prctl.h>
 #include <asm/mman.h>
 
@@ -952,8 +952,9 @@ static int __read_elf_header (struct shim_handle * file, void * fbp)
         return -EACCES;
 
     (*seek) (file, 0, SEEK_SET);
-
-    return (*read) (file, fbp, FILEBUF_SIZE);
+    int ret = (*read) (file, fbp, FILEBUF_SIZE);
+    (*seek) (file, 0, SEEK_SET);
+    return ret;
 }
 
 static int __load_elf_header (struct shim_handle * file, void * fbp,
@@ -973,74 +974,15 @@ static int __load_elf_header (struct shim_handle * file, void * fbp,
     return 0;
 }
 
-int check_elf_object (struct shim_handle ** file)
+int check_elf_object (struct shim_handle * file)
 {
-    struct shim_handle * exec = *file;
     char fb[FILEBUF_SIZE];
-    int ret;
-
-    if (!exec)
-        return -EINVAL;
-
-    int len = __read_elf_header(exec, &fb);
-    if (len < 0)
-        return len;
-
-    if (!(ret = __check_elf_header(&fb, len)) || ret != -EINVAL)
-        return ret;
-
-    if (memcmp(fb, "#!", 2))
-        return -EACCES;
-
-    const char * shargs[16];
-    int shnargs = 0;
-    char * p = fb + 2, * e = fb + len;
-
-    while (p < e) {
-        assert(shnargs < 16);
-        char * np = p;
-        while (np < e && *np != ' ' && *np != '\n')
-            np++;
-        if (*np == '\n')
-            e = np;
-        *np = '\0';
-        shargs[shnargs++] = p;
-        p = np + 1;
-    }
-
-    if (!shnargs)
-        return -EINVAL;
-
-    debug("detected as script: run by %s\n", shargs[0]);
-
-    struct shim_dentry * dent = NULL;
-    if ((ret = path_lookupat(NULL, shargs[0], LOOKUP_OPEN, &dent)) < 0)
-        return ret;
-
-    if (!dent->fs || !dent->fs->d_ops ||
-        !dent->fs->d_ops->open) {
-        ret = -EACCES;
-err:
-        put_dentry(dent);
-        return ret;
-    }
-
-    struct shim_handle * new_exe = get_new_handle();
-    if (!new_exe) {
-        ret = -ENOMEM;
-        goto err;
-    }
 
-    set_handle_fs(new_exe, dent->fs);
-    new_exe->flags = O_RDONLY;
-    new_exe->acc_mode = MAY_READ;
-
-    if ((ret = dent->fs->d_ops->open(new_exe, dent, O_RDONLY)) < 0)
-        goto err;
+    int l = __read_elf_header(file, &fb);
+    if (l < 0)
+        return l;
 
-    flush_handle(*file);
-    *file = new_exe;
-    return 0;
+    return __check_elf_header(&fb, l);
 }
 
 static int __load_elf_object (struct shim_handle * file, void * addr,
@@ -1532,15 +1474,12 @@ int remove_loaded_libraries (void)
 }
 
 void * __load_address;
-
 void * migrated_shim_addr __attribute_migratable = &__load_address;
 
 int init_internal_map (void)
 {
     __load_elf_object(NULL, &__load_address, OBJECT_INTERNAL, NULL);
-
     internal_map->l_name = "libsysdb.so";
-
     return 0;
 }
 
@@ -1641,105 +1580,84 @@ int execute_elf_object (struct shim_handle * exec, int argc, const char ** argp,
     return 0;
 }
 
-DEFINE_MIGRATE_FUNC(library)
-
-MIGRATE_FUNC_BODY(library)
+BEGIN_CP_FUNC(library)
 {
     assert(size == sizeof(struct link_map));
 
     struct link_map * map = (struct link_map *) obj;
     struct link_map * new_map;
 
-    struct shim_handle * file = NULL;
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-    if (map->l_file)
-        __DO_MIGRATE(handle, map->l_file, &file, 1);
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct link_map));
+        ADD_TO_CP_MAP(obj, off);
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset, size);
-    int namelen = map->l_name ? strlen(map->l_name) : 0;
-    int sonamelen = map->l_soname ? strlen(map->l_soname) : 0;
-
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct link_map));
+        new_map = (struct link_map *) (base + off);
+        memcpy(new_map, map, sizeof(struct link_map));
 
-        if (!dry) {
-            new_map = (struct link_map *) (base + off);
-            memcpy(new_map, map, sizeof(struct link_map));
+        new_map->l_prev = NULL;
+        new_map->l_next = NULL;
+        new_map->textrels = NULL;
 
-            get_handle(file);
-            new_map->l_file = file;
-            new_map->l_prev = NULL;
-            new_map->l_next = NULL;
-            new_map->textrels = NULL;
-        }
+        if (map->l_file)
+            DO_CP_MEMBER(handle, map, new_map, l_file);
 
         if (map->l_ld) {
             int size = sizeof(ElfW(Dyn)) * map->l_ldnum;
-            ADD_OFFSET(size);
-            if (!dry) {
-                ElfW(Dyn) * ld = (void *) (base + *offset);
-                memcpy(ld, map->l_ld, size);
-                new_map->l_ld = ld;
-                for (ElfW(Dyn) ** dyn = new_map->l_info ;
-                     (void *) dyn < ((void *) new_map->l_info +
-                     sizeof(new_map->l_info)) ; dyn++)
-                    if (*dyn)
-                        *dyn = ((void *) *dyn + ((void *) ld -
-                                (void *) map->l_ld));
-            }
+            ElfW(Dyn) * ld = (void *) (base + ADD_CP_OFFSET(size));
+            memcpy(ld, map->l_ld, size);
+            new_map->l_ld = ld;
+
+            ElfW(Dyn) ** start = new_map->l_info;
+            ElfW(Dyn) ** end = (void *) start + sizeof(new_map->l_info);
+            ElfW(Dyn) ** dyn;
+            for (dyn = start ; dyn < end ; dyn++)
+                 if (*dyn)
+                    *dyn = (void *) *dyn + ((void *) ld - (void *) map->l_ld);
         }
 
         if (map->l_name) {
-            ADD_OFFSET(namelen + 1);
-
-            if (!dry && map->l_name) {
-                char * name = (char *) (base + *offset);
-                memcpy(name, map->l_name, namelen + 1);
-                new_map->l_name = name;
-            }
+            int namelen = strlen(map->l_name);
+            char * name = (char *) (base + ADD_CP_OFFSET(namelen + 1));
+            memcpy(name, map->l_name, namelen + 1);
+            new_map->l_name = name;
         }
 
         if (map->l_soname) {
-            ADD_OFFSET(sonamelen + 1);
-
-            if (!dry && map->l_soname) {
-                char * soname = (char *) (base + *offset);
-                memcpy(soname, map->l_soname, sonamelen + 1);
-                new_map->l_soname = soname;
-            }
+            int sonamelen = strlen(map->l_soname);
+            char * soname = (char *) (base + ADD_CP_OFFSET(sonamelen + 1));
+            memcpy(soname, map->l_soname, sonamelen + 1);
+            new_map->l_soname = soname;
         }
 
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct link_map));
-
-    } else if (!dry) {
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_map = (struct link_map *) (base + off);
     }
 
-    if (new_map && objp)
+    if (objp)
         *objp = (void *) new_map;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(library)
 
-DEFINE_PROFILE_CATAGORY(inside_resume_library,  resume_func);
-DEFINE_PROFILE_INTERVAL(clean_up_library,       inside_resume_library);
-DEFINE_PROFILE_INTERVAL(search_library_vma,     inside_resume_library);
-DEFINE_PROFILE_INTERVAL(relocate_library,       inside_resume_library);
-DEFINE_PROFILE_INTERVAL(add_or_replace_library, inside_resume_library);
+DEFINE_PROFILE_CATAGORY(inside_rs_library, resume_func);
+DEFINE_PROFILE_INTERVAL(clean_up_library,       inside_rs_library);
+DEFINE_PROFILE_INTERVAL(search_library_vma,     inside_rs_library);
+DEFINE_PROFILE_INTERVAL(relocate_library,       inside_rs_library);
+DEFINE_PROFILE_INTERVAL(add_or_replace_library, inside_rs_library);
 
-RESUME_FUNC_BODY(library)
+BEGIN_RS_FUNC(library)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct link_map));
-    struct link_map * map = (struct link_map *) (base + off);
+    struct link_map * map = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    RESUME_REBASE(map->l_name);
-    RESUME_REBASE(map->l_soname);
-    RESUME_REBASE(map->l_file);
+    CP_REBASE(map->l_name);
+    CP_REBASE(map->l_soname);
+    CP_REBASE(map->l_file);
 
     if (map->l_ld && map->l_ld != map->l_real_ld) {
-        RESUME_REBASE(map->l_ld);
-        RESUME_REBASE(map->l_info);
+        CP_REBASE(map->l_ld);
+        CP_REBASE(map->l_info);
     }
 
     BEGIN_PROFILE_INTERVAL();
@@ -1751,24 +1669,6 @@ RESUME_FUNC_BODY(library)
 
     SAVE_PROFILE_INTERVAL(clean_up_library);
 
-    struct shim_vma * vma = NULL;
-
-    if (lookup_supervma((void *) map->l_map_start, allocsize, &vma) < 0 ||
-        vma->addr != (void *) map->l_map_start ||
-        !vma->received) {
-        sys_printf(vma ? "library %s (%p - %p) not received\n" :
-                   "library %s (%p - %p) not mapped\n",
-                   map->l_name, map->l_map_start, map->l_map_end);
-
-        if (vma)
-            put_vma(vma);
-
-        return -ENOMEM;
-    }
-
-    put_vma(vma);
-    SAVE_PROFILE_INTERVAL(search_library_vma);
-
     if (internal_map && (!map->l_resolved ||
         map->l_resolved_map != internal_map->l_addr)) {
         do_relocate_object(map);
@@ -1782,22 +1682,18 @@ RESUME_FUNC_BODY(library)
 
     SAVE_PROFILE_INTERVAL(add_or_replace_library);
 
-#ifdef DEBUG_RESUME
-    debug("library: loaded at %p,name=%s\n", map->l_addr, map->l_name);
-#endif
+    DEBUG_RS("base=%p,name=%s", map->l_addr, map->l_name);
 }
-END_RESUME_FUNC
-
-DEFINE_MIGRATE_FUNC(loaded_libraries)
+END_RS_FUNC(library)
 
-MIGRATE_FUNC_BODY(loaded_libraries)
+BEGIN_CP_FUNC(loaded_libraries)
 {
     struct link_map * map = loaded_libraries, * new_interp_map = NULL;
     while (map) {
-        struct link_map * new_map = NULL, ** map_obj = &new_map;
+        struct link_map * new_map = NULL;
 
         if (map != internal_map)
-            DO_MIGRATE(library, map, map_obj, recursive);
+            DO_CP(library, map, &new_map);
 
         if (map == interp_map)
             new_interp_map = new_map;
@@ -1805,19 +1701,17 @@ MIGRATE_FUNC_BODY(loaded_libraries)
         map = map->l_next;
     }
 
-    ADD_FUNC_ENTRY(new_interp_map);
+    ADD_CP_FUNC_ENTRY(new_interp_map);
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(loaded_libraries)
 
-RESUME_FUNC_BODY(loaded_libraries)
+BEGIN_RS_FUNC(loaded_libraries)
 {
-    interp_map = (struct link_map *) GET_FUNC_ENTRY();
+    interp_map = (void *) GET_CP_FUNC_ENTRY();
 
     if (interp_map) {
-        RESUME_REBASE(interp_map);
-#ifdef DEBUG_RESUME
-        debug("library: interpreter is %s\n", interp_map->l_name);
-#endif
+        CP_REBASE(interp_map);
+        DEBUG_RS("%s as interp", interp_map->l_name);
     }
 }
-END_RESUME_FUNC
+END_RS_FUNC(loaded_libraries)

+ 26 - 13
LibOS/shim/src/fs/chroot/fs.c

@@ -34,11 +34,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
 #include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <errno.h>
 
 #define URI_MAX_SIZE    STR_SIZE
 
@@ -351,6 +355,9 @@ static int chroot_lookup (struct shim_dentry * dent, bool force)
     if (!force)
         return -ESKIPPED;
 
+    if (dent->fs && dent == dent->fs->root)
+        return 0;
+
     return query_dentry(dent, NULL, NULL, NULL);
 }
 
@@ -375,20 +382,28 @@ static int __chroot_open (const char * uri, int len, int flags, mode_t mode,
         && accmode == O_WRONLY)
         accmode = O_RDWR;
 
-    PAL_HANDLE palhdl = DkStreamOpen(uri, accmode, mode, creat, option);
+    PAL_HANDLE palhdl;
+
+    if (hdl && hdl->pal_handle) {
+        palhdl = hdl->pal_handle;
+    } else {
+        palhdl = DkStreamOpen(uri, accmode, mode, creat, option);
 
-    if (!palhdl) {
-        if (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED &&
-            accmode != oldmode)
-            palhdl = DkStreamOpen(uri, oldmode, mode, creat, option);
+        if (!palhdl) {
+            if (PAL_NATIVE_ERRNO == PAL_ERROR_DENIED &&
+                accmode != oldmode)
+                palhdl = DkStreamOpen(uri, oldmode, mode, creat, option);
 
-        if (!palhdl)
-            return -PAL_ERRNO;
+            if (!palhdl)
+                return -PAL_ERRNO;
+        }
     }
 
-    lock(data->lock);
-    ret = __query_attr(data, palhdl);
-    unlock(data->lock);
+    if (!data->queried) {
+        lock(data->lock);
+        ret = __query_attr(data, palhdl);
+        unlock(data->lock);
+    }
 
     if (!hdl) {
         DkObjectClose(palhdl);
@@ -1006,7 +1021,6 @@ static int chroot_checkout (struct shim_handle * hdl)
     hdl->info.file.mapsize = 0;
     hdl->info.file.mapoffset = 0;
     hdl->info.file.mapbuf = NULL;
-
     hdl->pal_handle = NULL;
     return 0;
 }
@@ -1146,7 +1160,6 @@ static int chroot_chmod (struct shim_dentry * dent, mode_t mode)
     }
 
     DkObjectClose(pal_hdl);
-
     dent->mode = data->mode = mode;
 
     return 0;

+ 5 - 1
LibOS/shim/src/fs/dev/fs.c

@@ -32,11 +32,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
 #include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <errno.h>
 
 #define EMPTY_DEV_OPS                       \
     {                                       \

+ 9 - 5
LibOS/shim/src/fs/pipe/fs.c

@@ -27,18 +27,22 @@
 #include <shim_thread.h>
 #include <shim_handle.h>
 #include <shim_fs.h>
+#include <shim_profile.h>
 
 #include <pal.h>
 #include <pal_error.h>
 #include <pal_debug.h>
 
-#include <linux/types.h>
-typedef __kernel_pid_t pid_t;
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+#include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
 #include <asm/fcntl.h>
-#include <errno.h>
 #include <shim_profile.h>
 
 static int pipe_read (struct shim_handle * hdl, void * buf,
@@ -83,8 +87,8 @@ static int pipe_hstat (struct shim_handle * hdl, struct stat * stat)
     stat->st_gid    = (gid_t) thread->gid;    /* group ID of owner */
     stat->st_rdev   = (dev_t) 0;     /* device ID (if special file) */
     stat->st_size   = (off_t) 0;     /* total size, in bytes */
-    stat->st_blksize = (blksize_t) 0;   /* blocksize for file system I/O */
-    stat->st_blocks = (blkcnt_t) 0;     /* number of 512B blocks allocated */
+    stat->st_blksize = 0;            /* blocksize for file system I/O */
+    stat->st_blocks = 0;             /* number of 512B blocks allocated */
     stat->st_atime  = (time_t) 0;    /* access time */
     stat->st_mtime  = (time_t) 0;    /* last modification */
     stat->st_ctime  = (time_t) 0;    /* last status change */

+ 6 - 2
LibOS/shim/src/fs/proc/fs.c

@@ -32,11 +32,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+#include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <fcntl.h>
-#include <errno.h>
 
 extern const struct proc_nm_ops nm_thread;
 extern const struct proc_fs_ops fs_thread;

+ 5 - 1
LibOS/shim/src/fs/proc/info.c

@@ -7,11 +7,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
 #include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <errno.h>
 
 static int proc_info_mode (const char * name, mode_t * mode)
 {

+ 6 - 1
LibOS/shim/src/fs/proc/ipc-thread.c

@@ -12,10 +12,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+#include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <errno.h>
 
 static int parse_ipc_thread_name (const char * name,
                                   const char ** next, int * next_len,

+ 5 - 1
LibOS/shim/src/fs/proc/thread.c

@@ -11,11 +11,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.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
 

+ 79 - 10
LibOS/shim/src/fs/shim_dcache.c

@@ -91,18 +91,16 @@ static struct shim_dentry * alloc_dentry (void)
     INIT_LIST_HEAD(&dent->list);
     INIT_LIST_HEAD(&dent->children);
     INIT_LIST_HEAD(&dent->siblings);
-    INIT_LIST_HEAD(&dent->alias);
 
     return dent;
 }
 
 DEFINE_PROFILE_CATAGORY(dcache, );
 DEFINE_PROFILE_INTERVAL(total_init_dcache, dcache);
-DEFINE_PROFILE_CATAGORY(init_dcache, dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_memory, init_dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_hash_table, init_dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_lock, init_dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_root_entry, init_dcache);
+DEFINE_PROFILE_CATAGORY(within_init_dcache, dcache);
+DEFINE_PROFILE_INTERVAL(dcache_init_memory, within_init_dcache);
+DEFINE_PROFILE_INTERVAL(dcache_init_lock, within_init_dcache);
+DEFINE_PROFILE_INTERVAL(dcache_init_root_entry, within_init_dcache);
 
 int init_dcache (void)
 {
@@ -114,10 +112,6 @@ int init_dcache (void)
     dentry_mgr = create_mem_mgr(init_align_up(DCACHE_MGR_ALLOC));
     SAVE_PROFILE_INTERVAL(dcache_init_memory);
 
-    for (int i = 0 ; i < DCACHE_HASH_SIZE ; i++)
-        INIT_HLIST_HEAD(&dcache_htable[i]);
-    SAVE_PROFILE_INTERVAL(dcache_init_hash_table);
-
     create_lock(dcache_lock);
     SAVE_PROFILE_INTERVAL(dcache_init_lock);
 
@@ -451,3 +445,78 @@ resume:
 
     return 0;
 }
+
+BEGIN_CP_FUNC(dentry)
+{
+    assert(size == sizeof(struct shim_dentry));
+
+    struct shim_dentry * dent = (struct shim_dentry *) obj;
+    struct shim_dentry * new_dent = NULL;
+
+    ptr_t off = GET_FROM_CP_MAP(obj);
+
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_dentry));
+        ADD_TO_CP_MAP(obj, off);
+        new_dent = (struct shim_dentry *) (base + off);
+
+        lock(dent->lock);
+        *new_dent = *dent;
+        INIT_HLIST_NODE(&new_dent->hlist);
+        INIT_LIST_HEAD(&new_dent->list);
+        INIT_LIST_HEAD(&new_dent->children);
+        INIT_LIST_HEAD(&new_dent->siblings);
+        new_dent->data = NULL;
+        clear_lock(new_dent->lock);
+        REF_SET(new_dent->ref_count, 0);
+
+        DO_CP_IN_MEMBER(qstr, new_dent, rel_path);
+        DO_CP_IN_MEMBER(qstr, new_dent, name);
+
+        if (dent->fs)
+            DO_CP_MEMBER(mount, dent, new_dent, fs);
+
+        if (dent->parent)
+            DO_CP_MEMBER(dentry, dent, new_dent, parent);
+
+        if (dent->mounted)
+            DO_CP_MEMBER(mount, dent, new_dent, mounted);
+
+        unlock(dent->lock);
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
+        new_dent = (struct shim_dentry *) (base + off);
+    }
+
+    if (objp)
+        *objp = (void *) new_dent;
+}
+END_CP_FUNC(dentry)
+
+BEGIN_RS_FUNC(dentry)
+{
+    struct shim_dentry * dent = (void *) (base + GET_CP_FUNC_ENTRY());
+    BEGIN_PROFILE_INTERVAL();
+
+    CP_REBASE(dent->hlist);
+    CP_REBASE(dent->list);
+    CP_REBASE(dent->children);
+    CP_REBASE(dent->siblings);
+    CP_REBASE(dent->fs);
+    CP_REBASE(dent->parent);
+    CP_REBASE(dent->mounted);
+
+    create_lock(dent->lock);
+
+    if (dent->parent)
+        __set_parent_dentry(dent, dent->parent);
+
+    struct hlist_head * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
+    hlist_add_head(&dent->hlist, head);
+    dent->state |= DENTRY_HASHED;
+
+    DEBUG_RS("hash=%08x,path=%s,fs=%s", dent->rel_path.hash,
+             dentry_get_path(dent, true, NULL),
+             dent->fs ? qstrgetstr(&dent->fs->path) : NULL);
+}
+END_RS_FUNC(dentry)

+ 58 - 80
LibOS/shim/src/fs/shim_fs.c

@@ -81,8 +81,7 @@ int init_fs (void)
 
     create_lock(mount_mgr_lock);
     create_lock(mount_list_lock);
-
-    return init_dcache();
+    return 0;
 }
 
 static struct shim_mount * alloc_mount (void)
@@ -391,74 +390,72 @@ int walk_mounts (int (*walk) (struct shim_mount * mount, void * arg),
     return ret < 0 ? ret : (nsrched ? 0 : -ESRCH);
 }
 
-DEFINE_MIGRATE_FUNC(mount)
-
-MIGRATE_FUNC_BODY(mount)
+BEGIN_CP_FUNC(mount)
 {
     assert(size == sizeof(struct shim_mount));
 
     struct shim_mount * mount = (struct shim_mount *) obj;
     struct shim_mount * new_mount = NULL;
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset,
-                                           sizeof(struct shim_mount));
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_mount));
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_mount));
+        ADD_TO_CP_MAP(obj, off);
 
-        if (dry) {
-            mount->cpdata = NULL;
-            mount->cpsize = 0;
-
-            if (mount->fs_ops &&
-                mount->fs_ops->checkpoint) {
-                void * cpdata = NULL;
-                int bytes = mount->fs_ops->checkpoint(&cpdata, mount->data);
-                if (bytes > 0 && cpdata) {
-                    mount->cpdata = cpdata;
-                    mount->cpsize = bytes;
-                    ADD_OFFSET(bytes);
-                }
-            }
-        } else {
-            new_mount = (struct shim_mount *) (base + off);
-            memcpy(new_mount, mount, sizeof(struct shim_mount));
-
-            if (mount->cpdata) {
-                ADD_OFFSET(mount->cpsize);
-                new_mount->cpdata = (void *) (base + *offset);
-                memcpy(new_mount->cpdata, mount->cpdata, mount->cpsize);
+        if (!mount->cpdata &&
+            mount->fs_ops &&
+            mount->fs_ops->checkpoint) {
+            void * cpdata = NULL;
+            int bytes = mount->fs_ops->checkpoint(&cpdata, mount->data);
+            if (bytes > 0) {
+                mount->cpdata = cpdata;
+                mount->cpsize = bytes;
             }
+        }
+
+        new_mount = (struct shim_mount *) (base + off);
+        *new_mount = *mount;
 
-            new_mount->data = NULL;
-            new_mount->mount_point = NULL;
-            new_mount->root = NULL;
-            INIT_LIST_HEAD(&new_mount->list);
+        if (mount->cpdata) {
+            struct shim_mem_entry * entry;
+            DO_CP_SIZE(memory, mount->cpdata, mount->cpsize, &entry);
+            new_mount->cpdata = NULL;
+            entry->paddr = &new_mount->cpdata;
         }
 
-        DO_MIGRATE_IN_MEMBER(qstr, mount, new_mount, path, false);
-        DO_MIGRATE_IN_MEMBER(qstr, mount, new_mount, uri,  false);
+        new_mount->data = NULL;
+        new_mount->mount_point = NULL;
+        new_mount->root = NULL;
+        INIT_LIST_HEAD(&new_mount->list);
 
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct shim_mount));
+        DO_CP_IN_MEMBER(qstr, new_mount, path);
+        DO_CP_IN_MEMBER(qstr, new_mount, uri);
 
-    } else if (!dry) {
+        if (mount->mount_point)
+            DO_CP_MEMBER(dentry, mount, new_mount, mount_point);
+
+        if (mount->root)
+            DO_CP_MEMBER(dentry, mount, new_mount, root);
+
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_mount = (struct shim_mount *) (base + off);
     }
 
-    if (new_mount && objp)
+    if (objp)
         *objp = (void *) new_mount;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(mount)
 
-RESUME_FUNC_BODY(mount)
+BEGIN_RS_FUNC(mount)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_mount));
-    struct shim_mount * mount = (struct shim_mount *) (base + off);
+    struct shim_mount * mount = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    RESUME_REBASE(mount->cpdata);
-    RESUME_REBASE(mount->list);
+    CP_REBASE(mount->cpdata);
+    CP_REBASE(mount->list);
+    CP_REBASE(mount->mount_point);
+    CP_REBASE(mount->root);
 
     struct shim_fs * fs = find_fs(mount->type);
 
@@ -472,55 +469,36 @@ RESUME_FUNC_BODY(mount)
     mount->fs_ops = fs->fs_ops;
     mount->d_ops = fs->d_ops;
 
-    if (!qstrempty(&mount->path)) {
-        struct shim_dentry * dent = NULL;
-        const char * mount_point = qstrgetstr(&mount->path);
-
-        int err = path_lookupat(NULL, mount_point, 0, &dent);
-
-        if (!err && dent) {
-            err = __mount_fs(mount, dent);
-            assert(err == 0);
-        }
+    list_add_tail(&mount->list, &mount_list);
 
-#ifdef DEBUG_RESUME
-        debug("mount: type=%s,uri=%s,path=%s\n", mount->type,
-              qstrgetstr(&mount->uri), mount_point);
-#endif
-    }
-#ifdef DEBUG_RESUME
-    else {
-        debug("mount: type=%s,uri=%s\n", mount->type,
-              qstrgetstr(&mount->uri));
+    if (!qstrempty(&mount->path)) {
+        DEBUG_RS("type=%s,uri=%s,path=%s", mount->type, qstrgetstr(&mount->uri),
+                 qstrgetstr(&mount->path));
+    } else {
+        DEBUG_RS("type=%s,uri=%s", mount->type, qstrgetstr(&mount->uri));
     }
-#endif
 }
-END_RESUME_FUNC
-
-DEFINE_MIGRATE_FUNC(all_mounts)
+END_RS_FUNC(mount)
 
-MIGRATE_FUNC_BODY(all_mounts)
+BEGIN_CP_FUNC(all_mounts)
 {
     struct shim_mount * mount;
-
     lock(mount_list_lock);
     list_for_each_entry(mount, &mount_list, list)
-        DO_MIGRATE(mount, mount, NULL, recursive);
-
+        DO_CP(mount, mount, NULL);
     unlock(mount_list_lock);
 
     /* add an empty entry to mark as migrated */
-    ADD_FUNC_ENTRY(0);
+    ADD_CP_FUNC_ENTRY(0);
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(all_mounts)
 
-RESUME_FUNC_BODY(all_mounts)
+BEGIN_RS_FUNC(all_mounts)
 {
-    GET_FUNC_ENTRY();
     /* to prevent file system from being mount again */
     mount_migrated = true;
 }
-END_RESUME_FUNC
+END_RS_FUNC(all_mounts)
 
 const char * get_file_name (const char * path, size_t len)
 {

+ 47 - 22
LibOS/shim/src/fs/shim_namei.c

@@ -35,8 +35,10 @@
 
 #include <pal.h>
 
-#include <errno.h>
-#include <fcntl.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+#include <asm/fcntl.h>
 
 /* check permission of a dentry. If force is not set, permission
    is consider granted on invalid dentries */
@@ -156,7 +158,7 @@ static int do_lookup (struct lookup * look, const char * name, int namelen,
     int err = 0;
     struct shim_dentry * dent = NULL;
 
-    if ((err = lookup_dentry(look->dentry, name, namelen, force, &dent)) < 0)
+    if ((err = lookup_dentry(look->dentry, name, namelen,force, &dent)) < 0)
         goto fail;
 
     path_reacquire(look, dent);
@@ -541,6 +543,10 @@ static int path_lookup_walk (struct shim_dentry * start,
     return link_path_walk(name, look);
 }
 
+DEFINE_PROFILE_CATAGORY(path_lookup, dcache);
+DEFINE_PROFILE_INTERVAL(lookup_dcache_for_path_lookup, path_lookup);
+DEFINE_PROFILE_INTERVAL(lookup_walk_for_path_lookup,   path_lookup);
+
 int __path_lookupat (struct shim_dentry * start, const char * path, int flags,
                      struct shim_dentry ** dent)
 {
@@ -548,17 +554,21 @@ int __path_lookupat (struct shim_dentry * start, const char * path, int flags,
     struct shim_dentry * found = NULL;
     int ret = 0;
     struct lookup look;
+    BEGIN_PROFILE_INTERVAL();
 
     ret = path_lookup_dcache(start, path, flags, &found, cur_thread);
     if (ret < 0)
         return ret;
 
+    SAVE_PROFILE_INTERVAL(lookup_dcache_for_path_lookup);
+
     if (!found) {
         if ((ret = path_lookup_walk(start, path, flags, &look, cur_thread)) < 0)
             return ret;
 
         get_dentry(look.dentry);
         found = look.dentry;
+        SAVE_PROFILE_INTERVAL(lookup_walk_for_path_lookup);
 
         if (flags & LOOKUP_SYNC) {
             if ((ret = __do_lookup_dentry(found, true)) < 0)
@@ -595,6 +605,7 @@ int path_lookupat (struct shim_dentry * start, const char * path, int flags,
     struct lookup look;
 
     lock(dcache_lock);
+    BEGIN_PROFILE_INTERVAL();
 
     ret = path_lookup_dcache(start, path, flags, &found, cur_thread);
 
@@ -603,6 +614,8 @@ int path_lookupat (struct shim_dentry * start, const char * path, int flags,
         return ret;
     }
 
+    SAVE_PROFILE_INTERVAL(lookup_dcache_for_path_lookup);
+
     if (!found) {
         if ((ret = path_lookup_walk(start, path, flags, &look,
                                     cur_thread)) < 0)
@@ -610,6 +623,7 @@ int path_lookupat (struct shim_dentry * start, const char * path, int flags,
 
         get_dentry(look.dentry);
         found = look.dentry;
+        SAVE_PROFILE_INTERVAL(lookup_walk_for_path_lookup);
 
         if (flags & LOOKUP_SYNC) {
             if ((ret = __do_lookup_dentry(found, true)) < 0)
@@ -733,6 +747,7 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
     BEGIN_PROFILE_INTERVAL();
     lock(dcache_lock);
 
+#if 0
     err = path_lookup_dcache(start, path, lookup_flags|LOOKUP_OPEN,
                              &look.dentry, cur_thread);
 
@@ -749,6 +764,7 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
         SAVE_PROFILE_INTERVAL(end_open_namei);
         return err;
     }
+#endif
 
     if (look.dentry) {
         if (look.dentry->state & DENTRY_NEGATIVE) {
@@ -788,12 +804,16 @@ do_open:
         SAVE_PROFILE_INTERVAL(open_namei_permission);
         if (hdl) {
             if (look.dentry->state & DENTRY_ISDIRECTORY) {
-                assert(flags & O_DIRECTORY);
                 if ((err = directory_open(hdl, look.dentry, flags)) < 0)
                     goto exit;
                 SAVE_PROFILE_INTERVAL(open_namei_dir_open);
             } else {
-                assert(!(flags & O_DIRECTORY));
+                err = -ENOTDIR;
+                if (flags & O_DIRECTORY) {
+                    debug("%s is not a directory\n",
+                          dentry_get_path(look.dentry, true, NULL));
+                    goto exit;
+                }
                 if ((err = dentry_open(hdl, look.dentry, flags)) < 0)
                     goto exit;
                 SAVE_PROFILE_INTERVAL(open_namei_dentry_open);
@@ -814,6 +834,7 @@ do_open:
 
     struct shim_dentry * new = NULL;
     dir = look.dentry;
+    get_dentry(dir);
     err = lookup_dentry(dir, look.last, strlen(look.last), true, &new);
     SAVE_PROFILE_INTERVAL(open_namei_lookup_2);
     if (err < 0 && (err != -ENOENT || !new))
@@ -1021,30 +1042,31 @@ int directory_open (struct shim_handle * hdl, struct shim_dentry * dent,
 done_read:
     unlock(dcache_lock);
 
-    if (!(dent->state & DENTRY_LISTED))
-        return ret;
+    struct shim_dentry ** children = NULL;
 
-    int nchildren = dent->nchildren, count = 0;
-    struct shim_dentry ** children = malloc(sizeof(struct shim_dentry *) *
-                                            (nchildren + 1));
-    struct shim_dentry * child;
+    if (dent->state & DENTRY_LISTED) {
+        int nchildren = dent->nchildren, count = 0;
+        struct shim_dentry * child;
 
-    list_for_each_entry(child, &dent->children, siblings) {
-        if (count >= nchildren)
-            break;
+        children = malloc(sizeof(struct shim_dentry *) * (nchildren + 1));
+
+        list_for_each_entry(child, &dent->children, siblings) {
+            if (count >= nchildren)
+                break;
 
-        struct shim_dentry * c = child;
+            struct shim_dentry * c = child;
 
-        while (c->state & DENTRY_MOUNTPOINT)
-            c = c->mounted->root;
+            while (c->state & DENTRY_MOUNTPOINT)
+                c = c->mounted->root;
 
-        if (c->state & DENTRY_VALID) {
-            get_dentry(c);
-            children[count++] = c;
+            if (c->state & DENTRY_VALID) {
+                get_dentry(c);
+                children[count++] = c;
+            }
         }
-    }
 
-    children[count] = NULL;
+        children[count] = NULL;
+    }
 
     qstrsetstr(&hdl->path, path, size);
     hdl->type = TYPE_DIR;
@@ -1052,12 +1074,15 @@ done_read:
     memcpy(hdl->fs_type, fs->type, sizeof(fs->type));
     hdl->dentry = dent;
     hdl->flags = flags;
+
     get_dentry(dent);
     hdl->info.dir.dot = dent;
+
     if (dent->parent) {
         get_dentry(dent->parent);
         hdl->info.dir.dotdot = dent->parent;
     }
+
     hdl->info.dir.buf = children;
     hdl->info.dir.ptr = children;
 out:

+ 5 - 1
LibOS/shim/src/fs/socket/fs.c

@@ -30,11 +30,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
 #include <asm/fcntl.h>
-#include <errno.h>
 
 static int socket_close (struct shim_handle * hdl)
 {

+ 6 - 2
LibOS/shim/src/fs/str/fs.c

@@ -30,11 +30,15 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+#include <asm/fcntl.h>
 #include <asm/mman.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
-#include <fcntl.h>
-#include <errno.h>
 
 int str_open (struct shim_handle * hdl, struct shim_dentry * dent,
                  int flags)

+ 44 - 67
LibOS/shim/src/ipc/shim_ipc.c

@@ -29,6 +29,7 @@
 #include <shim_handle.h>
 #include <shim_ipc.h>
 #include <shim_checkpoint.h>
+#include <shim_unistd.h>
 #include <shim_profile.h>
 
 #include <pal.h>
@@ -642,112 +643,90 @@ int ipc_checkpoint_callback (IPC_CALLBACK_ARGS)
     if (ret < 0)
         goto out;
 
-    kill_all_threads(NULL, CHECKPOINT_REQUESTED, SIGINT);
+    kill_all_threads(NULL, msgin->cpsession, SIGCP);
     broadcast_ipc(msg, &port, 1, IPC_PORT_DIRPRT|IPC_PORT_DIRCLD);
 out:
     SAVE_PROFILE_INTERVAL(ipc_checkpoint_callback);
     return ret;
 }
 
-DEFINE_MIGRATE_FUNC(ipc_info)
-
-MIGRATE_FUNC_BODY(ipc_info)
+BEGIN_CP_FUNC(ipc_info)
 {
     assert(size == sizeof(struct shim_ipc_info));
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset,
-                                           sizeof(struct shim_ipc_info));
-
     struct shim_ipc_info * port = (struct shim_ipc_info *) obj;
     struct shim_ipc_info * new_port = NULL;
 
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_ipc_info));
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-        if (!dry) {
-            new_port = (struct shim_ipc_info *) (base + off);
-            *new_port = *port;
-            REF_SET(new_port->ref_count, 0);
-        }
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_ipc_info));
 
-        ADD_ENTRY(PALHDL, port->pal_handle && port->pal_handle !=
-                  IPC_FORCE_RECONNECT ? off +
-                  offsetof(struct shim_ipc_info, pal_handle) : 0);
+        new_port = (struct shim_ipc_info *) (base + off);
+        memcpy(new_port, port, sizeof(struct shim_ipc_info));
+        REF_SET(new_port->ref_count, 0);
 
-        DO_MIGRATE_IN_MEMBER(qstr, port, new_port, uri, false);
+        DO_CP_IN_MEMBER(qstr, new_port, uri);
 
-    } else if (!dry) {
+        if (port->pal_handle &&
+            port->pal_handle != IPC_FORCE_RECONNECT) {
+            struct shim_palhdl_entry * entry;
+            DO_CP(palhdl, port->pal_handle, &entry);
+            entry->uri = &new_port->uri;
+            entry->phandle = &new_port->pal_handle;
+        }
+    } else {
         new_port = (struct shim_ipc_info *) (base + off);
     }
 
     if (new_port && objp)
         *objp = (void *) new_port;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC_NO_RS(ipc_info)
 
-RESUME_FUNC_BODY(ipc_info)
-{
-    /* do nothing */
-}
-END_RESUME_FUNC
-
-DEFINE_MIGRATE_FUNC(process)
-
-MIGRATE_FUNC_BODY(process)
+BEGIN_CP_FUNC(process)
 {
     assert(size == sizeof(struct shim_process));
 
-    unsigned long off = ADD_TO_MIGRATE_MAP(obj, *offset,
-                                           sizeof(struct shim_process));
-
     struct shim_process * proc = (struct shim_process *) obj;
     struct shim_process * new_proc = NULL;
 
-    if (ENTRY_JUST_CREATED(off)) {
-        off = ADD_OFFSET(sizeof(struct shim_process));
+    ptr_t off = GET_FROM_CP_MAP(obj);
 
-        if (!dry) {
-            new_proc = (struct shim_process *) (base + off);
-            *new_proc = *proc;
-        }
+    if (!off) {
+        off = ADD_CP_OFFSET(sizeof(struct shim_process));
+        ADD_TO_CP_MAP(obj, off);
+
+        new_proc = (struct shim_process *) (base + off);
+        memcpy(new_proc, proc, sizeof(struct shim_process));
 
         if (proc->self)
-            __DO_MIGRATE(ipc_info, proc->self,
-                         &new_proc->self,
-                         true);
+            DO_CP_MEMBER(ipc_info, proc, new_proc, self);
 
         if (proc->parent)
-            __DO_MIGRATE(ipc_info, proc->parent,
-                         &new_proc->parent,
-                         true);
+            DO_CP_MEMBER(ipc_info, proc, new_proc, parent);
 
         for (int i = 0 ; i < TOTAL_NS ; i++)
             if (proc->ns[i])
-                __DO_MIGRATE(ipc_info, proc->ns[i],
-                             &new_proc->ns[i],
-                             true);
-
-        ADD_FUNC_ENTRY(off);
-        ADD_ENTRY(SIZE, sizeof(struct shim_process));
+                DO_CP_MEMBER(ipc_info, proc, new_proc, ns[i]);
 
-    } else if (!dry) {
+        ADD_CP_FUNC_ENTRY(off);
+    } else {
         new_proc = (struct shim_process *) (base + off);
     }
 
-    if (new_proc && objp)
+    if (objp)
         *objp = (void *) new_proc;
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(process)
 
-RESUME_FUNC_BODY(process)
+BEGIN_RS_FUNC(process)
 {
-    unsigned long off = GET_FUNC_ENTRY();
-    assert((size_t) GET_ENTRY(SIZE) == sizeof(struct shim_process));
-    struct shim_process * proc = (struct shim_process *) (base + off);
+    struct shim_process * proc = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    RESUME_REBASE(proc->self);
-    RESUME_REBASE(proc->parent);
-    RESUME_REBASE(proc->ns);
+    CP_REBASE(proc->self);
+    CP_REBASE(proc->parent);
+    CP_REBASE(proc->ns);
 
     if (proc->self) {
         proc->self->vmid = cur_process.vmid;
@@ -765,11 +744,9 @@ RESUME_FUNC_BODY(process)
     memcpy(&cur_process, proc, sizeof(struct shim_process));
     create_lock(cur_process.lock);
 
-#ifdef DEBUG_RESUME
-    debug("process: vmid=%u, uri=%s, parent=%u(%s)\n", proc->vmid,
-          proc->self ? qstrgetstr(&proc->self->uri) : NULL,
-          proc->parent ? proc->parent->vmid : 0,
-          proc->parent ? qstrgetstr(&proc->parent->uri) : NULL);
-#endif
+    DEBUG_RS("vmid=%u,uri=%s,parent=%u(%s)", proc->vmid,
+             proc->self ? qstrgetstr(&proc->self->uri) : "",
+             proc->parent ? proc->parent->vmid : 0,
+             proc->parent ? qstrgetstr(&proc->parent->uri) : "");
 }
-END_RESUME_FUNC
+END_RS_FUNC(process)

+ 28 - 4
LibOS/shim/src/ipc/shim_ipc_child.c

@@ -36,16 +36,25 @@
 
 #include <errno.h>
 
-static int ipc_thread_exit (IDTYPE vmid, IDTYPE tid, unsigned int exitcode)
+static int ipc_thread_exit (IDTYPE vmid, IDTYPE tid, unsigned int exitcode,
+                            unsigned long exit_time)
 {
     assert(vmid != cur_process.vmid);
 
+#ifdef PROFILE
+    if (!exit_time)
+        exit_time = GET_PROFILE_INTERVAL();
+#endif
+
     struct shim_thread * thread = __lookup_thread(tid);
 
     if (thread) {
         int ret = 0;
         //assert(thread->vmid == vmid && !thread->in_vm);
         thread->exit_code = -exitcode;
+#ifdef PROFILE
+        thread->exit_time = exit_time;
+#endif
         ret = thread_exit(thread, false);
         put_thread(thread);
         return ret;
@@ -62,6 +71,9 @@ static int ipc_thread_exit (IDTYPE vmid, IDTYPE tid, unsigned int exitcode)
 
     sthread->is_alive = 0;
     sthread->exit_code = -exitcode;
+#ifdef PROFILE
+    sthread->exit_time = exit_time;
+#endif
     DkEventSet(sthread->exit_event);
     put_simple_thread(sthread);
     return 0;
@@ -162,12 +174,14 @@ static struct shim_ipc_port * get_parent_port (IDTYPE * dest)
     return port;
 }
 
+DEFINE_PROFILE_INTERVAL(ipc_cld_exit_turnaround, ipc);
 DEFINE_PROFILE_INTERVAL(ipc_cld_exit_send, ipc);
 DEFINE_PROFILE_INTERVAL(ipc_cld_exit_callback, ipc);
 
 int ipc_cld_exit_send (IDTYPE tid, unsigned int exitcode)
 {
-    BEGIN_PROFILE_INTERVAL();
+    unsigned long send_time = GET_PROFILE_INTERVAL();
+    BEGIN_PROFILE_INTERVAL_SET(send_time);
     int ret = 0;
 
     struct shim_ipc_msg * msg =
@@ -177,6 +191,9 @@ int ipc_cld_exit_send (IDTYPE tid, unsigned int exitcode)
                 (struct shim_ipc_cld_exit *) &msg->msg;
     msgin->tid = tid;
     msgin->exitcode = exitcode;
+#ifdef PROFILE
+    msgin->time = send_time;
+#endif
 
     debug("ipc broadcast: IPC_CLD_EXIT(%u, %d)\n", tid, exitcode);
 
@@ -187,14 +204,21 @@ int ipc_cld_exit_send (IDTYPE tid, unsigned int exitcode)
 
 int ipc_cld_exit_callback (IPC_CALLBACK_ARGS)
 {
-    BEGIN_PROFILE_INTERVAL();
     struct shim_ipc_cld_exit * msgin =
                 (struct shim_ipc_cld_exit *) &msg->msg;
 
+#ifdef PROFILE
+    unsigned long time = msgin->time;
+#else
+    unsigned long time = 0;
+#endif
+    BEGIN_PROFILE_INTERVAL_SET(time);
+    SAVE_PROFILE_INTERVAL(ipc_cld_exit_turnaround);
+
     debug("ipc callback from %u: IPC_CLD_EXIT(%u, %d)\n",
           msg->src, msgin->tid, msgin->exitcode);
 
-    int ret = ipc_thread_exit(msg->src, msgin->tid, msgin->exitcode);
+    int ret = ipc_thread_exit(msg->src, msgin->tid, msgin->exitcode, time);
     SAVE_PROFILE_INTERVAL(ipc_cld_exit_callback);
     return ret;
 }

+ 1 - 1
LibOS/shim/src/ipc/shim_ipc_helper.c

@@ -755,7 +755,7 @@ static void shim_ipc_helper (void * arg)
         return;
 
     __libc_tcb_t tcb;
-    allocate_tls(&tcb, self);
+    allocate_tls(&tcb, false, self);
     debug_setbuf(&tcb.shim_tcb, true);
     debug("set tcb to %p\n", &tcb);
 

+ 38 - 15
LibOS/shim/src/shim.lds

@@ -7,13 +7,37 @@ SECTIONS
   __load_address = .;
   . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS;
   .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash          : { *(.hash) }
+  .gnu.hash      : { *(.gnu.hash) }
   .dynsym        : { *(.dynsym) }
   .dynstr        : { *(.dynstr) }
   .gnu.version   : { *(.gnu.version) }
   .gnu.version_d : { *(.gnu.version_d) }
   .gnu.version_r : { *(.gnu.version_r) }
-  .rela.dyn      : { *(.rela.*) }
-  .init          : { KEEP(*(.init)) }
+  .rela.dyn       :
+     {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt      :
+    {
+      *(.rela.plt)
+      *(.rela.iplt)
+    }
+  .init          : { *(.init) }
   .plt           : { *(.plt) *(.iplt) }
   .text :
   {
@@ -21,30 +45,29 @@ SECTIONS
     __code_address = .;
     *(.text .stub .text.*);
     . = ALIGN(8);
-    __migrate_name = .;
-    SORT(*)(SORT(.migrate_name.*));
-    __migrate_func = .;
-    SORT(*)(SORT(.migrate.*));
-    __resume_func = .;
-    SORT(*)(SORT(.resume.*));
+    __cp_name = .;
+    SORT(*)(SORT(.cp_name.*));
+    __cp_func = .;
+    SORT(*)(SORT(.cp_func.*));
+    __rs_func = .;
+    SORT(*)(SORT(.rs_func.*));
     __code_address_end = .;
   }
-  .fini          : { KEEP(*(.fini)) }
+  .fini          : { *(.fini) }
   .rodata :
   {
     /* the rest of rodata */
     *(.rodata .rodata.*)
   }
   .eh_frame_hdr  : { *(.eh_frame_hdr) }
-  .eh_frame      : ONLY_IF_RO { KEEP(*(.eh_frame)) }
-  .hash          : { *(.hash) }
+  .eh_frame      : ONLY_IF_RO { *(.eh_frame) }
 
   /* now adjust the address for the data segment */
   . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
-  .eh_frame      : ONLY_IF_RW { KEEP(*(.eh_frame)) }
-  .ctors         : { KEEP(*(.ctors)) }
-  .dtors         : { KEEP(*(.dtors)) }
-  .jcr           : { KEEP(*(.jcr)) }
+  .eh_frame      : ONLY_IF_RW { *(.eh_frame) }
+  .ctors         : { *(.ctors) }
+  .dtors         : { *(.dtors) }
+  .jcr           : { *(.jcr) }
   .dynamic       : { *(.dynamic) }
   .got           : { *(.got) *(.igot) }
   .got.plt       : { *(.got.plt) *(.igot.plt) }

+ 1 - 1
LibOS/shim/src/shim_async.c

@@ -107,7 +107,7 @@ static void shim_async_helper (void * arg)
         return;
 
     __libc_tcb_t tcb;
-    allocate_tls(&tcb, self);
+    allocate_tls(&tcb, false, self);
     debug_setbuf(&tcb.shim_tcb, true);
     debug("set tcb to %p\n", &tcb);
 

File diff suppressed because it is too large
+ 519 - 383
LibOS/shim/src/shim_checkpoint.c


+ 38 - 29
LibOS/shim/src/shim_debug.c

@@ -34,7 +34,24 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
+#ifndef DEBUG
+
+void clean_link_map_list (void)
+{
+    /* do nothing */
+}
+
+void remove_r_debug (void * addr)
+{
+    /* do nothing */
+}
+
+void append_r_debug (const char * uri, void * addr, void * dyn_addr)
+{
+    /* do nothing */
+}
+
+#else /* !DEBUG */
 
 struct gdb_link_map
 {
@@ -113,43 +130,35 @@ void append_r_debug (const char * uri, void * addr, void * dyn_addr)
     DkDebugAttachBinary(uri, addr);
 }
 
-DEFINE_MIGRATE_FUNC(gdb_map)
-
-MIGRATE_FUNC_BODY(gdb_map)
+BEGIN_CP_FUNC(gdb_map)
 {
     struct gdb_link_map *m = link_map_list;
     struct gdb_link_map *newm = NULL;
 
     while (m) {
-        unsigned long off = ADD_OFFSET(sizeof(struct gdb_link_map));
-
-        if (!dry) {
-            newm = (struct gdb_link_map *) (base + off);
-            memcpy(newm, m, sizeof(struct gdb_link_map));
-            newm->l_prev = newm->l_next = NULL;
-        }
+        ptr_t off = ADD_CP_OFFSET(sizeof(struct gdb_link_map));
+        newm = (struct gdb_link_map *) (base + off);
 
-        ADD_OFFSET(strlen(m->l_name) + 1);
+        memcpy(newm, m, sizeof(struct gdb_link_map));
+        newm->l_prev = newm->l_next = NULL;
 
-        if (!dry) {
-            newm->l_name = (char *) (base + *offset);
-            memcpy(newm->l_name, m->l_name, strlen(m->l_name) + 1);
-        }
+        int len = strlen(newm->l_name);
+        newm->l_name = (char *) (base + ADD_CP_OFFSET(len + 1));
+        memcpy(newm->l_name, m->l_name, len + 1);
 
-        ADD_FUNC_ENTRY(off);
+        ADD_CP_FUNC_ENTRY(off);
         m = m->l_next;
     }
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(gdb_map)
 
-RESUME_FUNC_BODY(gdb_map)
+BEGIN_RS_FUNC(gdb_map)
 {
-    uint64_t off = GET_FUNC_ENTRY();
-    struct gdb_link_map *map = (struct gdb_link_map *) (base + off);
+    struct gdb_link_map * map = (void *) (base + GET_CP_FUNC_ENTRY());
 
-    RESUME_REBASE(map->l_name);
-    RESUME_REBASE(map->l_prev);
-    RESUME_REBASE(map->l_next);
+    CP_REBASE(map->l_name);
+    CP_REBASE(map->l_prev);
+    CP_REBASE(map->l_next);
 
     struct gdb_link_map *prev = NULL;
     struct gdb_link_map **tail = &link_map_list;
@@ -162,10 +171,10 @@ RESUME_FUNC_BODY(gdb_map)
     map->l_prev = prev;
     *tail = map;
 
-#ifdef DEBUG_RESUME
-    debug("gdb: %s loaded at %p\n", map->l_name, map->l_addr);
-#endif
-
     DkDebugAttachBinary(map->l_name, map->l_addr);
+
+    DEBUG_RS("base=%p,name=%s", map->l_addr, map->l_name);
 }
-END_RESUME_FUNC
+END_RS_FUNC(gdb_map)
+
+#endif

+ 56 - 66
LibOS/shim/src/shim_init.c

@@ -103,21 +103,19 @@ long convert_pal_errno (long err)
            pal_errno_to_unix_errno[err] : 0;
 }
 
-void * initial_stack = NULL;
-const char ** initial_envp __attribute_migratable = NULL;
+void * migrated_memory_start;
+void * migrated_memory_end;
+void * migrated_shim_addr;
 
-void * migrated_memory_start = 0;
-void * migrated_memory_end = 0;
+void * initial_stack;
+const char ** initial_envp __attribute_migratable;
 
-extern void * migrated_shim_addr;
-
-const char ** library_paths = NULL;
-
-bool in_gdb = false;
+const char ** library_paths;
 
 LOCKTYPE __master_lock;
+bool lock_enabled;
 
-bool lock_enabled = false;
+bool in_gdb;
 
 void init_tcb (shim_tcb_t * tcb)
 {
@@ -137,7 +135,7 @@ void copy_tcb (shim_tcb_t * new_tcb, const shim_tcb_t * old_tcb)
 }
 
 /* This function is used to allocate tls before interpreter start running */
-void allocate_tls (void * tcb_location, struct shim_thread * thread)
+void allocate_tls (void * tcb_location, bool user, struct shim_thread * thread)
 {
     __libc_tcb_t * tcb = tcb_location;
     assert(tcb);
@@ -146,7 +144,7 @@ void allocate_tls (void * tcb_location, struct shim_thread * thread)
 
     if (thread) {
         thread->tcb       = tcb;
-        thread->user_tcb  = false;
+        thread->user_tcb  = user;
         tcb->shim_tcb.tp  = thread;
         tcb->shim_tcb.tid = thread->tid;
     } else {
@@ -178,7 +176,7 @@ void populate_tls (void * tcb_location, bool user)
 DEFINE_PROFILE_OCCURENCE(alloc_stack, memory);
 DEFINE_PROFILE_OCCURENCE(alloc_stack_count, memory);
 
-#define STACK_FLAGS     (MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL)
+#define STACK_FLAGS     (MAP_PRIVATE|MAP_ANONYMOUS)
 
 void * allocate_stack (size_t size, size_t protect_size, bool user)
 {
@@ -389,8 +387,6 @@ static void __free (void * mem)
     free(mem);
 }
 
-extern bool ask_for_checkpoint;
-
 int init_manifest (PAL_HANDLE manifest_handle)
 {
     PAL_STREAM_ATTR attr;
@@ -421,13 +417,6 @@ int init_manifest (PAL_HANDLE manifest_handle)
         return ret;
     }
 
-    char cfgbuf[CONFIG_MAX];
-
-    if (get_config(root_config, "sys.ask_for_checkpoint", cfgbuf,
-                   CONFIG_MAX) > 0 &&
-        cfgbuf[0] == '1' && !cfgbuf[1])
-        ask_for_checkpoint = true;
-
     return 0;
 }
 
@@ -523,61 +512,58 @@ static void set_profile_enabled (const char ** envp)
 }
 #endif
 
-DEFINE_PROFILE_CATAGORY(resume, );
-DEFINE_PROFILE_INTERVAL(child_created_in_new_process, resume);
-DEFINE_PROFILE_INTERVAL(child_receive_header, resume);
-DEFINE_PROFILE_INTERVAL(child_total_migration_time, resume);
-
 static int init_newproc (struct newproc_header * hdr)
 {
+    BEGIN_PROFILE_INTERVAL();
+
     int bytes = DkStreamRead(PAL_CB(parent_process), 0,
                              sizeof(struct newproc_header), hdr,
                              NULL, 0);
     if (!bytes)
         return -PAL_ERRNO;
 
+    SAVE_PROFILE_INTERVAL(child_wait_header);
     SAVE_PROFILE_INTERVAL_SINCE(child_receive_header, hdr->write_proc_time);
     return hdr->failure;
 }
 
 DEFINE_PROFILE_CATAGORY(pal, );
-DEFINE_PROFILE_INTERVAL(pal_startup_time, pal);
+DEFINE_PROFILE_INTERVAL(pal_startup_time,               pal);
 DEFINE_PROFILE_INTERVAL(pal_host_specific_startup_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_relocation_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_linking_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_manifest_loading_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_allocation_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_tail_startup_time, pal);
-DEFINE_PROFILE_INTERVAL(pal_child_creation_time, pal);
+DEFINE_PROFILE_INTERVAL(pal_relocation_time,            pal);
+DEFINE_PROFILE_INTERVAL(pal_linking_time,               pal);
+DEFINE_PROFILE_INTERVAL(pal_manifest_loading_time,      pal);
+DEFINE_PROFILE_INTERVAL(pal_allocation_time,            pal);
+DEFINE_PROFILE_INTERVAL(pal_tail_startup_time,          pal);
+DEFINE_PROFILE_INTERVAL(pal_child_creation_time,        pal);
 
 DEFINE_PROFILE_CATAGORY(init, );
-DEFINE_PROFILE_INTERVAL(init_randgen, init);
-DEFINE_PROFILE_INTERVAL(init_heap, init);
-DEFINE_PROFILE_INTERVAL(init_slab, init);
-DEFINE_PROFILE_INTERVAL(init_str_mgr, init);
-DEFINE_PROFILE_INTERVAL(init_internal_map, init);
-DEFINE_PROFILE_INTERVAL(init_vma, init);
-DEFINE_PROFILE_INTERVAL(init_fs, init);
-DEFINE_PROFILE_INTERVAL(init_handle, init);
-DEFINE_PROFILE_INTERVAL(read_from_checkpoint, init);
-DEFINE_PROFILE_INTERVAL(read_from_file, init);
-DEFINE_PROFILE_INTERVAL(init_newproc, init);
-DEFINE_PROFILE_INTERVAL(do_migration, init);
-DEFINE_PROFILE_INTERVAL(init_mount_root, init);
-DEFINE_PROFILE_INTERVAL(init_from_checkpoint_file, init);
-DEFINE_PROFILE_INTERVAL(restore_from_file, init);
-DEFINE_PROFILE_INTERVAL(restore_checkpoint, init);
-DEFINE_PROFILE_INTERVAL(init_manifest, init);
-DEFINE_PROFILE_INTERVAL(init_ipc, init);
-DEFINE_PROFILE_INTERVAL(init_thread, init);
-DEFINE_PROFILE_INTERVAL(init_important_handles, init);
-DEFINE_PROFILE_INTERVAL(init_mount, init);
-DEFINE_PROFILE_INTERVAL(init_async, init);
-DEFINE_PROFILE_INTERVAL(init_stack, init);
-DEFINE_PROFILE_INTERVAL(read_environs, init);
-DEFINE_PROFILE_INTERVAL(init_loader, init);
-DEFINE_PROFILE_INTERVAL(init_ipc_helper, init);
-DEFINE_PROFILE_INTERVAL(init_signal, init);
+DEFINE_PROFILE_INTERVAL(init_randgen,               init);
+DEFINE_PROFILE_INTERVAL(init_heap,                  init);
+DEFINE_PROFILE_INTERVAL(init_slab,                  init);
+DEFINE_PROFILE_INTERVAL(init_str_mgr,               init);
+DEFINE_PROFILE_INTERVAL(init_internal_map,          init);
+DEFINE_PROFILE_INTERVAL(init_vma,                   init);
+DEFINE_PROFILE_INTERVAL(init_fs,                    init);
+DEFINE_PROFILE_INTERVAL(init_dcache,                init);
+DEFINE_PROFILE_INTERVAL(init_handle,                init);
+DEFINE_PROFILE_INTERVAL(read_from_checkpoint,       init);
+DEFINE_PROFILE_INTERVAL(read_from_file,             init);
+DEFINE_PROFILE_INTERVAL(init_newproc,               init);
+DEFINE_PROFILE_INTERVAL(init_mount_root,            init);
+DEFINE_PROFILE_INTERVAL(init_from_checkpoint_file,  init);
+DEFINE_PROFILE_INTERVAL(restore_from_file,          init);
+DEFINE_PROFILE_INTERVAL(init_manifest,              init);
+DEFINE_PROFILE_INTERVAL(init_ipc,                   init);
+DEFINE_PROFILE_INTERVAL(init_thread,                init);
+DEFINE_PROFILE_INTERVAL(init_important_handles,     init);
+DEFINE_PROFILE_INTERVAL(init_mount,                 init);
+DEFINE_PROFILE_INTERVAL(init_async,                 init);
+DEFINE_PROFILE_INTERVAL(init_stack,                 init);
+DEFINE_PROFILE_INTERVAL(read_environs,              init);
+DEFINE_PROFILE_INTERVAL(init_loader,                init);
+DEFINE_PROFILE_INTERVAL(init_ipc_helper,            init);
+DEFINE_PROFILE_INTERVAL(init_signal,                init);
 
 #define CALL_INIT(func, args ...)   func(args)
 
@@ -594,7 +580,7 @@ DEFINE_PROFILE_INTERVAL(init_signal, init);
 
 extern PAL_HANDLE thread_start_event;
 
-int shim_init (int argc, void * args)
+int shim_init (int argc, void * args, void ** return_stack)
 {
     debug_handle = PAL_CB(debug_stream);
     cur_process.vmid = (IDTYPE) PAL_CB(process_id);
@@ -602,7 +588,7 @@ int shim_init (int argc, void * args)
     /* 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);
+    allocate_tls(&tcb, false, NULL);
     debug_setbuf(&tcb.shim_tcb, true);
     debug("set tcb to %p\n", &tcb);
 
@@ -645,6 +631,7 @@ int shim_init (int argc, void * args)
     RUN_INIT(init_internal_map);
     RUN_INIT(init_vma);
     RUN_INIT(init_fs);
+    RUN_INIT(init_dcache);
     RUN_INIT(init_handle);
 
     debug("shim loaded at %p, ready to initialize\n", &__load_address);
@@ -669,14 +656,16 @@ int shim_init (int argc, void * args)
         begin_create_time = hdr.begin_create_time;
 #endif
 
-        if (hdr.checkpoint.data.cpsize)
+        if (hdr.checkpoint.hdr.size)
             RUN_INIT(do_migration, &hdr.checkpoint, &cpaddr);
     }
 
     if (cpaddr) {
 restore:
         thread_start_event = DkNotificationEventCreate(0);
-        RUN_INIT(restore_checkpoint, cpaddr, &hdr.checkpoint.data, 0);
+        RUN_INIT(restore_checkpoint,
+                 &hdr.checkpoint.hdr, &hdr.checkpoint.mem,
+                 (ptr_t) cpaddr, 0);
     }
 
     if (PAL_CB(manifest_handle))
@@ -730,6 +719,7 @@ restore:
         execute_elf_object(cur_thread->exec,
                            argc, argp, nauxv, auxp);
 
+    *return_stack = initial_stack;
     return 0;
 }
 
@@ -1008,7 +998,7 @@ static void print_profile_result (PAL_HANDLE hdl, struct shim_profile * root,
         }
     }
     if (total_interval_count) {
-        __sys_fprintf(hdl, "- (%11.11u) total: %u times, %lu msec\n",
+        __sys_fprintf(hdl, "                - (%11.11u) total: %u times, %lu msec\n",
                       total_interval_time, total_interval_count, 
                       total_interval_time / total_interval_count);
     }

+ 13 - 15
LibOS/shim/src/shim_parser.c

@@ -33,15 +33,22 @@
 #include <pal.h>
 #include <pal_error.h>
 
+#include <errno.h>
+
+#include <asm/fcntl.h>
 #include <asm/unistd.h>
 #include <asm/prctl.h>
 #include <asm/mman.h>
 #include <asm/ioctls.h>
+
+#include <linux/stat.h>
+#include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/futex.h>
 #include <linux/wait.h>
-#include <errno.h>
-#include <fcntl.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/un.h>
 
 static void parse_open_flags    (const char *, va_list);
 static void parse_open_mode     (const char *, va_list);
@@ -580,10 +587,6 @@ static void parse_open_flags (const char * type, va_list ap)
         PUTS("|O_TRUNC");
         flags &= ~O_TRUNC;
     }
-    if (flags & O_ASYNC) {
-        PUTS("|O_ASYNC");
-        flags &= ~O_ASYNC;
-    }
     if (flags & O_EXCL) {
         PUTS("|O_EXCL");
         flags &= ~O_EXCL;
@@ -793,14 +796,12 @@ static void parse_signum (const char * type, va_list ap)
     unsigned int signum = va_arg (ap, unsigned int);
 
     if (signum > 0 && signum <= NUM_KNOWN_SIGS)
-        PUTS(siglist[signum]);
-    else
-        PRINTF("Signal %u", signum);
+        PUTS(signal_name(signum));
 }
 
 static void parse_sigmask (const char * type, va_list ap)
 {
-    sigset_t * sigset = va_arg (ap, sigset_t *);
+    __sigset_t * sigset = va_arg(ap, __sigset_t *);
 
     if (!sigset) {
         PUTS("NULL");
@@ -811,11 +812,8 @@ static void parse_sigmask (const char * type, va_list ap)
 
     for (int signum = 1 ; signum <= sizeof(sigset) * 8 ; signum++)
         if (__sigismember(sigset, signum)) {
-            if (signum <= NUM_KNOWN_SIGS) {
-                PUTS(siglist[signum]);
-                PUTS(",");
-            } else
-                PRINTF("Signal %u,", signum);
+            PUTS(signal_name(signum));
+            PUTS(",");
         }
 
     PUTS("]");

+ 12 - 11
LibOS/shim/src/shim_syscalls.c

@@ -202,7 +202,7 @@ DEFINE_SHIM_SYSCALL (rt_sigaction, 3, shim_do_sigaction, int, int, signum,
 
 /* rt_sigprocmask: sys/shim_sigaction.c */
 DEFINE_SHIM_SYSCALL (rt_sigprocmask, 3, shim_do_sigprocmask, int, int, how,
-                     const sigset_t *, set, sigset_t *, oldset)
+                     const __sigset_t *, set, __sigset_t *, oldset)
 
 /* rt_sigreturn: sys/shim_sigaction.c */
 DEFINE_SHIM_SYSCALL (rt_sigreturn, 1, shim_do_sigreturn, int, int, __unused)
@@ -577,17 +577,17 @@ SHIM_SYSCALL_PASSTHROUGH (capget, 2, int, cap_user_header_t, header,
 SHIM_SYSCALL_PASSTHROUGH (capset, 2, int, cap_user_header_t, header,
                           const cap_user_data_t, data)
 
-SHIM_SYSCALL_PASSTHROUGH (rt_sigpending, 2, int, sigset_t *, set, size_t,
+SHIM_SYSCALL_PASSTHROUGH (rt_sigpending, 2, int, __sigset_t *, set, size_t,
                           sigsetsize)
 
-SHIM_SYSCALL_PASSTHROUGH (rt_sigtimedwait, 4, int, const sigset_t *, uthese,
+SHIM_SYSCALL_PASSTHROUGH (rt_sigtimedwait, 4, int, const __sigset_t *, uthese,
                           siginfo_t *, uinfo, const struct timespec *, uts,
                           size_t, sigsetsize)
 
 SHIM_SYSCALL_PASSTHROUGH (rt_sigqueueinfo, 3, int, int, pid, int, sig,
                           siginfo_t *, uinfo)
 
-SHIM_SYSCALL_PASSTHROUGH (rt_sigsuspend, 1, int, const sigset_t *, mask)
+SHIM_SYSCALL_PASSTHROUGH (rt_sigsuspend, 1, int, const __sigset_t *, mask)
 
 SHIM_SYSCALL_PASSTHROUGH (sigaltstack, 2, int, const stack_t *, ss, stack_t *,
                           oss)
@@ -602,7 +602,8 @@ SHIM_SYSCALL_PASSTHROUGH (uselib, 1, int, const char *, library)
 
 SHIM_SYSCALL_PASSTHROUGH (personality, 1, int, unsigned int, personality)
 
-SHIM_SYSCALL_PASSTHROUGH (ustat, 2, int, unsigned, dev, struct ustat *, ubuf)
+SHIM_SYSCALL_PASSTHROUGH (ustat, 2, int, unsigned, dev,
+                          struct __kernel_ustat *, ubuf)
 
 SHIM_SYSCALL_PASSTHROUGH (statfs, 2, int, const char *, path, struct statfs *,
                           buf)
@@ -808,7 +809,7 @@ SHIM_SYSCALL_PASSTHROUGH (fremovexattr, 2, int, int, fd, const char *, name)
 
 DEFINE_SHIM_SYSCALL (tkill, 2, shim_do_tkill, int, pid_t, pid, int, sig)
 
-DEFINE_SHIM_SYSCALL (time, 1, shim_do_time, int, time_t *, tloc)
+DEFINE_SHIM_SYSCALL (time, 1, shim_do_time, time_t, time_t *, tloc)
 
 /* futex: sys/shim_futex.c */
 DEFINE_SHIM_SYSCALL (futex, 6, shim_do_futex, int, unsigned int *, uaddr,
@@ -1048,12 +1049,12 @@ DEFINE_SHIM_SYSCALL (faccessat, 3, shim_do_faccessat, int, int, dfd,
 DEFINE_SHIM_SYSCALL (pselect6, 6, shim_do_pselect6, int, int, nfds,
                      fd_set *, readfds, fd_set *, writefds, fd_set *, errorfds,
                      const struct __kernel_timespec *, tsp,
-                     const sigset_t *, sigmask)
+                     const __sigset_t *, sigmask)
 
 /* ppoll: sys/shim_poll.c */
 DEFINE_SHIM_SYSCALL (ppoll, 5, shim_do_ppoll, int, struct pollfd *, fds,
                      int, nfds, struct timespec *, tsp,
-                     const sigset_t *, sigmask, size_t, sigsetsize)
+                     const __sigset_t *, sigmask, size_t, sigsetsize)
 
 SHIM_SYSCALL_PASSTHROUGH (unshare, 1, int, int, unshare_flags)
 
@@ -1086,10 +1087,10 @@ SHIM_SYSCALL_PASSTHROUGH (utimensat, 4, int, int, dfd, const char *, filename,
 
 DEFINE_SHIM_SYSCALL (epoll_pwait, 6, shim_do_epoll_pwait, int, int, epfd,
                           struct __kernel_epoll_event *, events, int, maxevents,
-                          int, timeout, const sigset_t *, sigmask,
+                          int, timeout, const __sigset_t *, sigmask,
                           size_t, sigsetsize)
 
-SHIM_SYSCALL_PASSTHROUGH (signalfd, 3, int, int, ufd, sigset_t *, user_mask,
+SHIM_SYSCALL_PASSTHROUGH (signalfd, 3, int, int, ufd, __sigset_t *, user_mask,
                           size_t, sizemask)
 
 SHIM_SYSCALL_PASSTHROUGH (timerfd_create, 2, int, int, clockid, int, flags)
@@ -1110,7 +1111,7 @@ SHIM_SYSCALL_PASSTHROUGH (timerfd_gettime, 2, int, int, ufd,
 DEFINE_SHIM_SYSCALL (accept4, 4, shim_do_accept4, int, int, sockfd,
                      struct sockaddr *, addr, socklen_t *, addrlen, int, flags)
 
-SHIM_SYSCALL_PASSTHROUGH (signalfd4, 4, int, int, ufd, sigset_t *, user_mask,
+SHIM_SYSCALL_PASSTHROUGH (signalfd4, 4, int, int, ufd, __sigset_t *, user_mask,
                           size_t, sizemask, int, flags)
 
 SHIM_SYSCALL_PASSTHROUGH (eventfd2, 2, int, int, count, int, flags)

+ 8 - 1
LibOS/shim/src/start.S

@@ -37,6 +37,7 @@ shim_start:
    The arguments are passed via registers and on the stack:
    argc:         %rdi
    argv:         %rsi
+   stack:        %rdx
 */
 
     /* Align the stack to a 16 byte boundary to follow the ABI.  */
@@ -46,10 +47,16 @@ shim_start:
     movq 0(%rbp), %rdi      /* Pop the argument count.  */
     leaq 8(%rbp), %rsi      /* argv starts just at the current stack top.  */
 
-    pushq %rdx
+/* Provide the highest stack address to the user code (for stacks
+   which grow downwards).  */
+
+    pushq %rbp
+    movq %rsp, %rdx
 
     movq shim_init@GOTPCREL(%rip), %r11
     call *%r11
 
+    popq %rbp
+    leaveq
     retq
     .cfi_endproc

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

@@ -37,7 +37,7 @@ void signal_alarm (IDTYPE target, void * arg)
     if (!thread)
         return;
 
-    append_signal(thread, SIGALRM, NULL);
+    append_signal(thread, SIGALRM, NULL, true);
 }
 
 int shim_do_alarm (unsigned int seconds)

+ 14 - 18
LibOS/shim/src/sys/shim_brk.c

@@ -170,26 +170,24 @@ out:
     return brk;
 }
 
-DEFINE_MIGRATE_FUNC(brk)
-
-MIGRATE_FUNC_BODY(brk)
+BEGIN_CP_FUNC(brk)
 {
     if (region.brk_start) {
-        ADD_FUNC_ENTRY(region.brk_start);
-        ADD_ENTRY(ADDR, region.brk_current);
-        ADD_ENTRY(SIZE, region.brk_end - region.brk_start);
+        ADD_CP_FUNC_ENTRY(region.brk_start);
+        ADD_CP_ENTRY(ADDR, region.brk_current);
+        ADD_CP_ENTRY(SIZE, region.brk_end - region.brk_start);
         assert(brk_max_size);
-        ADD_ENTRY(SIZE, brk_max_size);
+        ADD_CP_ENTRY(SIZE, brk_max_size);
     }
 }
-END_MIGRATE_FUNC
+END_CP_FUNC(bek)
 
-RESUME_FUNC_BODY(brk)
+BEGIN_RS_FUNC(brk)
 {
-    region.brk_start   = (void *) GET_FUNC_ENTRY();
-    region.brk_current = (void *) GET_ENTRY(ADDR);
-    region.brk_end     = region.brk_start + GET_ENTRY(SIZE);
-    brk_max_size       = GET_ENTRY(SIZE);
+    region.brk_start   = (void *) GET_CP_FUNC_ENTRY();
+    region.brk_current = (void *) GET_CP_ENTRY(ADDR);
+    region.brk_end     = region.brk_start + GET_CP_ENTRY(SIZE);
+    brk_max_size       = GET_CP_ENTRY(SIZE);
 
     debug("brk area: %p - %p\n", region.brk_start, region.brk_end);
 
@@ -214,9 +212,7 @@ RESUME_FUNC_BODY(brk)
                    NULL);
     }
 
-#ifdef DEBUG_RESUME
-    debug("brk: %p in %p - %p\n", region.brk_current, region.brk_start,
-          region.brk_end);
-#endif
+    DEBUG_RS("current=%p,region=%p-%p", region.brk_current, region.brk_start,
+             region.brk_end);
 }
-END_RESUME_FUNC
+END_RS_FUNC(brk)

+ 3 - 3
LibOS/shim/src/sys/shim_clone.c

@@ -107,7 +107,7 @@ int clone_implementation_wrapper(struct clone_args * arg)
 
     if (!my_thread->tcb)
         my_thread->tcb = __alloca(sizeof(__libc_tcb_t));
-    allocate_tls(my_thread->tcb, my_thread);
+    allocate_tls(my_thread->tcb, my_thread->user_tcb, my_thread);
     shim_tcb_t * tcb = &((__libc_tcb_t *) my_thread->tcb)->shim_tcb;
     debug_setbuf(tcb, true);
     debug("set tcb to %p\n", my_thread->tcb);
@@ -148,8 +148,8 @@ int clone_implementation_wrapper(struct clone_args * arg)
 }
 
 int migrate_fork (struct shim_cp_store * cpstore,
-                  struct shim_process * process,
-                  struct shim_thread * thread, va_list ap);
+                  struct shim_thread * thread,
+                  struct shim_process * process, va_list ap);
 
 /*  long int __arg0 - flags
  *  long int __arg1 - 16 bytes ( 2 words ) offset into the child stack allocated

+ 0 - 1
LibOS/shim/src/sys/shim_dup.c

@@ -33,7 +33,6 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
 #include <errno.h>
 
 int shim_do_dup (int fd)

+ 14 - 3
LibOS/shim/src/sys/shim_epoll.c

@@ -34,8 +34,19 @@
 #include <pal_error.h>
 
 #include <errno.h>
-#include <sys/epoll.h>
-#include <sys/poll.h>
+
+#include <linux/eventpoll.h>
+
+#define EPOLLIN         0x001
+#define EPOLLPRI        0x002
+#define EPOLLOUT        0x004
+#define EPOLLRDNORM     0x040
+#define EPOLLRDBAND     0x080
+#define EPOLLWRNORM     0x100
+#define EPOLLERBAND     0x200
+#define EPOLLERR        0x008
+#define EPOLLHUP        0x010
+#define EPOLLRDHUP      0x2000
 
 #define MAX_EPOLL_FDS       1024
 
@@ -292,7 +303,7 @@ reply:
 }
 
 int shim_do_epoll_pwait (int epfd, struct __kernel_epoll_event * events,
-                         int maxevents, int timeout, const sigset_t * sigmask,
+                         int maxevents, int timeout, const __sigset_t * sigmask,
                          size_t sigsetsize)
 {
     int ret = shim_do_epoll_wait (epfd, events, maxevents, timeout);

+ 129 - 59
LibOS/shim/src/sys/shim_exec.c

@@ -33,12 +33,13 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
+#include <errno.h>
+
+#include <linux/futex.h>
+
 #include <sys/syscall.h>
 #include <sys/mman.h>
 #include <asm/prctl.h>
-#include <linux/futex.h>
-#include <errno.h>
 
 static int close_cloexec_handle (struct shim_handle_map * map)
 {
@@ -118,7 +119,7 @@ int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
 
     DkVirtualMemoryFree(old_stack, old_stack_top - old_stack);
     DkVirtualMemoryFree(old_stack_red, old_stack - old_stack_red);
-    int flags = VMA_INTERNAL;
+    int flags = 0;
     bkeep_munmap(old_stack, old_stack_top - old_stack, &flags);
     bkeep_munmap(old_stack_red, old_stack - old_stack_red, &flags);
 
@@ -139,6 +140,11 @@ int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
 
     cur_thread->robust_list = NULL;
 
+#ifdef PROFILE
+    if (ENTER_TIME)
+        SAVE_PROFILE_INTERVAL_SINCE(syscall_execve, ENTER_TIME);
+#endif
+
     debug("execve: start execution\n");
     execute_elf_object(cur_thread->exec, new_argc, new_argp,
                        REQUIRED_ELF_AUXV, new_auxp);
@@ -146,22 +152,6 @@ int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
     return 0;
 }
 
-static void * __malloc (size_t size)
-{
-    int flags = MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL;
-    size = ALIGN_UP(size);
-    void * addr = get_unmapped_vma(size, flags);
-
-    addr = (void *)
-        DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
-    if (!addr)
-        return NULL;
-
-    bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
-    return addr;
-}
-
-#define malloc_method __malloc
 #include <shim_checkpoint.h>
 
 DEFINE_PROFILE_CATAGORY(exec, );
@@ -170,13 +160,12 @@ DEFINE_PROFILE_INTERVAL(open_file_for_exec, exec);
 DEFINE_PROFILE_INTERVAL(close_CLOEXEC_files_for_exec, exec);
 
 static int migrate_execve (struct shim_cp_store * cpstore,
-                           struct shim_process * process,
-                           struct shim_thread * thread, va_list ap)
+                           struct shim_thread * thread,
+                           struct shim_process * process, va_list ap)
 {
-    struct shim_handle_map * handle_map = NULL;
+    struct shim_handle_map * handle_map;
+    const char ** envp = va_arg(ap, const char **);
     int ret;
-    const char ** envp = va_arg (ap, const char **);
-    size_t envsize = va_arg (ap, size_t);
 
     BEGIN_PROFILE_INTERVAL();
 
@@ -196,23 +185,22 @@ static int migrate_execve (struct shim_cp_store * cpstore,
             2. cur_threadrent filesystem
             3. handle mapping
             4. each handle              */
-    BEGIN_MIGRATION_DEF(execve, struct shim_process * proc,
+    BEGIN_MIGRATION_DEF(execve,
                         struct shim_thread * thread,
-                        const char ** envp, size_t envsize)
+                        struct shim_process * proc,
+                        const char ** envp)
     {
-        store->use_gipc = true;
-        DEFINE_MIGRATE(process, proc, sizeof(struct shim_process), false);
-        DEFINE_MIGRATE(all_mounts, NULL, 0, false);
-        DEFINE_MIGRATE(running_thread, thread, sizeof(struct shim_thread),
-                       false);
+        DEFINE_MIGRATE(process, proc, sizeof(struct shim_process));
+        DEFINE_MIGRATE(all_mounts, NULL, 0);
+        DEFINE_MIGRATE(running_thread, thread, sizeof(struct shim_thread));
         DEFINE_MIGRATE(handle_map, thread->handle_map,
-                       sizeof (struct shim_handle_map), true);
-        DEFINE_MIGRATE(migratable, NULL, 0, false);
-        DEFINE_MIGRATE(environ, envp, envsize, true);
+                       sizeof (struct shim_handle_map));
+        DEFINE_MIGRATE(migratable, NULL, 0);
+        DEFINE_MIGRATE(environ, envp, 0);
     }
-    END_MIGRATION_DEF
+    END_MIGRATION_DEF(execve)
 
-    return START_MIGRATE(cpstore, execve, 0, process, thread, envp, envsize);
+    return START_MIGRATE(cpstore, execve, thread, process, envp);
 }
 
 int shim_do_execve (const char * file, const char ** argv,
@@ -220,13 +208,24 @@ int shim_do_execve (const char * file, const char ** argv,
 {
     struct shim_thread * cur_thread = get_cur_thread();
     struct shim_dentry * dent = NULL;
-    int ret = 0;
+    int ret = 0, argc = 0;
+
+    for (const char ** a = argv ; *a ; a++, argc++);
 
     if (!envp)
         envp = initial_envp;
 
     BEGIN_PROFILE_INTERVAL();
 
+    LIST_HEAD(shargs);
+    struct sharg {
+        struct list_head list;
+        int len;
+        char arg[0];
+    };
+
+reopen:
+
     if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent)) < 0)
         return ret;
 
@@ -241,7 +240,7 @@ err:
     }
 
     if (fs->d_ops->mode) {
-        mode_t mode;
+        __kernel_mode_t mode;
         if ((ret = fs->d_ops->mode(dent, &mode, 1)) < 0)
             goto err;
     }
@@ -265,15 +264,85 @@ err:
         return -EACCES;
     }
 
-    int sz;
-    char *path = dentry_get_path(dent, true, &sz);
-    qstrsetstr(&exec->path, path, sz);
+    int pathlen;
+    char *path = dentry_get_path(dent, true, &pathlen);
+    qstrsetstr(&exec->path, path, pathlen);
 
-    if ((ret = check_elf_object(&exec)) < 0) {
+    if ((ret = check_elf_object(exec)) < 0 && ret != -EINVAL) {
         put_handle(exec);
         return ret;
     }
 
+    if (ret == -EINVAL) { /* it's a shebang */
+        LIST_HEAD(new_shargs);
+        struct sharg * next = NULL;
+        bool ended = false, started = false;
+        char buf[80];
+
+        do {
+            ret = do_handle_read(exec, buf, 80);
+            if (ret <= 0)
+                break;
+
+            char * s = buf, * c = buf, * e = buf + ret;
+
+            if (!started) {
+                if (ret < 2 || buf[0] != '#' || buf[1] != '!')
+                    break;
+
+                s += 2;
+                c += 2;
+                started = true;
+            }
+
+            for (; c < e ; c++) {
+                if (*c == ' ' || *c == '\n' || c == e - 1) {
+                    int l = (*c == ' ' || * c == '\n') ? c - s : e - s;
+                    if (next) {
+                        struct sharg * sh =
+                            __alloca(sizeof(struct sharg) + next->len + l + 1);
+                        sh->len = next->len + l;
+                        memcpy(sh->arg, next->arg, next->len);
+                        memcpy(sh->arg + next->len, s, l);
+                        sh->arg[next->len + l] = 0;
+                        next = sh;
+                    } else {
+                        next = __alloca(sizeof(struct sharg) + l + 1);
+                        next->len = l;
+                        memcpy(next->arg, s, l);
+                        next->arg[l] = 0;
+                    }
+                    if (*c == ' ' || *c == '\n') {
+                        INIT_LIST_HEAD(&next->list);
+                        list_add_tail(&next->list, &new_shargs);
+                        next = NULL;
+                        s = c + 1;
+                        if (*c == '\n') {
+                            ended = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        } while (!ended);
+
+        if (started) {
+            if (next) {
+                INIT_LIST_HEAD(&next->list);
+                list_add_tail(&next->list, &new_shargs);
+            }
+
+            struct sharg * first =
+                list_first_entry(&new_shargs, struct sharg, list);
+            assert(first);
+            debug("detected as script: run by %s\n", first->arg);
+            file = first->arg;
+            list_splice(&new_shargs, &shargs);
+            put_handle(exec);
+            goto reopen;
+        }
+    }
+
     SAVE_PROFILE_INTERVAL(open_file_for_exec);
 
     int is_last = check_last_thread(cur_thread) == 0;
@@ -282,19 +351,23 @@ err:
 
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
 
-    size_t envsize = allocsize;
-    void * envptr = NULL;
-    const char ** empty_argv = NULL;
-retry:
-    envptr = system_malloc(envsize);
-    if (!envptr)
-        return -ENOMEM;
+    if (!list_empty(&shargs)) {
+        struct sharg * sh;
+        int shargc = 0, cnt = 0;
+        list_for_each_entry(sh, &shargs, list)
+            shargc++;
+
+        const char ** new_argv =
+                __alloca(sizeof(const char *) * (argc + shargc + 1));
+
+        list_for_each_entry(sh, &shargs, list)
+            new_argv[cnt++] = sh->arg;
 
-    ret = populate_user_stack(envptr, envsize, 0, NULL, &empty_argv, &envp);
-    if (ret == -ENOMEM) {
-        system_free(envptr, envsize);
-        envsize += allocsize;
-        goto retry;
+        for (cnt = 0 ; cnt < argc ; cnt++)
+            new_argv[shargc + cnt] = argv[cnt];
+
+        new_argv[shargc + argc] = NULL;
+        argv = new_argv;
     }
 
     lock(cur_thread->lock);
@@ -315,10 +388,7 @@ retry:
     cur_thread->in_vm     = false;
     unlock(cur_thread->lock);
 
-    ret = do_migrate_process(&migrate_execve, exec, argv, cur_thread, envp,
-                             envptr + envsize - (void *) envp);
-
-    system_free(envptr, envsize);
+    ret = do_migrate_process(&migrate_execve, exec, argv, cur_thread, envp);
 
     lock(cur_thread->lock);
     cur_thread->stack       = stack;

+ 5 - 1
LibOS/shim/src/sys/shim_exit.c

@@ -60,6 +60,10 @@ out:
         return 0;
     }
 
+#ifdef PROFILE
+    self->exit_time = GET_PROFILE_INTERVAL();
+#endif
+
     int exit_code = self->exit_code;
     self->is_alive = false;
 
@@ -91,7 +95,7 @@ out:
             info.si_uid   = self->uid;
             info.si_status = (exit_code & 0xff) << 8;
 
-            append_signal(parent, SIGCHLD, &info);
+            append_signal(parent, SIGCHLD, &info, false);
         }
         unlock(parent->lock);
 

+ 4 - 3
LibOS/shim/src/sys/shim_fcntl.c

@@ -33,9 +33,10 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
 #include <errno.h>
 
+#include <linux/fcntl.h>
+
 int shim_do_fcntl (int fd, int cmd, unsigned long arg)
 {
     struct shim_handle_map * handle_map = get_cur_handle_map(NULL);
@@ -135,11 +136,11 @@ int shim_do_fcntl (int fd, int cmd, unsigned long arg)
          *   Set the file status flags to the value specified by arg.  File
          *   access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags
          *   (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On
-         *   Linux this command can only change the O_APPEND, O_ASYNC, O_DIRECT,
+         *   Linux this command can only change the O_APPEND, O_DIRECT,
          *   O_NOATIME, and O_NONBLOCK flags.
          */
 
-#define FCNTL_SETFL_MASK (O_APPEND|O_ASYNC|O_NONBLOCK)
+#define FCNTL_SETFL_MASK (O_APPEND|O_NONBLOCK)
 
         case F_SETFL:
             lock(hdl->lock);

+ 19 - 36
LibOS/shim/src/sys/shim_fork.c

@@ -28,6 +28,7 @@
 #include <shim_thread.h>
 #include <shim_ipc.h>
 #include <shim_profile.h>
+#include <shim_checkpoint.h>
 
 #include <pal.h>
 #include <pal_error.h>
@@ -38,47 +39,29 @@
 #include <asm/prctl.h>
 #include <linux/futex.h>
 
-static void * __malloc (size_t size)
-{
-    int flags = MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL;
-    size = ALIGN_UP(size);
-    void * addr = get_unmapped_vma(size, flags);
-
-    addr = (void *)
-        DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
-    if (!addr)
-        return NULL;
-
-    bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
-    return addr;
-}
-
-#define malloc_method __malloc
-#include <shim_checkpoint.h>
-
-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 * store,
+                  struct shim_thread * thread,
+                  struct shim_process * process, va_list ap)
 {
-    BEGIN_MIGRATION_DEF(fork, struct shim_process * proc,
-                        struct shim_thread * thread)
+    BEGIN_MIGRATION_DEF(fork, struct shim_thread * thread,
+                        struct shim_process * process)
     {
-        DEFINE_MIGRATE(process, proc, sizeof(struct shim_process), false);
-        DEFINE_MIGRATE(all_mounts, NULL, 0, false);
-        DEFINE_MIGRATE(all_vmas, NULL, 0, true); /* recusive for the data */
-        DEFINE_MIGRATE(running_thread, thread, sizeof(struct shim_thread),
-                       true); /* recusive for the stack */
+        DEFINE_MIGRATE(process, process, sizeof(struct shim_process));
+        DEFINE_MIGRATE(all_mounts, NULL, 0);
+        DEFINE_MIGRATE(all_vmas, NULL, 0);
+        DEFINE_MIGRATE(running_thread, thread, sizeof(struct shim_thread));
         DEFINE_MIGRATE(handle_map, thread->handle_map,
-                       sizeof (struct shim_handle_map), true);
-                       /* recursive for the handles */
-        DEFINE_MIGRATE(brk, NULL, 0, false);
-        DEFINE_MIGRATE(loaded_libraries, NULL, 0, false);
-        DEFINE_MIGRATE(gdb_map, NULL, 0, false);
-        DEFINE_MIGRATE(migratable, NULL, 0, false);
+                       sizeof (struct shim_handle_map));
+        DEFINE_MIGRATE(brk, NULL, 0);
+        DEFINE_MIGRATE(loaded_libraries, NULL, 0);
+#ifdef DEBUG
+        DEFINE_MIGRATE(gdb_map, NULL, 0);
+#endif
+        DEFINE_MIGRATE(migratable, NULL, 0);
     }
-    END_MIGRATION_DEF
+    END_MIGRATION_DEF(fork)
 
-    int ret = START_MIGRATE(cpstore, fork, 0, process, thread);
+    int ret = START_MIGRATE(store, fork, thread, process);
 
     thread->in_vm = false;
 

+ 3 - 1
LibOS/shim/src/sys/shim_fs.c

@@ -35,8 +35,10 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
 #include <errno.h>
+
+#include <linux/fcntl.h>
+
 #include <asm/mman.h>
 
 /* The kernel would look up the parent directory, and remove the child from

+ 3 - 1
LibOS/shim/src/sys/shim_getcwd.c

@@ -70,13 +70,14 @@ int shim_do_chdir (const char * filename)
     struct shim_dentry * dent = NULL;
     int ret;
 
-    if ((ret = path_lookupat(NULL, filename, LOOKUP_SYNC, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, filename, LOOKUP_OPEN, &dent)) < 0)
         return ret;
 
     if (!dent)
         return -ENOENT;
 
     if (!(dent->state & DENTRY_ISDIRECTORY)) {
+        debug("%s is not a directory\n", dentry_get_path(dent, false, NULL));
         put_dentry(dent);
         return -ENOTDIR;
     }
@@ -98,6 +99,7 @@ int shim_do_fchdir (int fd)
     struct shim_dentry * dent = hdl->dentry;
 
     if (!(dent->state & DENTRY_ISDIRECTORY)) {
+        debug("%s is not a directory\n", dentry_get_path(dent, false, NULL));
         put_handle(hdl);
         return -ENOTDIR;
     }

+ 75 - 112
LibOS/shim/src/sys/shim_migrate.c

@@ -30,37 +30,36 @@
 #include <shim_vma.h>
 #include <shim_fs.h>
 #include <shim_ipc.h>
+#include <shim_checkpoint.h>
 
 #include <pal.h>
 #include <pal_error.h>
 
 #include <errno.h>
-#include <fcntl.h>
-#include <asm/mman.h>
 
-#define malloc_method(size)     malloc_method_file(size)
-#include <shim_checkpoint.h>
+#include <linux/fcntl.h>
+
+#include <asm/mman.h>
 
-LIST_HEAD(created_sessions);
+LIST_HEAD(cp_sessions);
 
-struct cpsession {
-    IDTYPE                  session;
+struct cp_session {
+    IDTYPE                  sid;
     struct shim_handle *    cpfile;
     struct list_head        registered_threads;
     struct list_head        list;
     PAL_HANDLE              finish_event;
+    struct shim_cp_store    cpstore;
 };
 
-struct cpthread {
+struct cp_thread {
     struct shim_thread *    thread;
     struct list_head        list;
 };
 
-static struct cpsession * current_cpsession = NULL;
-
-int create_checkpoint (const char * cpdir, IDTYPE * session)
+int create_checkpoint (const char * cpdir, IDTYPE * sid)
 {
-    struct cpsession * cpsession = malloc(sizeof(struct cpsession));
+    struct cp_session * cpsession = malloc(sizeof(struct cp_session));
     if (!cpsession)
         return -ENOMEM;
 
@@ -94,30 +93,27 @@ int create_checkpoint (const char * cpdir, IDTYPE * session)
         goto err;
 
     open_handle(cpsession->cpfile);
-
     master_lock();
 
-    if (*session) {
-        struct cpsession * cps;
-        list_for_each_entry(cps, &created_sessions, list)
-            if (cps->session == *session) {
+    struct cp_session * s;
+    if (*sid) {
+        list_for_each_entry(s, &cp_sessions, list)
+            if (s->sid == *sid) {
                 ret = 0;
                 goto err_locked;
             }
     } else {
-        struct cpsession * cps;
 retry:
-        getrand(session, sizeof(IDTYPE));
-        list_for_each_entry(cps, &created_sessions, list)
-            if (cps->session == *session)
-                goto retry;
-    }
+        getrand(&cpsession->sid, sizeof(IDTYPE));
 
-    list_add_tail(&cpsession->list, &created_sessions);
+        list_for_each_entry(s, &cp_sessions, list)
+            if (s->sid == cpsession->sid)
+                goto retry;
 
-    if (!current_cpsession)
-        current_cpsession = cpsession;
+        *sid = cpsession->sid;
+    }
 
+    list_add_tail(&cpsession->list, &cp_sessions);
     master_unlock();
     return 0;
 
@@ -132,50 +128,58 @@ err:
     return ret;
 }
 
-static int finish_checkpoint (void);
+static int finish_checkpoint (struct cp_session * session);
 
 static int check_thread (struct shim_thread * thread, void * arg,
                          bool * unlocked)
 {
     struct list_head * registered = (struct list_head *) arg;
-    struct cpthread * cpt;
+    struct cp_thread * t;
 
     if (!thread->in_vm || !thread->is_alive)
         return 0;
 
-    list_for_each_entry(cpt, registered, list)
-        if (cpt->thread == thread)
+    list_for_each_entry(t, registered, list)
+        if (t->thread == thread)
             return 0;
 
     return 1;
 }
 
-int join_checkpoint (struct shim_thread * cur, ucontext_t * context)
+int join_checkpoint (struct shim_thread * thread, ucontext_t * context,
+                     IDTYPE sid)
 {
-    struct cpthread cpt;
+    struct cp_session * s, * cpsession = NULL;
+    struct cp_thread cpthread;
     int ret = 0;
     bool do_checkpoint = false;
 
     master_lock();
 
-    if (!current_cpsession) {
+    list_for_each_entry(s, &cp_sessions, list)
+        if (s->sid == sid) {
+            cpsession = s;
+            break;
+        }
+
+    if (!cpsession) {
         master_unlock();
         return -EINVAL;
     }
 
-    INIT_LIST_HEAD(&cpt.list);
-    cpt.thread = cur;
-    list_add_tail(&cpt.list, &current_cpsession->registered_threads);
+    INIT_LIST_HEAD(&cpthread.list);
+    cpthread.thread = thread;
+    list_add_tail(&cpthread.list, &cpsession->registered_threads);
 
     /* find out if there is any thread that is not registered yet */
     ret = walk_thread_list(&check_thread,
-                           &current_cpsession->registered_threads,
+                           &cpsession->registered_threads,
                            false);
 
     if (ret == -ESRCH)
         do_checkpoint = true;
 
-    PAL_HANDLE finish_event = current_cpsession->finish_event;
+    PAL_HANDLE finish_event = cpsession->finish_event;
     master_unlock();
 
     if (!do_checkpoint) {
@@ -186,7 +190,7 @@ int join_checkpoint (struct shim_thread * cur, ucontext_t * context)
 
     debug("ready for checkpointing\n");
 
-    ret = finish_checkpoint();
+    ret = finish_checkpoint(cpsession);
     if (ret < 0)
         debug("failed creating checkpoint\n");
     else
@@ -196,99 +200,58 @@ int join_checkpoint (struct shim_thread * cur, ucontext_t * context)
     return ret;
 }
 
-void * malloc_method_file (size_t size)
+static void * file_alloc (struct shim_cp_store * store, void * addr, int size)
 {
-    struct shim_handle * cpfile;
-
-    master_lock();
-    if (!current_cpsession || !current_cpsession->cpfile) {
-        master_unlock();
-        return NULL;
-    }
-    cpfile = current_cpsession->cpfile;
-    get_handle(cpfile);
-    master_unlock();
-
-    struct shim_mount * fs = cpfile->fs;
+    assert(store->cp_file);
+    struct shim_mount * fs = store->cp_file->fs;
 
     if (!fs || !fs->fs_ops ||
         !fs->fs_ops->truncate || !fs->fs_ops->mmap)
         return NULL;
 
-    if (fs->fs_ops->truncate(cpfile, size) < 0)
+    if (fs->fs_ops->truncate(store->cp_file, size) < 0)
         return NULL;
 
-    void * addr = NULL;
-    void * mem = fs->fs_ops->mmap(cpfile, &addr, ALIGN_UP(size),
-                            PROT_READ|PROT_WRITE,
-                            MAP_FILE|MAP_SHARED, 0) < 0 ? NULL : addr;
+    if (fs->fs_ops->mmap(store->cp_file, &addr, size,
+                         PROT_READ|PROT_WRITE,
+                         MAP_FILE|MAP_SHARED, 0) < 0)
+        return NULL;
 
-    put_handle(cpfile);
-    return mem;
+    return addr;
 }
 
-static int finish_checkpoint (void)
+static int finish_checkpoint (struct cp_session * cpsession)
 {
-    struct shim_cp_store cpstore;
+    struct shim_cp_store * cpstore = &cpsession->cpstore;
+    int ret;
 
-again:
-    INIT_CP_STORE(&cpstore);
+    cpstore->alloc = file_alloc;
 
     BEGIN_MIGRATION_DEF(checkpoint)
     {
-        store->use_gipc = false;
-        DEFINE_MIGRATE(process, &cur_process, sizeof(struct shim_process),
-                       false);
-        DEFINE_MIGRATE(all_mounts, NULL, 0, false);
-        DEFINE_MIGRATE(all_vmas, NULL, 0, true);
-        DEFINE_MIGRATE(all_running_threads, NULL, 0, true);
-        DEFINE_MIGRATE(brk, NULL, 0, false);
-        DEFINE_MIGRATE(loaded_libraries, NULL, 0, false);
-        DEFINE_MIGRATE(gdb_map, NULL, 0, false);
-        DEFINE_MIGRATE(migratable, NULL, 0, false);
+        DEFINE_MIGRATE(process, &cur_process, sizeof(struct shim_process));
+        DEFINE_MIGRATE(all_mounts, NULL, 0);
+        DEFINE_MIGRATE(all_vmas, NULL, 0);
+        DEFINE_MIGRATE(all_running_threads, NULL, 0);
+        DEFINE_MIGRATE(brk, NULL, 0);
+        DEFINE_MIGRATE(loaded_libraries, NULL, 0);
+#ifdef DEBUG
+        DEFINE_MIGRATE(gdb_map, NULL, 0);
+#endif
+        DEFINE_MIGRATE(migratable, NULL, 0);
     }
-    END_MIGRATION_DEF
-
-    int ret = START_MIGRATE(&cpstore, checkpoint, sizeof(struct cp_header));
+    END_MIGRATION_DEF(checkpoint)
 
-    if (ret < 0)
+    if ((ret = START_MIGRATE(cpstore, checkpoint)) < 0)
         return ret;
 
-    struct shim_cp_entry * cpent = cpstore.cpdata;
-    for ( ; cpent->cp_type != CP_NULL ; cpent++)
-        if (cpent->cp_type == CP_PALHDL &&
-            cpent->cp_un.cp_val) {
-            PAL_HANDLE * pal_hdl = cpstore.cpdata + cpent->cp_un.cp_val;
-            assert(*pal_hdl);
-            *pal_hdl = NULL;
-        }
-
-    struct cp_header * hdr = (struct cp_header *) cpstore.cpaddr;
-    hdr->cpaddr = cpstore.cpaddr;
-    hdr->cpsize = cpstore.cpsize;
-    hdr->cpoffset = cpstore.cpdata - cpstore.cpaddr;
-
-    DkStreamUnmap(cpstore.cpaddr, cpstore.cpsize);
-
-    master_lock();
-    assert(current_cpsession);
-    struct shim_handle * cpfile = current_cpsession->cpfile;
-    bool do_again = false;
-    current_cpsession->cpfile = NULL;
-    if (current_cpsession->list.next != &created_sessions) {
-        current_cpsession = list_entry(current_cpsession->list.next,
-                                       struct cpsession, list);
-        do_again = true;
-    } else {
-        current_cpsession = NULL;
-    }
-    master_unlock();
-
-    close_handle(cpfile);
+    struct cp_header * hdr = (struct cp_header *) cpstore->base;
+    hdr->addr = (void *) cpstore->base;
+    hdr->size = cpstore->offset;
 
-    if (do_again)
-        goto again;
+    DkStreamUnmap((void *) cpstore->base, cpstore->bound);
 
+    close_handle(cpstore->cp_file);
     return 0;
 }
 
@@ -313,9 +276,9 @@ int shim_do_checkpoint (const char * filename)
     }
 
     ipc_checkpoint_send(filename, session);
-    kill_all_threads(tcb->tp, CHECKPOINT_REQUESTED, SIGINT);
+    kill_all_threads(tcb->tp, session, SIGCP);
 
-    ret = join_checkpoint(tcb->tp, &signal.context);
+    ret = join_checkpoint(tcb->tp, &signal.context, session);
     if (ret < 0) {
         shim_do_rmdir(filename);
         return ret;

+ 7 - 6
LibOS/shim/src/sys/shim_open.c

@@ -36,11 +36,13 @@
 #include <pal.h>
 #include <pal_error.h>
 
-#include <fcntl.h>
 #include <errno.h>
 #include <dirent.h>
 
-int do_handle_read (struct shim_handle * hdl, void * buf, size_t count)
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+
+int do_handle_read (struct shim_handle * hdl, void * buf, int count)
 {
     if (!(hdl->acc_mode & MAY_READ))
         return -EACCES;
@@ -57,7 +59,6 @@ int do_handle_read (struct shim_handle * hdl, void * buf, size_t count)
     return fs->fs_ops->read(hdl, buf, count);
 }
 
-
 size_t shim_do_read (int fd, void * buf, size_t count)
 {
     struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL);
@@ -68,7 +69,7 @@ size_t shim_do_read (int fd, void * buf, size_t count)
     return ret;
 }
 
-int do_handle_write (struct shim_handle * hdl, const void * buf, size_t count)
+int do_handle_write (struct shim_handle * hdl, const void * buf, int count)
 {
     if (!(hdl->acc_mode & MAY_WRITE))
         return -EACCES;
@@ -367,7 +368,7 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
         dirhdl->dotdot = NULL;
     }
 
-    while (*dirhdl->ptr) {
+    while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
         ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
         put_dentry(dent);
@@ -436,7 +437,7 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
         dirhdl->dotdot = NULL;
     }
 
-    while (*dirhdl->ptr) {
+    while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
         ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
         put_dentry(dent);

+ 6 - 1
LibOS/shim/src/sys/shim_pipe.c

@@ -33,7 +33,8 @@
 #include <pal_error.h>
 
 #include <errno.h>
-#include <fcntl.h>
+
+#include <asm/fcntl.h>
 
 int create_pipes (IDTYPE * pipeid, PAL_HANDLE * srv, PAL_HANDLE * cli,
                   struct shim_qstr * qstr, int flags)
@@ -93,10 +94,12 @@ int shim_do_pipe2 (int * filedes, int flags)
 
     hdl1->type       = TYPE_PIPE;
     set_handle_fs(hdl1, &pipe_builtin_fs);
+    hdl1->flags      = O_RDONLY;
     hdl1->acc_mode   = MAY_READ;
 
     hdl2->type       = TYPE_PIPE;
     set_handle_fs(hdl2, &pipe_builtin_fs);
+    hdl2->flags      = O_WRONLY;
     hdl2->acc_mode   = MAY_WRITE;
 
     if ((ret = create_pipes(&hdl1->info.pipe.pipeid,
@@ -164,6 +167,7 @@ int shim_do_socketpair (int domain, int type, int protocol, int * sv)
 
     hdl1->type          = TYPE_SOCK;
     set_handle_fs(hdl1, &socket_builtin_fs);
+    hdl1->flags         = O_RDONLY;
     hdl1->acc_mode      = MAY_READ|MAY_WRITE;
     sock1->domain       = domain;
     sock1->sock_type    = type & ~(SOCK_NONBLOCK|SOCK_CLOEXEC);
@@ -172,6 +176,7 @@ int shim_do_socketpair (int domain, int type, int protocol, int * sv)
 
     hdl2->type          = TYPE_SOCK;
     set_handle_fs(hdl2, &socket_builtin_fs);
+    hdl1->flags         = O_WRONLY;
     hdl2->acc_mode      = MAY_READ|MAY_WRITE;
     sock2->domain       = domain;
     sock2->sock_type    = type & ~(SOCK_NONBLOCK|SOCK_CLOEXEC);

+ 49 - 32
LibOS/shim/src/sys/shim_poll.c

@@ -35,10 +35,9 @@
 #include <pal_error.h>
 #include <linux_list.h>
 
-#include <fcntl.h>
 #include <errno.h>
-#include <sys/poll.h>
-#include <sys/select.h>
+
+#include <linux/fcntl.h>
 
 void __attribute__ ((noreturn))
 fortify_fail (const char *msg)
@@ -54,15 +53,6 @@ chk_fail (void)
     fortify_fail ("buffer overflow detected");
 }
 
-unsigned long int
-__fdelt_chk (unsigned long int d)
-{
-    if (d > FD_SETSIZE)
-        chk_fail();
-
-    return d / __NFDBITS;
-}
-
 static inline __attribute__((always_inline))
 void * __try_alloca (struct shim_thread * cur, int size)
 {
@@ -422,7 +412,7 @@ out:
 }
 
 int shim_do_ppoll (struct pollfd * fds, int nfds, struct timespec * tsp,
-                   const sigset_t * sigmask, size_t sigsetsize)
+                   const __sigset_t * sigmask, size_t sigsetsize)
 {
     struct shim_thread * cur = get_cur_thread();
 
@@ -469,6 +459,35 @@ out:
     return ret;
 }
 
+typedef long int __fd_mask;
+
+#ifndef __NFDBITS
+#define __NFDBITS    (8 * (int) sizeof (__fd_mask))
+#endif
+#ifndef __FDS_BITS
+#define __FDS_BITS(set) ((set)->fds_bits)
+#endif
+
+/* We don't use `memset' because this would require a prototype and
+   the array isn't too big.  */
+# define __FD_ZERO(set)                                     \
+    do {                                                    \
+        unsigned int __i;                                   \
+        fd_set *__arr = (set);                              \
+        for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
+        __FDS_BITS (__arr)[__i] = 0;                        \
+    } while (0)
+
+#define __FD_ELT(d)     ((d) / __NFDBITS)
+#define __FD_MASK(d)    ((__fd_mask) 1 << ((d) % __NFDBITS))
+
+#define __FD_SET(d, set)                                    \
+  ((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))
+#define __FD_CLR(d, set)                                    \
+  ((void) (__FDS_BITS (set)[__FD_ELT (d)] &= ~__FD_MASK (d)))
+#define __FD_ISSET(d, set)                                  \
+  ((__FDS_BITS (set)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
+
 DEFINE_PROFILE_CATAGORY(select, );
 DEFINE_PROFILE_INTERVAL(select_tryalloca_1, select);
 DEFINE_PROFILE_INTERVAL(select_setup_array, select);
@@ -501,8 +520,8 @@ int shim_do_select (int nfds, fd_set * readfds, fd_set * writefds,
     SAVE_PROFILE_INTERVAL(select_tryalloca_1);
 
     for (int fd = 0 ; fd < nfds ; fd++) {
-        bool do_r = (readfds  && FD_ISSET(fd, readfds));
-        bool do_w = (writefds && FD_ISSET(fd, writefds));
+        bool do_r = (readfds  && __FD_ISSET(fd, readfds));
+        bool do_w = (writefds && __FD_ISSET(fd, writefds));
         if (!do_r && !do_w)
             continue;
         polls[npolls].fd = fd;
@@ -526,25 +545,25 @@ int shim_do_select (int nfds, fd_set * readfds, fd_set * writefds,
     ret = 0;
 
     if (readfds)
-        FD_ZERO(readfds);
+        __FD_ZERO(readfds);
     if (writefds)
-        FD_ZERO(writefds);
+        __FD_ZERO(writefds);
     if (errorfds)
-        FD_ZERO(errorfds);
+        __FD_ZERO(errorfds);
 
     SAVE_PROFILE_INTERVAL(select_fd_zero);
 
     for (int i = 0 ; i < npolls ; i++) {
         if (readfds && ((polls[i].flags & (DO_R|RET_R)) == (DO_R|RET_R))) {
-            FD_SET(polls[i].fd, readfds);
+            __FD_SET(polls[i].fd, readfds);
             ret++;
         }
         if (writefds && ((polls[i].flags & (DO_W|RET_W)) == (DO_W|RET_W))) {
-            FD_SET(polls[i].fd, writefds);
+            __FD_SET(polls[i].fd, writefds);
             ret++;
         }
         if (errorfds && ((polls[i].flags & (DO_R|DO_W|RET_E)) > RET_E)) {
-            FD_SET(polls[i].fd, errorfds);
+            __FD_SET(polls[i].fd, errorfds);
             ret++;
         }
     }
@@ -553,13 +572,12 @@ int shim_do_select (int nfds, fd_set * readfds, fd_set * writefds,
 out:
     __try_free(cur, polls);
     SAVE_PROFILE_INTERVAL(select_try_free);
-
     return ret;
 }
 
 int shim_do_pselect6 (int nfds, fd_set * readfds, fd_set * writefds,
                       fd_set * errorfds, const struct __kernel_timespec * tsp,
-                      const sigset_t * sigmask)
+                      const __sigset_t * sigmask)
 {
     if (!nfds)
         return tsp ? shim_do_nanosleep (tsp, NULL) : -EINVAL;
@@ -571,8 +589,8 @@ int shim_do_pselect6 (int nfds, fd_set * readfds, fd_set * writefds,
     int npolls = 0;
 
     for (int fd = 0 ; fd < nfds ; fd++) {
-        bool do_r = (readfds  && FD_ISSET(fd, readfds));
-        bool do_w = (writefds && FD_ISSET(fd, writefds));
+        bool do_r = (readfds  && __FD_ISSET(fd, readfds));
+        bool do_w = (writefds && __FD_ISSET(fd, writefds));
         if (!do_r && !do_w)
             continue;
         polls[npolls].fd = fd;
@@ -592,29 +610,28 @@ int shim_do_pselect6 (int nfds, fd_set * readfds, fd_set * writefds,
     ret = 0;
 
     if (readfds)
-        FD_ZERO(readfds);
+        __FD_ZERO(readfds);
     if (writefds)
-        FD_ZERO(writefds);
+        __FD_ZERO(writefds);
     if (errorfds)
-        FD_ZERO(errorfds);
+        __FD_ZERO(errorfds);
 
     for (int i = 0 ; i < npolls ; i++) {
         if (readfds && ((polls[i].flags & (DO_R|RET_R)) == (DO_R|RET_R))) {
-            FD_SET(polls[i].fd, readfds);
+            __FD_SET(polls[i].fd, readfds);
             ret++;
         }
         if (writefds && ((polls[i].flags & (DO_W|RET_W)) == (DO_W|RET_W))) {
-            FD_SET(polls[i].fd, writefds);
+            __FD_SET(polls[i].fd, writefds);
             ret++;
         }
         if (errorfds && ((polls[i].flags & (DO_R|DO_W|RET_E)) > RET_E)) {
-            FD_SET(polls[i].fd, errorfds);
+            __FD_SET(polls[i].fd, errorfds);
             ret++;
         }
     }
 
 out:
     __try_free(cur, polls);
-
     return ret;
 }

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

@@ -86,9 +86,9 @@ int shim_do_sigreturn (int __unused)
     return 0;
 }
 
-int shim_do_sigprocmask (int how, const sigset_t * set, sigset_t * oldset)
+int shim_do_sigprocmask (int how, const __sigset_t * set, __sigset_t * oldset)
 {
-    sigset_t * old, tmp, set_tmp;
+    __sigset_t * old, tmp, set_tmp;
 
     if (how != SIG_BLOCK && how != SIG_UNBLOCK &&
         how != SIG_SETMASK)
@@ -101,7 +101,7 @@ int shim_do_sigprocmask (int how, const sigset_t * set, sigset_t * oldset)
 
     old = get_sig_mask(cur);
     if (oldset) {
-        memcpy(&tmp, old, sizeof(sigset_t));
+        memcpy(&tmp, old, sizeof(__sigset_t));
         old = &tmp;
     }
 
@@ -110,7 +110,7 @@ int shim_do_sigprocmask (int how, const sigset_t * set, sigset_t * oldset)
     if (!set)
         goto out;
 
-    memcpy(&set_tmp, old, sizeof(sigset_t));
+    memcpy(&set_tmp, old, sizeof(__sigset_t));
 
     switch (how) {
         case SIG_BLOCK:
@@ -122,7 +122,7 @@ int shim_do_sigprocmask (int how, const sigset_t * set, sigset_t * oldset)
             break;
 
         case SIG_SETMASK:
-            memcpy(&set_tmp, set, sizeof(sigset_t));
+            memcpy(&set_tmp, set, sizeof(__sigset_t));
             break;
     }
 
@@ -132,7 +132,7 @@ out:
     unlock(cur->lock);
 
     if (!err && oldset)
-        memcpy(oldset, old, sizeof(sigset_t));
+        memcpy(oldset, old, sizeof(__sigset_t));
 
     return err;
 }
@@ -153,7 +153,7 @@ static inline void __append_signal (struct shim_thread * thread, int sig,
     memset(&info, 0, sizeof(siginfo_t));
     info.si_signo = sig;
     info.si_pid   = sender;
-    append_signal(thread, sig, &info);
+    append_signal(thread, sig, &info, true);
 }
 
 static int __kill_proc (struct shim_thread * thread, void * arg,

+ 29 - 36
LibOS/shim/src/sys/shim_socket.c

@@ -36,10 +36,30 @@
 #include <pal_error.h>
 
 #include <errno.h>
+
 #include <linux/fcntl.h>
-#include <linux/un.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+#include <asm/socket.h>
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define TCP_NODELAY         1   /* Don't delay send to coalesce packets  */
+#define TCP_MAXSEG          2   /* Set maximum segment size  */
+#define TCP_CORK            3   /* Control sending of partial frames  */
+#define TCP_KEEPIDLE        4   /* Start keeplives after this period */
+#define TCP_KEEPINTVL       5   /* Interval between keepalives */
+#define TCP_KEEPCNT         6   /* Number of keepalives before death */
+#define TCP_SYNCNT          7   /* Number of SYN retransmits */
+#define TCP_LINGER2         8   /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT    9   /* Wake up listener only when data arrive */
+#define TCP_WINDOW_CLAMP    10  /* Bound advertised window */
+#define TCP_INFO            11  /* Information about this connection. */
+#define TCP_QUICKACK        12  /* Bock/reenable quick ACKs.  */
+#define TCP_CONGESTION      13  /* Congestion control algorithm.  */
+#define TCP_MD5SIG          14  /* TCP MD5 Signature (RFC2385) */
 
 #define SOCK_URI_SIZE   64
 
@@ -90,38 +110,18 @@ int shim_do_socket (int family, int type, int protocol)
 
     int ret = -ENOSYS;
 
-#undef  NOTSUPPORT
-#define NOTSUPPORT(domain)  \
-    case domain:            \
-        debug("shim_socket: domain " #domain " not supported\n"); \
-        goto err;
-
     switch (sock->domain) {
         case AF_UNIX:             //Local communication
         case AF_INET:             //IPv4 Internet protocols          ip(7)
         case AF_INET6:            //IPv6 Internet protocols
             break;
 
-        NOTSUPPORT(AF_IPX)        //IPX - Novell protocols
-        NOTSUPPORT(AF_NETLINK)    //Kernel user interface device     netlink(7)
-        NOTSUPPORT(AF_X25)        //ITU-T X.25 / ISO-8208 protocol   x25(7)
-        NOTSUPPORT(AF_AX25)       //Amateur radio AX.25 protocol
-        NOTSUPPORT(AF_ATMPVC)     //Access to raw ATM PVCs
-        NOTSUPPORT(AF_APPLETALK)  //Appletalk                        ddp(7)
-        NOTSUPPORT(AF_PACKET)     //Low level packet interface       packet(7)
-
         default:
             debug("shim_socket: unknown socket domain %d\n",
                   sock->domain);
             goto err;
     }
 
-#undef  NOTSUPPORT
-#define NOTSUPPORT(type)    \
-    case type:              \
-        debug("shim_socket: type " #type " not supported\n"); \
-        goto err;
-
     switch (sock->sock_type) {
         case SOCK_STREAM:         //TCP
             break;
@@ -129,11 +129,6 @@ int shim_do_socket (int family, int type, int protocol)
             hdl->acc_mode = MAY_READ|MAY_WRITE;
             break;
 
-        NOTSUPPORT(SOCK_SEQPACKET)
-        NOTSUPPORT(SOCK_RAW)
-        NOTSUPPORT(SOCK_RDM)
-        NOTSUPPORT(SOCK_PACKET)
-
         default:
             debug("shim_socket: unknown socket type %d\n",
                   sock->sock_type);
@@ -566,18 +561,12 @@ static int inet_parse_addr (int domain, int type, const char * uri,
         struct addr_inet * addr = round ? conn : bind;
 
         if (domain == AF_INET) {
-            char ip_buf[20];
-            memcpy(ip_buf, ip_str, ip_len);
-            ip_buf[ip_len] = 0;
-            inet_pton4(ip_buf, &addr->addr.v4);
+            inet_pton4(ip_str, ip_len, &addr->addr.v4);
             addr->ext_port = atoi(port_str);
         }
 
         if (domain == AF_INET6) {
-            char ip_buf[48];
-            memcpy(ip_buf, ip_str, ip_len);
-            ip_buf[ip_len] = 0;
-            inet_pton6(ip_str, &addr->addr.v6);
+            inet_pton6(ip_str, ip_len, &addr->addr.v6);
             addr->ext_port = atoi(port_str);
         }
     }
@@ -1194,6 +1183,10 @@ ssize_t shim_do_recvmsg (int sockfd, struct msghdr * msg, int flags)
                       msg->msg_name, &msg->msg_namelen);
 }
 
+#define SHUT_RD     0
+#define SHUT_WR     1
+#define SHUT_RDWR   2
+
 int shim_do_shutdown (int sockfd, int how)
 {
     struct shim_handle * hdl = get_fd_handle(sockfd, NULL, NULL);

+ 7 - 6
LibOS/shim/src/sys/shim_time.c

@@ -49,18 +49,19 @@ int shim_do_gettimeofday (struct __kernel_timeval * tv,
     return 0;
 }
 
-int shim_do_time (time_t * tloc)
+time_t shim_do_time (time_t * tloc)
 {
-    if (!tloc)
-        return -EINVAL;
-
     long time = DkSystemTimeQuery();
 
     if (time == -1)
         return -PAL_ERRNO;
 
-    *tloc  = time / 1000000;
-    return 0;
+    time_t t = time / 1000000;
+
+    if (tloc)
+        *tloc = t;
+
+    return t;
 }
 
 int shim_do_clock_gettime (clockid_t which_clock,

+ 1 - 0
LibOS/shim/src/sys/shim_vfork.c

@@ -113,6 +113,7 @@ int shim_do_vfork (void)
 
     /* set the current thread running */
     set_cur_thread(new_thread);
+    put_thread(new_thread);
 
     /* here we return immediately, no letting the hooks mes up our stack */
     return 0;

+ 4 - 0
LibOS/shim/src/sys/shim_wait.c

@@ -38,6 +38,9 @@
 #include <linux/wait.h>
 #include <errno.h>
 
+DEFINE_PROFILE_CATAGORY(wait, );
+DEFINE_PROFILE_INTERVAL(child_exit_notification, wait);
+
 pid_t shim_do_wait4 (pid_t pid, int * status, int option,
                      struct __kernel_rusage * ru)
 {
@@ -138,6 +141,7 @@ found:
         *status = (thread->exit_code & 0xff) << 8;
 
     ret = thread->tid;
+    SAVE_PROFILE_INTERVAL_SINCE(child_exit_notification, thread->exit_time);
     del_thread(thread);
     put_thread(thread);
     return ret;

+ 3 - 3
LibOS/shim/test/Makefile

@@ -40,15 +40,15 @@ clean: $(clean-extra) $(if $(level),,clean-subdirs)
 	rm -rf $(target)
 
 build-subdirs:
-	for f in $(subdirs); do (cd $$f; make $(DEBUG); cd ..); done
+	for f in $(subdirs); do (cd $$f; $(MAKE) $(DEBUG); cd ..); done
 
 ifeq ($(SYS),x86_64-linux-gnu)
 ifeq ($(level),)
 .PHONY: pack
 pack:
-	for f in $(subdirs); do (cd $$f; make pack; cd ..); done
+	for f in $(subdirs); do (cd $$f; $(MAKE) pack; cd ..); done
 endif
 endif
 
 clean-subdirs:
-	for f in $(subdirs); do (cd $$f; make clean; cd ..); done
+	for f in $(subdirs); do (cd $$f; $(MAKE) clean; cd ..); done

+ 19 - 8
LibOS/shim/test/apps/Makefile

@@ -1,19 +1,30 @@
-apps = lmbench gcc busybox lighttpd bash apache make
+SYS ?= $(shell gcc -dumpmachine)
+export SYS
+
+apps = lmbench gcc busybox lighttpd bash apache make python r openjdk
 packed_apps = lmbench
 
-targets = pal pal_sec
+target = pal pal_sec
 clean-extra = clean-all
 
 level = ../
 include ../Makefile
 
+ifeq ($(SYS),x86_64-linux-gnu)
+HOSTDIR =
+PAL = $(abspath $(PWD)/../pal_loader)
+else
+HOSTDIR = /tmp/host
+PAL = $(abspath $(PWD)/../pal)
+endif
+
 manifest_rules = \
-	-e 's:\$$(PAL):$(abspath $(PWD)/../pal_loader):g' \
+	-e 's:\$$(PAL):$(PAL):g' \
 	-e 's:\$$(PWD):$(PWD)/:g' \
 	-e 's:\$$(BIN):$(subst .manifest,,$(notdir $@)):g' \
 	-e 's:\$$(SHIMPATH):$(abspath ../../src/libsysdb.so):g' \
 	-e 's:\$$(GLIBCDIR):$(abspath $(glibc_dir))/:g' \
-	-e 's:\$$(HOSTNAME):$(shell hostname)/:g' \
+	-e 's:\$$(HOSTDIR):$(HOSTDIR):g' \
 	$(extra_rules)
 
 %.manifest: %.manifest.template
@@ -23,15 +34,15 @@ manifest_rules = \
 
 ifeq ($(SYS),x86_64-linux-gnu)
 build-all:
-	for f in $(apps); do (cd $$f; make $(DEBUG) || true; cd ..); done
+	for f in $(apps); do (cd $$f; $(MAKE) $(DEBUG) || true; cd ..); done
 
 .PHONY: pack
 pack:
-	for f in $(packed_apps); do (cd $$f; make pack; cd ..); done
+	for f in $(packed_apps); do (cd $$f; $(MAKE) pack; cd ..); done
 else
 build-all:
-	for f in $(packed_apps); do (cd $$f; make || true; cd ..); done
+	for f in $(packed_apps); do (cd $$f; $(MAKE) || true; cd ..); done
 endif
 
 clean-all:
-	for f in $(apps); do (cd $$f; make clean; cd ..); done
+	for f in $(apps); do (cd $$f; $(MAKE) clean; cd ..); done

+ 17 - 16
LibOS/shim/test/apps/apache/Makefile

@@ -1,5 +1,5 @@
-HOST := $(firstword $(shell ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' -m 1 | cut -d: -f2))
-PORT := 8000
+HOST ?= $(firstword $(shell ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' -m 1 | cut -d: -f2))
+PORT ?= 8000
 
 NPROCS := 1
 OS := $(shell uname -s)
@@ -35,27 +35,27 @@ debug: $(TARGET)
 $(INSTALL_DIR)/lib/libapr-1.so.0: $(APR_DIR)
 	#cd $< && patch -p1 < ../disable-epoll.patch
 	cd $< && ./configure --prefix=$(INSTALL_DIR)
-	cd $< && make -j$(NPROCS) $(MAKE_FLAGS)
-	cd $< && make install
+	cd $< && $(MAKE) -j$(NPROCS) $(MAKE_FLAGS)
+	cd $< && $(MAKE) install
 
 $(INSTALL_DIR)/lib/libaprutil-1.so.0: $(APRUTIL_DIR) $(INSTALL_DIR)/lib/libapr-1.so.0
 	cd $< && ./configure --prefix=$(INSTALL_DIR) --with-apr=$(INSTALL_DIR)
-	cd $< && make -j$(NPROCS) $(MAKE_FLAGS)
-	cd $< && make install
+	cd $< && $(MAKE) -j$(NPROCS) $(MAKE_FLAGS)
+	cd $< && $(MAKE) install
 
 $(INSTALL_DIR)/bin/httpd $(INSTALL_DIR)/bin/apxs: $(INSTALL_DIR)/lib/libapr-1.so.0 $(INSTALL_DIR)/lib/libaprutil-1.so.0
 	[ -d $(HTTPD_DIR) ] || tar -xzf $(HTTPD_DIR).tar.gz
 	[ -f $(HTTPD_DIR)/Makefile ] || \
 	cd $(HTTPD_DIR) && ./configure --prefix=$(INSTALL_DIR) --with-apr=$(INSTALL_DIR) \
 	--with-apr-util=$(INSTALL_DIR) --with-mpm=prefork
-	cd $(HTTPD_DIR) && make -j$(NPROCS) $(MAKE_FLAGS)
-	cd $(HTTPD_DIR) && make install
+	cd $(HTTPD_DIR) && $(MAKE) -j$(NPROCS) $(MAKE_FLAGS)
+	cd $(HTTPD_DIR) && $(MAKE) install
 
 $(INSTALL_DIR)/modules/libphp5.so: $(PHP_DIR) $(INSTALL_DIR)/bin/apxs
 	cd $< && ./configure --prefix=$(INSTALL_DIR) --with-apxs2=$(INSTALL_DIR)/bin/apxs \
 	--disable-cgi --disable-cli --disable-soap
-	cd $< && make -j$(NPROCS) $(MAKE_FLAGS)
-	cd $< && make install
+	cd $< && $(MAKE) -j$(NPROCS) $(MAKE_FLAGS)
+	cd $< && $(MAKE) install
 
 .PHONY: modules
 
@@ -67,14 +67,13 @@ $(INSTALL_DIR)/modules/mod_auth_basic_sandbox.so: mod_auth_basic_sandbox.c $(INS
 		-S LDFLAGS="-L../../../../build/libos -llibos" -c -i -A $<
 
 %.manifest: %.manifest.template
-	make -C .. apache/$@ appdir=apache/ \
+	$(MAKE) -C .. apache/$@ appdir=apache/ \
 		extra_rules="-e 's:\\\$$\$$(HOST):$(HOST):g' -e 's:\\\$$\$$(PORT):$(PORT):g'"
 
-
 conf:
 	[ -f $(INSTALL_DIR)/conf/httpd.conf.old ] || \
 		mv $(INSTALL_DIR)/conf/httpd.conf $(INSTALL_DIR)/conf/httpd.conf.old
-	sed -e "s/Listen 80/Listen $(HOST):$(PORT)/g" \
+	sed -e "s/Listen 80/#Listen 80/g" \
 	    -e "s/User daemon/#User root/g" \
 	    -e "s/Group daemon/#Group root/g" \
 	    -e "s/#EnableMMAP off/EnableMMAP off/g" \
@@ -96,11 +95,13 @@ conf:
 	cd $(INSTALL_DIR)/conf && ln -sf httpd.conf.new httpd.conf
 
 start-native-server:
-	$(PREFIX) $(INSTALL_DIR)/bin/httpd -D FOREGROUND
+	@echo "Listen on $(HOST):$(PORT)"
+	$(PREFIX) $(INSTALL_DIR)/bin/httpd -D FOREGROUND -C "Listen $(HOST):$(PORT)" -C "PidFile /httpd-$(HOST)-$(PORT).pid"
 
 start-graphene-server:
-	rm -rf $(INSTALL_DIR)/logs/httpd.pid
-	$(PREFIX) ./httpd.manifest -D FOREGROUND
+	rm -rf httpd-$(HOST)-$(PORT).pid
+	@echo "Listen on $(HOST):$(PORT)"
+	$(PREFIX) ./httpd.manifest -D FOREGROUND -C "Listen $(HOST):$(PORT)" -C "PidFile /httpd-$(HOST)-$(PORT).pid"
 
 random-data = $(foreach n,1 2 3 4 5 6 7 8 9 10,2K.$n.html) \
 	      $(foreach n,1 2 3 4 5,10K.$n.html) \

+ 2 - 2
LibOS/shim/test/apps/bash/Makefile

@@ -14,7 +14,7 @@ $(bash_src): $(bash_src).tar.gz
 
 $(bash_src)/bash: $(bash_src)
 	cd $(bash_src) && ./configure --without-gnu-malloc
-	cd $(bash_src) && make CC="gcc -g"
+	cd $(bash_src) && $(MAKE) CC="gcc -g"
 
 test: all $(test_targets)
 
@@ -22,7 +22,7 @@ testsamplebash:
 	bash bash_test.sh
 
 %.manifest: %.manifest.template
-	make -C .. bash/$@ appdir=bash/
+	$(MAKE) -C .. bash/$@ appdir=bash/
 
 clean: clean-manifests
 

+ 10 - 12
LibOS/shim/test/apps/bash/bash_test.sh

@@ -1,16 +1,14 @@
 #!/bin/bash
+
 times=$1
-rm -rf OUTPUT
 [ $times -gt 0 2> /dev/null ] || times=300
-time for (( c=1; c<=$times; c++ ))
-do
-echo "hello $c" >> OUTPUT
-cp somefile ./testdir/somefile
-rm -rf ./testdir/somefile
-ls ./testdir/ >> OUTPUT
-cat somefile > ./testdir/x
-date >> OUTPUT
-done
 
-#cleanup
-rm ./testdir/x
+for (( c=1; c<=$times; c++ ))
+do
+	echo "hello $c"
+	cp somefile testdir/somefile
+	rm -rf testdir/somefile
+	ls testdir/
+	cat somefile > testdir/x
+	date
+done > OUTPUT

+ 7 - 6
LibOS/shim/test/apps/bash/unixbench.sh

@@ -15,10 +15,11 @@
 ###############################################################################
 ID="@(#)multi.sh:3.4 -- 5/15/91 19:30:24";
 instance=1
-time for (( c=1; c<2; c++ )) do
-while [ $instance -le $1 ]; do
-	/bin/bash "./tst.sh" &
-	instance=`expr $instance + 1`
-done
-wait
+for (( c=1; c<2; c++ ))
+do
+	while [ $instance -le $1 ]; do
+		/bin/bash "./tst.sh" &
+		instance=`expr $instance + 1`
+	done
+	wait
 done

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

@@ -12,21 +12,21 @@ debug: $(targets)
 busybox busybox_gdb: config_for_graphene
 	[ -d $(busybox_src) ] || tar -xjf $(busybox_src).tar.bz2
 	cp config_for_graphene $(busybox_src)/.config
-	cd $(busybox_src) && make $(MAKE_FLAGS)
+	cd $(busybox_src) && $(MAKE) $(MAKE_FLAGS)
 	cp $(busybox_src)/busybox busybox
 	cp $(busybox_src)/busybox_unstripped busybox_gdb
 
 busybox_nofork busybox_nofork_gdb: $(busybox_src) config_for_graphene_nofork
 	[ -d $(busybox_src) ] || tar -xjf $(busybox_src).tar.bz2
 	cp config_for_graphene_nofork $(busybox_src)/.config
-	cd $(busybox_src) && make $(MAKE_FLAGS)
+	cd $(busybox_src) && $(MAKE) $(MAKE_FLAGS)
 	cp $(busybox_src)/busybox busybox_nofork
 	cp $(busybox_src)/busybox_unstripped busybox_nofork_gdb
 
 test: all $(test_targets)
 
 %.manifest: %.manifest.template
-	make -C .. busybox/$@ appdir=busybox/
+	$(MAKE) -C .. busybox/$@ appdir=busybox/
 
 distclean: clean
 	rm -rf $(busybox_src)

+ 18 - 22
LibOS/shim/test/apps/gcc/Makefile

@@ -9,7 +9,7 @@ test_targets = $(c_targets) $(make_targets)
 test: all $(test_targets)
 
 %.manifest: %.manifest.template
-	make -C .. gcc/$@ appdir=gcc/
+	$(MAKE) -C .. gcc/$@ appdir=gcc/
 
 $(c_targets): %: %.c
 	echo "$@ (native):" >> result
@@ -24,29 +24,28 @@ $(c_targets): %: %.c
 
 $(make_targets): %:
 	echo "$@ (native2):" >> result
-	make -C $(dir $@) clean
-	time -a -o result -p make -C $(dir $@) $(notdir $@) CC=g++
+	$(MAKE) -C $(dir $@) clean
+	time -a -o result -p $(MAKE) -C $(dir $@) $(notdir $@) CC=g++
 	echo "$@ (graphene):" >> result
-	make -C $(dir $@) clean
-	time -a -o result -p make -C $(dir $@) $(notdir $@) CC=$(shell pwd)/g++.manifest
+	$(MAKE) -C $(dir $@) clean
+	time -a -o result -p $(MAKE) -C $(dir $@) $(notdir $@) CC=$(shell pwd)/g++.manifest
 
 gcc-local: obj/bin/gcc
 
-GCC_VER = 4.4.5
+GCC_VER = 4.8.4
 BINUTILS_VER = 2.20.1
-GMP_SRC = gmp-4.3.2
+GMP_SRC = gmp-5.1.3
 GMP_OBJ = libgmp.so.3
-PPL_SRC = ppl-0.10.2
+GMPXX_OBJ = libgmpxx.so.4
+PPL_SRC = ppl-1.1
 PPL_OBJ = libppl_c.so.2
-MPFR_SRC = mpfr-2.4.2
+MPFR_SRC = mpfr-3.1.2
 MPFR_OBJ = libmpfr.so.1
-MPC_SRC = mpc-0.8.1
+MPC_SRC = mpc-1.0.1
 MPC_OBJ = libmpc.so.2
 
 LINK_LIBC =
-MAKE = make #-j$(shell grep -c processor /proc/cpuinfo)
 GCC_FLAGS = \
-	--with-build-libsubdir=$(PWD)/../../../../build \
 	--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-gnu-ld \
 	--enable-languages=c,c++ --disable-shared --disable-multilib \
 	--with-gmp=$(PWD)/obj --with-mpfr=$(PWD)/obj --with-mpc=$(PWD)/obj --without-cloog \
@@ -57,10 +56,7 @@ GCC_FLAGS = \
 GCC_MAKE_FLAGS = \
 	LD_LIBRARY_PATH="$(PWD)/obj/lib:/usr/lib:/lib"
 
-export CFLAGS
-export CXXFLAGS="-fpermissive"
-
-obj/bin/gcc: src/gcc-$(GCC_VER) obj/bin/ld $(addprefix obj/lib/,$(GMP_OBJ) $(PPL_OBJ) $(MPFR_OBJ) $(MPC_OBJ))
+obj/bin/gcc: src/gcc-$(GCC_VER) obj/bin/ld $(addprefix obj/lib/,$(GMP_OBJ) $(GMPXX_OBJ) $(PPL_OBJ) $(MPFR_OBJ) $(MPC_OBJ))
 	cd $< && ./configure --prefix=$(PWD)/obj $(GCC_FLAGS)
 	$(MAKE) -C $< $(GCC_MAKE_FLAGS)
 	$(MAKE) -C $< install
@@ -69,15 +65,15 @@ src/gcc-$(GCC_VER): gcc-$(GCC_VER).tar.bz2 src
 	cd src && tar -xjf ../$<
 
 obj/bin/ld: src/binutils-$(BINUTILS_VER)
-	cd $< && ./configure --prefix=$(PWD)/obj $(GCC_FLAGS)
+	cd $< && ./configure --prefix=$(PWD)/obj $(GCC_FLAGS) --enable-shared
 	$(MAKE) -C $< $(GCC_MAKE_FLAGS)
 	$(MAKE) -C $< install
 
 src/binutils-$(BINUTILS_VER): binutils-$(BINUTILS_VER).tar.bz2 src
 	cd src && tar -xjf ../$<
 
-obj/lib/$(GMP_OBJ): src/$(GMP_SRC)
-	cd $< && ./configure --prefix=$(PWD)/obj --enable-shared --enable-cxx \
+obj/lib/$(GMP_OBJ) obj/lib/$(GMPXX_OBJ): src/$(GMP_SRC)
+	cd $< && ./configure --prefix=$(PWD)/obj --enable-cxx --enable-shared \
 	$(LINK_LIBC)
 	$(MAKE) -C $<
 	$(MAKE) -C $< install
@@ -87,7 +83,7 @@ src/$(GMP_SRC): $(GMP_SRC).tar.bz2 src
 
 obj/lib/$(PPL_OBJ): src/$(PPL_SRC) obj/lib/$(GMP_OBJ)
 	cd $< && ./configure --prefix=$(PWD)/obj --with-libgmp-prefix=$(PWD)/obj --enable-shared \
-	$(LINK_LIBC)
+	$(LINK_LIBC) CXXFLAGS=-fpermissive
 	$(MAKE) -C $<
 	$(MAKE) -C $< install
 
@@ -96,7 +92,7 @@ src/$(PPL_SRC): $(PPL_SRC).tar.gz src
 
 obj/lib/$(MPFR_OBJ): src/$(MPFR_SRC) obj/lib/$(GMP_OBJ)
 	cd $< && ./configure --prefix=$(PWD)/obj --enable-shared \
-	$(LINK_LIBC)
+	$(LINK_LIBC) CXXFLAGS=-D__gmp_const=const
 	$(MAKE) -C $<
 	$(MAKE) -C $< install
 
@@ -146,4 +142,4 @@ clean-manifests:
 	rm -rf $(addsuffix .manifest, $(manifests))
 
 clean-garbages:
-	rm -rf cc*.s cc*.c cc*.ld cc*.le cc*.o
+	rm -rf cc*.s cc*.c cc*.ld cc*.le cc*.o a.out

BIN
LibOS/shim/test/apps/gcc/gcc-4.8.4.tar.bz2


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

@@ -1,9 +1,9 @@
 #!$(PAL)
 
-loader.interp = file:$(SHIMROOT)build/elf/ld.so
-loader.preload = file:$(SHIMROOT)build/libsysdb.so
+loader.preload = file:$(SHIMPATH)
 loader.exec = file:$(PWD)obj/bin/gcc
-loader.env.LD_LIBRARY_PATH = /lib:/usr/lib
+loader.env.LD_LIBRARY_PATH = /obj/lib:/lib:/lib/x86_64-linux-gnu
+loader.env.PATH = /obj/bin:/obj/libexec/gcc/x86_64-linux-gnu/4.8.4
 loader.debug_type = none
 
 fs.mount.root.type = chroot
@@ -11,7 +11,7 @@ fs.mount.root.uri = file:
 
 fs.mount.other.lib1.type = chroot
 fs.mount.other.lib1.path = /lib
-fs.mount.other.lib1.uri = file:$(SHIMROOT)build
+fs.mount.other.lib1.uri = file:$(GLIBCDIR)
 
 fs.mount.other.lib2.type = chroot
 fs.mount.other.lib2.path = /lib/x86_64-linux-gnu

BIN
LibOS/shim/test/apps/gcc/gmp-4.3.2.tar.bz2


BIN
LibOS/shim/test/apps/gcc/gmp-5.0.2.tar.bz2


BIN
LibOS/shim/test/apps/gcc/gmp-5.1.3.tar.bz2


BIN
LibOS/shim/test/apps/gcc/mpc-0.8.1.tar.gz


BIN
LibOS/shim/test/apps/gcc/mpc-1.0.1.tar.gz


BIN
LibOS/shim/test/apps/gcc/mpfr-2.4.2.tar.bz2


BIN
LibOS/shim/test/apps/gcc/mpfr-3.1.2.tar.bz2


BIN
LibOS/shim/test/apps/gcc/ppl-0.10.2.tar.gz


BIN
LibOS/shim/test/apps/gcc/ppl-1.1.tar.gz


+ 11 - 11
LibOS/shim/test/apps/lighttpd/Makefile

@@ -9,14 +9,14 @@ conf_files = lighttpd-server.conf lighttpd.conf lighttpd-multithreaded.conf
 all: build/sbin/lighttpd $(manifests) $(conf_files) test-data
 
 %.manifest: %.manifest.template
-	make -C .. lighttpd/$@ appdir=lighttpd/ \
+	$(MAKE) -C .. lighttpd/$@ appdir=lighttpd/ \
 		extra_rules="-e 's:\\\$$\$$(HOST):$(HOST):g' -e 's:\\\$$\$$(PORT):$(PORT):g'"
 
 build/sbin/lighttpd: $(SRCDIR)
 	cd $(SRCDIR) && ./configure --prefix=$(PWD)/build \
 		--without-openssl --without-pcre --without-zlib --without-bzip2
-	make -C $(SRCDIR)
-	make -C $(SRCDIR) install
+	$(MAKE) -C $(SRCDIR)
+	$(MAKE) -C $(SRCDIR) install
 
 $(SRCDIR): %: %.tar.gz
 	tar -xzf $<
@@ -74,24 +74,24 @@ try-download:
 	time -a -o result -p wget -r http://$(HOST):$(PORT)/oscar-web-static/index.php -O wget-out;
 
 test-native: $(test-data)
-	make start-native-server & serverid=$$!; sleep 1; \
-	make try-download TESTNAME=native; \
+	$(MAKE) start-native-server & serverid=$$!; sleep 1; \
+	$(MAKE) try-download TESTNAME=native; \
 	rm wget-out; kill $$serverid
 
 test-multithreaded-native: $(test-data)
-	make start-multithreaded-native-server & serverid=$$!; sleep 1; \
-        make try-download TESTNAME=native; \
+	$(MAKE) start-multithreaded-native-server & serverid=$$!; sleep 1; \
+	$(MAKE) try-download TESTNAME=native; \
         rm wget-out; kill $$serverid
 
 
 test-graphene: $(test-data)
-	make start-graphene-server & serverid=$$!; sleep 1; \
-	make try-download TESTNAME=graphene; \
+	$(MAKE) start-graphene-server & serverid=$$!; sleep 1; \
+	$(MAKE) try-download TESTNAME=graphene; \
 	rm wget-out; kill $$serverid
 
 test-multithreaded-graphene: $(test-data)
-	make start-multithreaded-graphene-server & serverid=$$!; sleep 1; \
-        make try-download TESTNAME=graphene; \
+	$(MAKE) start-multithreaded-graphene-server & serverid=$$!; sleep 1; \
+        $(MAKE) try-download TESTNAME=graphene; \
         rm wget-out; kill $$serverid
 
 

Some files were not shown because too many files changed in this diff