root/mtcp/mtcp_restart.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __libc_start_main
  2. __libc_csu_init
  3. __libc_csu_fini
  4. abort
  5. memset
  6. memcpy
  7. main
  8. restore_brk
  9. restart_fast_path
  10. restart_slow_path
  11. mtcp_simulateread
  12. restorememoryareas
  13. unmap_memory_areas_and_restore_vdso
  14. readmemoryareas
  15. read_one_memory_area
  16. adjust_for_smaller_file_size
  17. restore_libc
  18. doAreasOverlap
  19. hasOverlappingMapping
  20. getTextAddr
  21. __stack_chk_fail
  22. __stack_chk_fail_local
  23. __stack_chk_guard
  24. _Unwind_Resume
  25. __gcc_personality_v0
  26. __intel_security_cookie
  27. __intel_security_check_cookie

   1 /*****************************************************************************
   2  * Copyright (C) 2014 Kapil Arya <kapil@ccs.neu.edu>                         *
   3  * Copyright (C) 2014 Gene Cooperman <gene@ccs.neu.edu>                      *
   4  *                                                                           *
   5  * DMTCP is free software: you can redistribute it and/or                    *
   6  * modify it under the terms of the GNU Lesser General Public License as     *
   7  * published by the Free Software Foundation, either version 3 of the        *
   8  * License, or (at your option) any later version.                           *
   9  *                                                                           *
  10  * DMTCP is distributed in the hope that it will be useful,                  *
  11  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
  12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
  13  * GNU Lesser General Public License for more details.                       *
  14  *                                                                           *
  15  * You should have received a copy of the GNU Lesser General Public          *
  16  * License along with DMTCP.  If not, see <http://www.gnu.org/licenses/>.    *
  17  *****************************************************************************/
  18 
  19 /* Algorithm:
  20  *    When DMTCP originally launched, it mmap'ed a region of memory sufficient
  21  *  to hold the mtcp_restart executable.  This mtcp_restart was compiled
  22  *  as position-independent code (-fPIC).  So, we can copy the code into
  23  *  the memory (holebase) that was reserved for us during DMTCP launch.
  24  *    When we move to high memory, we will also use a temporary stack
  25  *  within the reserved memory (holebase).  Changing from the original
  26  *  mtcp_restart stack to a new stack must be done with care.  All information
  27  *  to be passed will be stored in the variable rinfo, a global struct.
  28  *  When we enter the copy of restorememoryareas() in the reserved memory,
  29  *  we will copy the data of rinfo from the global rinfo data to our
  30  *  new call frame.
  31  *    It is then safe to munmap the old text, data, and stack segments.
  32  *  Once we have done the munmap, we have almost finished bootstrapping
  33  *  ourselves.  We only need to copy the memory sections from the checkpoint
  34  *  image to the original addresses in memory.  Finally, we will then jump
  35  *  back using the old program counter of the checkpoint thread.
  36  *    Now, the copy of mtcp_restart is "dead code", and we will not use
  37  *  this memory region again until we restart from the next checkpoint.
  38  */
  39 
  40 #define _GNU_SOURCE 1
  41 #include <errno.h>
  42 #include <fcntl.h>
  43 #include <sched.h>
  44 #include <signal.h>
  45 #include <stdarg.h>
  46 #include <stdio.h>
  47 #include <stdlib.h>
  48 #include <string.h>
  49 #include <sys/mman.h>
  50 #include <sys/stat.h>
  51 #include <unistd.h>
  52 #include <unistd.h>
  53 #include <sys/types.h>
  54 
  55 #include "mtcp_sys.h"
  56 #include "mtcp_util.ic"
  57 #include "mtcp_check_vdso.ic"
  58 #include "../membarrier.h"
  59 #include "procmapsarea.h"
  60 #include "mtcp_header.h"
  61 #include "tlsutil.h"
  62 
  63 /* The use of NO_OPTIMIZE is deprecated and will be removed, since we
  64  * compile mtcp_restart.c with the -O0 flag already.
  65  */
  66 #ifdef __clang__
  67 # define NO_OPTIMIZE __attribute__((optnone)) /* Supported only in late 2014 */
  68 #else
  69 # define NO_OPTIMIZE __attribute__((optimize(0)))
  70 #endif
  71 
  72 void mtcp_check_vdso(char **environ);
  73 
  74 #define BINARY_NAME "mtcp_restart"
  75 #define BINARY_NAME_M32 "mtcp_restart-32"
  76 
  77 /* struct RestoreInfo to pass all parameters from one function to next.
  78  * This must be global (not on stack) at the time that we jump from
  79  * original stack to copy of restorememoryareas() on new stack.
  80  * This is becasue we will wait until we are in the new call frame and then
  81  * copy the global data into the new call frame.
  82  */
  83 typedef void (*fnptr_t)();
  84 #define STACKSIZE 4*1024*1024
  85   //static long long tempstack[STACKSIZE];
  86 typedef struct RestoreInfo {
  87   int fd;
  88   int stderr_fd;  /* FIXME:  This is never used. */
  89   // int mtcp_sys_errno;
  90   VA text_addr;
  91   size_t text_size;
  92   VA saved_brk;
  93   VA restore_addr;
  94   VA restore_end;
  95   size_t restore_size;
  96   VA vdsoStart;
  97   VA vdsoEnd;
  98   VA vvarStart;
  99   VA vvarEnd;
 100   fnptr_t post_restart;
 101   fnptr_t restorememoryareas_fptr;
 102   //void (*post_restart)();
 103   //void (*restorememoryareas_fptr)();
 104   int use_gdb;
 105   int text_offset;
 106   ThreadTLSInfo motherofall_tls_info;
 107   int tls_pid_offset;
 108   int tls_tid_offset;
 109   MYINFO_GS_T myinfo_gs;
 110 } RestoreInfo;
 111 static RestoreInfo rinfo;
 112 
 113 /* Internal routines */
 114 static void readmemoryareas(int fd);
 115 static int read_one_memory_area(int fd);
 116 static void adjust_for_smaller_file_size(Area *area, int fd);
 117 static void restorememoryareas(RestoreInfo *rinfo_ptr);
 118 static void restore_brk(VA saved_brk, VA restore_begin, VA restore_end);
 119 static void restart_fast_path(void);
 120 static void restart_slow_path(void);
 121 static int doAreasOverlap(VA addr1, size_t size1, VA addr2, size_t size2);
 122 static int hasOverlappingMapping(VA addr, size_t size);
 123 static void getTextAddr(VA *textAddr, size_t *size);
 124 static void mtcp_simulateread(int fd, MtcpHeader *mtcpHdr);
 125 void restore_libc(ThreadTLSInfo *tlsInfo, int tls_pid_offset,
 126                   int tls_tid_offset, MYINFO_GS_T myinfo_gs);
 127 static void unmap_memory_areas_and_restore_vdso(RestoreInfo *rinfo);
 128 
 129 
 130 #define MB 1024*1024
 131 #define RESTORE_STACK_SIZE 5*MB
 132 #define RESTORE_MEM_SIZE 5*MB
 133 #define RESTORE_TOTAL_SIZE (RESTORE_STACK_SIZE+RESTORE_MEM_SIZE)
 134 
 135 //const char service_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
 136 
 137 
 138 int __libc_start_main (int (*main) (int, char **, char **),
 139                        int argc, char **argv,
 140                        void (*init) (void), void (*fini) (void),
 141                        void (*rtld_fini) (void), void *stack_end)
 142 {
 143   int mtcp_sys_errno;
 144   char **envp = argv + argc + 1;
 145   int result = main(argc, argv, envp);
 146   mtcp_sys_exit(result);
 147   (void)mtcp_sys_errno; /* Stop compiler warning about unused variable */
 148   while(1);
 149 }
 150 void __libc_csu_init (int argc, char **argv, char **envp) { }
 151 void __libc_csu_fini (void) { }
 152 void __stack_chk_fail (void);  /* defined at end of file */
 153 void abort(void) { mtcp_abort(); }
 154 /* Implement memcpy() and memset() inside mtcp_restart. Although we are not
 155  * calling memset, the compiler may generate a call to memset() when trying to
 156  * initialize a large array etc.
 157  */
 158 void *memset(void *s, int c, size_t n) {
 159   return mtcp_memset(s, c, n);
 160 }
 161 
 162 void *memcpy(void *dest, const void *src, size_t n) {
 163   return mtcp_memcpy(dest, src, n);
 164 }
 165 
 166 #define shift argv++; argc--;
 167 NO_OPTIMIZE
 168 int main(int argc, char *argv[], char **environ)
 169 {
 170   char *ckptImage = NULL;
 171   MtcpHeader mtcpHdr;
 172   int mtcp_sys_errno;
 173   int simulate = 0;
 174 
 175   if (argc == 1) {
 176     MTCP_PRINTF("***ERROR: This program should not be used directly.\n");
 177     mtcp_sys_exit(1);
 178   }
 179 
 180 #if 0
 181 MTCP_PRINTF("Attach for debugging.");
 182 {int x=1; while(x);}
 183 #endif
 184 
 185 // TODO(karya0): Remove vDSO checks after 2.4.0-rc3 release, and after testing.
 186 // Without mtcp_check_vdso, CentOS 7 fails on dmtcp3, dmtcp5, others.
 187 #define ENABLE_VDSO_CHECK
 188 // TODO(karya0): Remove this block and the corresponding file after sufficient
 189 // testing:  including testing for __i386__, __arm__ and __aarch64__
 190 #ifdef ENABLE_VDSO_CHECK
 191   /* i386 uses random addresses for vdso.  Make sure that its location
 192    * will not conflict with other memory regions.
 193    * (Other arch's may also need this in the future.  So, we do it for all.)
 194    * Note that we may need to keep the old and the new vdso.  We may
 195    * have checkpointed inside gettimeofday inside the old vdso, and the
 196    * kernel, on restart, knows only the new vdso.
 197    */
 198   mtcp_check_vdso(environ);
 199 #endif
 200 
 201   rinfo.fd = -1;
 202   rinfo.use_gdb = 0;
 203   rinfo.text_offset = -1;
 204   shift;
 205   while (argc > 0) {
 206     // Flags for standalone debugging
 207     if (argc == 1) {
 208       // We would use MTCP_PRINTF, but it's also for output of util/readdmtcp.sh
 209       mtcp_printf("Considering '%s' as a ckpt image.\n", argv[0]);
 210       ckptImage = argv[0];
 211       break;
 212     } else if (mtcp_strcmp(argv[0], "--use-gdb") == 0) {
 213       rinfo.use_gdb = 1;
 214       shift;
 215     } else if (mtcp_strcmp(argv[0], "--text-offset") == 0) {
 216       rinfo.text_offset = mtcp_strtol(argv[1]);
 217       shift; shift;
 218     // Flags for call by dmtcp_restart follow here:
 219     } else if (mtcp_strcmp(argv[0], "--fd") == 0) {
 220       rinfo.fd = mtcp_strtol(argv[1]);
 221       shift; shift;
 222     } else if (mtcp_strcmp(argv[0], "--stderr-fd") == 0) {
 223       rinfo.stderr_fd = mtcp_strtol(argv[1]);
 224       shift; shift;
 225     } else if (mtcp_strcmp(argv[0], "--simulate") == 0) {
 226       simulate = 1;
 227       shift;
 228     } else {
 229       MTCP_PRINTF("MTCP Internal Error\n");
 230       return -1;
 231     }
 232   }
 233 
 234   if ((rinfo.fd != -1) ^ (ckptImage == NULL)) {
 235     MTCP_PRINTF("***MTCP Internal Error\n");
 236     mtcp_abort();
 237   }
 238 
 239   if (rinfo.fd != -1) {
 240     mtcp_readfile(rinfo.fd, &mtcpHdr, sizeof mtcpHdr);
 241   } else {
 242     int rc = -1;
 243     rinfo.fd = mtcp_sys_open2(ckptImage, O_RDONLY);
 244     if (rinfo.fd == -1) {
 245       MTCP_PRINTF("***ERROR opening ckpt image (%s); errno: %d\n",
 246                   ckptImage, mtcp_sys_errno);
 247       mtcp_abort();
 248     }
 249     // This assumes that the MTCP header signature is unique.
 250     // We repeatedly look for mtcpHdr because the first header will be
 251     //   for DMTCP.  So, we look deeper for the MTCP header.  The MTCP
 252     //   header is guaranteed to start on an offset that's an integer
 253     //   multiple of sizeof(mtcpHdr), which is currently 4096 bytes.
 254     do {
 255       rc = mtcp_readfile(rinfo.fd, &mtcpHdr, sizeof mtcpHdr);
 256     } while (rc > 0 && mtcp_strcmp(mtcpHdr.signature, MTCP_SIGNATURE) != 0);
 257     if (rc == 0) { /* if end of file */
 258       MTCP_PRINTF("***ERROR: ckpt image doesn't match MTCP_SIGNATURE\n");
 259       return 1;  /* exit with error code 1 */
 260     }
 261   }
 262 
 263   DPRINTF("For debugging:\n"
 264           "    (gdb) add-symbol-file ../../bin/mtcp_restart %p\n",
 265           mtcpHdr.restore_addr + rinfo.text_offset);
 266   if (rinfo.text_offset == -1)
 267     DPRINTF("... but add to the above the result, 1 +"
 268             " `text_offset.sh mtcp_restart`\n    in the mtcp subdirectory.\n");
 269 
 270   if (simulate) {
 271     mtcp_simulateread(rinfo.fd, &mtcpHdr);
 272     return 0;
 273   }
 274 
 275   rinfo.saved_brk = mtcpHdr.saved_brk;
 276   rinfo.restore_addr = mtcpHdr.restore_addr;
 277   rinfo.restore_end = mtcpHdr.restore_addr + mtcpHdr.restore_size;
 278   rinfo.restore_size = mtcpHdr.restore_size;
 279   rinfo.vdsoStart = mtcpHdr.vdsoStart;
 280   rinfo.vdsoEnd = mtcpHdr.vdsoEnd;
 281   rinfo.vvarStart = mtcpHdr.vvarStart;
 282   rinfo.vvarEnd = mtcpHdr.vvarEnd;
 283   rinfo.post_restart = mtcpHdr.post_restart;
 284   rinfo.motherofall_tls_info = mtcpHdr.motherofall_tls_info;
 285   rinfo.tls_pid_offset = mtcpHdr.tls_pid_offset;
 286   rinfo.tls_tid_offset = mtcpHdr.tls_tid_offset;
 287   rinfo.myinfo_gs = mtcpHdr.myinfo_gs;
 288 
 289   restore_brk(rinfo.saved_brk, rinfo.restore_addr,
 290               rinfo.restore_addr + rinfo.restore_size);
 291   getTextAddr(&rinfo.text_addr, &rinfo.text_size);
 292   if (hasOverlappingMapping(rinfo.restore_addr, rinfo.restore_size)) {
 293     MTCP_PRINTF("*** Not Implemented.\n\n");
 294     mtcp_abort();
 295     restart_slow_path();
 296   } else {
 297     restart_fast_path();
 298   }
 299   return 0;  /* Will not reach here, but need to satisfy the compiler */
 300 }
 301 
 302 NO_OPTIMIZE
 303 static void restore_brk(VA saved_brk, VA restore_begin, VA restore_end)
 304 {
 305   int mtcp_sys_errno;
 306   VA current_brk;
 307   VA new_brk;
 308 
 309   /* The kernel (2.6.9 anyway) has a variable mm->brk that we should restore.
 310    * The only access we have is brk() which basically sets mm->brk to the new
 311    * value, but also has a nasty side-effect (as far as we're concerned) of
 312    * mmapping an anonymous section between the old value of mm->brk and the
 313    * value being passed to brk().  It will munmap the bracketed memory if the
 314    * value being passed is lower than the old value.  But if zero, it will
 315    * return the current mm->brk value.
 316    *
 317    * So we're going to restore the brk here.  As long as the current mm->brk
 318    * value is below the static restore region, we're ok because we 'know' the
 319    * restored brk can't be in the static restore region, and we don't care if
 320    * the kernel mmaps something or munmaps something because we're going to wipe
 321    * it all out anyway.
 322    */
 323 
 324   current_brk = mtcp_sys_brk (NULL);
 325   if ((current_brk > restore_begin) &&
 326       (saved_brk < restore_end)) {
 327     MTCP_PRINTF("current_brk %p, saved_brk %p, restore_begin %p,"
 328                 " restore_end %p\n",
 329                  current_brk, saved_brk, restore_begin,
 330                  restore_end);
 331     mtcp_abort ();
 332   }
 333 
 334   new_brk = mtcp_sys_brk (saved_brk);
 335   if (new_brk == (VA)-1) {
 336     MTCP_PRINTF("sbrk(%p): errno: %d (bad heap)\n",
 337                  saved_brk, mtcp_sys_errno );
 338     mtcp_abort();
 339   } else if (new_brk > current_brk) {
 340     // Now unmap the just mapped extended heap. This is to ensure that we don't
 341     // have overlap with the restore region.
 342     if (mtcp_sys_munmap(current_brk, new_brk - current_brk) == -1) {
 343       MTCP_PRINTF("***WARNING: munmap failed; errno: %d\n", mtcp_sys_errno);
 344     }
 345   }
 346   if (new_brk != saved_brk) {
 347     if (new_brk == current_brk && new_brk > saved_brk)
 348       DPRINTF("new_brk == current_brk == %p\n; saved_break, %p,"
 349               " is strictly smaller;\n  data segment not extended.\n",
 350               new_brk, saved_brk);
 351     else {
 352       if (new_brk == current_brk)
 353         MTCP_PRINTF("error: new/current break (%p) != saved break (%p)\n",
 354                     current_brk, saved_brk);
 355       else
 356         MTCP_PRINTF("error: new break (%p) != current break (%p)\n",
 357                     new_brk, current_brk);
 358       //mtcp_abort ();
 359     }
 360   }
 361 }
 362 
 363 NO_OPTIMIZE
 364 static void restart_fast_path()
 365 {
 366   int mtcp_sys_errno;
 367   void *addr = mtcp_sys_mmap(rinfo.restore_addr, rinfo.restore_size,
 368                              PROT_READ|PROT_WRITE|PROT_EXEC,
 369                              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
 370   if (addr == MAP_FAILED) {
 371     MTCP_PRINTF("mmap failed with error; errno: %d\n", mtcp_sys_errno);
 372     mtcp_abort();
 373   }
 374 
 375   size_t offset = (char*)&restorememoryareas - rinfo.text_addr;
 376   rinfo.restorememoryareas_fptr = (fnptr_t)(rinfo.restore_addr + offset);
 377 /* For __arm__
 378  *    should be able to use kernel call: __ARM_NR_cacheflush(start, end, flag)
 379  *    followed by copying new text below, followed by DSB and ISB,
 380  *    to eliminstate need for delay loop.  But this needs more testing.
 381  */
 382   mtcp_memcpy(rinfo.restore_addr, rinfo.text_addr, rinfo.text_size);
 383   mtcp_memcpy(rinfo.restore_addr + rinfo.text_size, &rinfo, sizeof(rinfo));
 384   void *stack_ptr = rinfo.restore_addr + rinfo.restore_size - MB;
 385 
 386 #if defined(__INTEL_COMPILER) && defined(__x86_64__)
 387   memfence();
 388   asm volatile (CLEAN_FOR_64_BIT(mov %0,%%esp;)
 389                 CLEAN_FOR_64_BIT(xor %%ebp,%%ebp)
 390                 : : "g" (stack_ptr) : "memory");
 391   // This is copied from gcc assembly output for:
 392   //     rinfo.restorememoryareas_fptr(&rinfo);
 393   // Intel icc-13.1.3 output uses register rbp here.  It's no longer available.
 394   asm volatile(
 395    "movq    64+rinfo(%%rip), %%rdx;" /* rinfo.restorememoryareas_fptr */
 396    "leaq    rinfo(%%rip), %%rdi;"    /* &rinfo */
 397    "movl    $0, %%eax;"
 398    "call    *%%rdx"
 399    : : );
 400   /* NOTREACHED */
 401 #endif
 402 
 403 #if defined(__arm__) || defined(__aarch64__)
 404 # if 0
 405   memfence();
 406 # else
 407 // FIXME: Replace this code by memfence() for __aarch64__, once it is stable.
 408 /* This delay loop was required for:
 409  *    ARM v7 (rev 3, v71), SAMSUNG EXYNOS5 (Flattened Device Tree)
 410  *    gcc-4.8.1 (Ubuntu pre-release for 14.04) ; Linux 3.13.0+ #54
 411  */
 412 {int x = 10000000;
 413 int y = 1000000000;
 414 for (; x>0; x--) for (; y>0; y--);
 415 }
 416 # endif
 417 #endif
 418 
 419 #if 0
 420   RMB; // refresh instruction cache, for new memory
 421   WMB; // refresh instruction cache, for new memory
 422   IMB; // refresh instruction cache, for new memory
 423 #endif
 424 
 425   DPRINTF("We have copied mtcp_restart to higher address.  We will now\n"
 426           "    jump into a copy of restorememoryareas().\n");
 427 
 428 #if defined(__i386__) || defined(__x86_64__)
 429   asm volatile (CLEAN_FOR_64_BIT(mov %0,%%esp;)
 430                 /* This next assembly language confuses gdb.  Set a future
 431                    future breakpoint, or attach after this point, if in gdb.
 432                    It's here to force a hard error early, in case of a bug.*/
 433                 CLEAN_FOR_64_BIT(xor %%ebp,%%ebp)
 434                 : : "g" (stack_ptr) : "memory");
 435 #elif defined(__arm__)
 436   asm volatile ("mov sp,%0\n\t"
 437                 : : "r" (stack_ptr) : "memory");
 438   /* If we're going to have an error, force a hard error early, to debug. */
 439   asm volatile ("mov fp,#0\n\tmov ip,#0\n\tmov lr,#0" : : );
 440 #elif defined(__aarch64__)
 441   asm volatile ("mov sp,%0\n\t"
 442                 : : "r" (stack_ptr) : "memory");
 443   /* If we're going to have an error, force a hard error early, to debug. */
 444   // FIXME:  Add a hard error here in assembly.
 445 #else
 446 # error "assembly instruction not translated"
 447 #endif
 448 
 449   /* IMPORTANT:  We just changed to a new stack.  The call frame for this
 450    * function on the old stack is no longer available.  The only way to pass
 451    * rinfo into the next function is by passing a pointer to a global variable
 452    * We call restorememoryareas_fptr(), which points to the copy of the
 453    * function in higher memory.  We will be unmapping the original fnc.
 454    */
 455   rinfo.restorememoryareas_fptr(&rinfo);
 456   /* NOTREACHED */
 457 }
 458 
 459 NO_OPTIMIZE
 460 static void restart_slow_path()
 461 {
 462   restorememoryareas(&rinfo);
 463 }
 464 
 465 // Used by util/readdmtcp.sh
 466 // So, we use mtcp_printf to stdout instead of MTCP_PRINTF (diagnosis for DMTCP)
 467 static void mtcp_simulateread(int fd, MtcpHeader *mtcpHdr)
 468 {
 469   int mtcp_sys_errno;
 470 
 471   // Print miscellaneous information:
 472   char buf[MTCP_SIGNATURE_LEN+1];
 473   mtcp_memcpy(buf, mtcpHdr->signature, MTCP_SIGNATURE_LEN);
 474   buf[MTCP_SIGNATURE_LEN] = '\0';
 475   mtcp_printf("\nMTCP: %s", buf);
 476   mtcp_printf("**** mtcp_restart (will be copied here): %p-%p\n",
 477             mtcpHdr->restore_addr, mtcpHdr->restore_addr + mtcpHdr->restore_size);
 478   mtcp_printf("**** DMTCP entry point (ThreadList::postRestart()): %p\n",
 479               mtcpHdr->post_restart);
 480   mtcp_printf("**** brk (sbrk(0)): %p\n", mtcpHdr->saved_brk);
 481   mtcp_printf("**** vdso: %p-%p\n", mtcpHdr->vdsoStart, mtcpHdr->vdsoEnd);
 482   mtcp_printf("**** vvar: %p-%p\n", mtcpHdr->vvarStart, mtcpHdr->vvarEnd);
 483 
 484   Area area;
 485   mtcp_printf("\n**** Listing ckpt image area:\n");
 486   while(1) {
 487     mtcp_readfile(fd, &area, sizeof area);
 488     if (area.size == -1) break;
 489     if ((area.prot & MTCP_PROT_ZERO_PAGE) == 0) {
 490       void *addr = mtcp_sys_mmap(0, area.size, PROT_WRITE | PROT_READ,
 491                                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 492       if (addr == MAP_FAILED) {
 493         MTCP_PRINTF("***Error: mmap failed; errno: %d\n", mtcp_sys_errno);
 494         mtcp_abort();
 495       }
 496       mtcp_readfile(fd, addr, area.size);
 497       if (mtcp_sys_munmap(addr, area.size) == -1) {
 498         MTCP_PRINTF("***Error: munmap failed; errno: %d\n", mtcp_sys_errno);
 499         mtcp_abort();
 500       }
 501     }
 502 
 503     mtcp_printf("%p-%p %c%c%c%c "
 504                // "%x %u:%u %u"
 505                 "          %s\n",
 506                 area.addr, area.addr + area.size,
 507                 ( area.prot & PROT_READ  ? 'r' : '-' ),
 508                 ( area.prot & PROT_WRITE ? 'w' : '-' ),
 509                 ( area.prot & PROT_EXEC  ? 'x' : '-' ),
 510                 ( area.flags & MAP_SHARED ? 's'
 511                   : ( area.flags & MAP_ANONYMOUS ? 'p' : '-' ) ),
 512                 //area.offset, area.devmajor, area.devminor, area.inodenum,
 513                 area.name);
 514   }
 515 }
 516 
 517 NO_OPTIMIZE
 518 static void restorememoryareas(RestoreInfo *rinfo_ptr)
 519 {
 520   int mtcp_sys_errno;
 521 
 522   DPRINTF("Entering copy of restorememoryareas().  Will now unmap old memory"
 523           "\n    and restore memory sections from the checkpoint image.\n");
 524 
 525   DPRINTF("DPRINTF may fail when we unmap, since strings are in rodata.\n"
 526           "But we may be lucky if the strings have been cached by the O/S\n"
 527           "or if compiler uses relative addressing for rodata with -fPIC\n");
 528 
 529   if (rinfo_ptr->use_gdb) {
 530     MTCP_PRINTF("Called with --use-gdb.  A useful command is:\n"
 531                 "    (gdb) info proc mapping");
 532     if (rinfo_ptr->text_offset != -1) {
 533       MTCP_PRINTF("Called with --text-offset 0x%x.  A useful command is:\n"
 534                   "(gdb) add-symbol-file ../../bin/mtcp_restart %p\n",
 535                   rinfo_ptr->text_offset,
 536                   rinfo_ptr->restore_addr + rinfo_ptr->text_offset);
 537 #if defined(__i386__) || defined(__x86_64__)
 538       asm volatile ("int3"); // Do breakpoint; send SIGTRAP, caught by gdb
 539 #else
 540       MTCP_PRINTF("IN GDB: interrupt (^C); add-symbol-file ...; (gdb) print x=0\n");
 541       { int x = 1; while (x); } // Stop execution for user to type command.
 542 #endif
 543     }
 544   }
 545 
 546   RestoreInfo restore_info;
 547   mtcp_memcpy(&restore_info, rinfo_ptr, sizeof (restore_info));
 548 
 549 #if defined(__i386__) || defined(__x86_64__)
 550   asm volatile (CLEAN_FOR_64_BIT(xor %%eax,%%eax ; movw %%ax,%%fs)
 551                                 : : : CLEAN_FOR_64_BIT(eax));
 552 #elif defined(__arm__)
 553   mtcp_sys_kernel_set_tls(0);  /* Uses 'mcr', a kernel-mode instr. on ARM */
 554 #elif defined(__aarch64__)
 555 # warning __FUNCTION__ "TODO: Implementation for ARM64"
 556 #endif
 557 
 558   /* Unmap everything except for vdso, vvar, vsyscall and this image as
 559    *  everything we need is contained in the libmtcp.so image.
 560    * Unfortunately, in later Linuxes, it's important also not to wipe
 561    *   out [vsyscall] if it exists (we may not have permission to remove it).
 562    * Further, if the [vdso] when we restart is different from the old
 563    *   [vdso] that was saved at checkpoint time, then we need to overwrite
 564    *   the old vdso with the new one (using mremap).
 565    *   Similarly for vvar.
 566    */
 567   unmap_memory_areas_and_restore_vdso(&restore_info);
 568 
 569   /* Restore memory areas */
 570   DPRINTF("restoring memory areas\n");
 571   readmemoryareas (restore_info.fd);
 572 
 573   /* Everything restored, close file and finish up */
 574 
 575   DPRINTF("close cpfd %d\n", restore_info.fd);
 576   mtcp_sys_close (restore_info.fd);
 577 
 578   IMB; /* flush instruction cache, since mtcp_restart.c code is now gone. */
 579 
 580   /* Restore libc */
 581   DPRINTF("Memory is now restored.  Will next restore libc internals.\n");
 582   restore_libc(&restore_info.motherofall_tls_info, restore_info.tls_pid_offset,
 583                restore_info.tls_tid_offset, restore_info.myinfo_gs);
 584   /* System calls and libc library calls should now work. */
 585 
 586   DPRINTF("MTCP restore is now complete.  Continuing by jumping to\n"
 587           "  ThreadList:postRestart() back inside libdmtcp.so: %p...\n",
 588           restore_info.post_restart);
 589   restore_info.post_restart();
 590 }
 591 
 592 NO_OPTIMIZE
 593 static void unmap_memory_areas_and_restore_vdso(RestoreInfo *rinfo)
 594 {
 595   /* Unmap everything except this image, vdso, vvar and vsyscall. */
 596   int mtcp_sys_errno;
 597   Area area;
 598   VA vdsoStart = NULL;
 599   VA vdsoEnd = NULL;
 600   VA vvarStart = NULL;
 601   VA vvarEnd = NULL;
 602 
 603   int mapsfd = mtcp_sys_open2("/proc/self/maps", O_RDONLY);
 604   if (mapsfd < 0) {
 605     MTCP_PRINTF("error opening /proc/self/maps; errno: %d\n", mtcp_sys_errno);
 606     mtcp_abort ();
 607   }
 608 
 609   while (mtcp_readmapsline(mapsfd, &area)) {
 610     if (area.addr >= rinfo->restore_addr && area.addr < rinfo->restore_end) {
 611       // Do not unmap this restore image.
 612     } else if (mtcp_strcmp(area.name, "[vdso]") == 0) {
 613       // Do not unmap vdso.
 614       vdsoStart = area.addr;
 615       vdsoEnd = area.endAddr;
 616       DPRINTF("***INFO: vDSO found (%p-%p)\n orignal vDSO: (%p-%p)\n",
 617               area.addr, area.endAddr, rinfo->vdsoStart, rinfo->vdsoEnd);
 618     } else if (mtcp_strcmp(area.name, "[vvar]") == 0) {
 619       // Do not unmap vvar.
 620       vvarStart = area.addr;
 621       vvarEnd = area.endAddr;
 622     } else if (mtcp_strcmp(area.name, "[vsyscall]") == 0) {
 623       // Do not unmap vsyscall.
 624     } else if (mtcp_strcmp(area.name, "[vectors]") == 0) {
 625       // Do not unmap vectors.  (used in Linux 3.10 on __arm__)
 626     } else if (area.size > 0 ) {
 627       DPRINTF("***INFO: munmapping (%p-%p)\n", area.addr, area.endAddr);
 628       if (mtcp_sys_munmap(area.addr, area.size) == -1) {
 629         MTCP_PRINTF("***WARNING: munmap(%s, %x, %p, %d) failed; errno: %d\n",
 630                     area.name, area.flags, area.addr, area.size,
 631                     mtcp_sys_errno);
 632         mtcp_abort();
 633       }
 634       // Rewind and reread maps.
 635       mtcp_sys_lseek(mapsfd, 0, SEEK_SET);
 636     }
 637   }
 638   mtcp_sys_close (mapsfd);
 639 
 640   if ((vdsoStart == vvarEnd && rinfo->vdsoStart != rinfo->vvarEnd) ||
 641       (vvarStart == vdsoEnd && rinfo->vvarStart != rinfo->vdsoEnd)) {
 642     MTCP_PRINTF("***Error: vdso/vvar order was different during ckpt.\n");
 643     mtcp_abort();
 644   }
 645 
 646   if (vdsoEnd - vdsoStart != rinfo->vdsoEnd - rinfo->vdsoStart) {
 647     MTCP_PRINTF("***Error: vdso size mismatch.\n");
 648     mtcp_abort();
 649   }
 650 
 651   if (vvarEnd - vvarStart != rinfo->vvarEnd - rinfo->vvarStart) {
 652     MTCP_PRINTF("***Error: vvar size mismatch.\n");
 653     mtcp_abort();
 654   }
 655 
 656   if (vdsoStart == rinfo->vdsoStart) {
 657     // If the new vDSO is at the same address as the old one, do nothing.
 658     MTCP_ASSERT(vvarStart == rinfo->vvarStart);
 659     return;
 660   }
 661 
 662   // Check for overlap between newer and older vDSO/vvar sections.
 663   if (doAreasOverlap(vdsoStart, vdsoEnd - vdsoStart,
 664                      rinfo->vdsoStart, rinfo->vdsoEnd - rinfo->vdsoStart) ||
 665       doAreasOverlap(vdsoStart, vdsoEnd - vdsoStart,
 666                      rinfo->vvarStart, rinfo->vvarEnd - rinfo->vvarStart) ||
 667       doAreasOverlap(vvarStart, vvarEnd - vvarStart,
 668                      rinfo->vdsoStart, rinfo->vdsoEnd - rinfo->vdsoStart) ||
 669       doAreasOverlap(vdsoStart, vdsoEnd - vdsoStart,
 670                      rinfo->vvarStart, rinfo->vvarEnd - rinfo->vvarStart)) {
 671     MTCP_PRINTF("*** MTCP Error: Overlapping addresses for older and newer\n"
 672                 "                vDSO/vvar sections.\n"
 673                 "      vdsoStart: %p vdsoEnd: %p vvarStart: %p vvarEnd: %p\n"
 674                 "rinfo:vdsoStart: %p vdsoEnd: %p vvarStart: %p vvarEnd: %p\n",
 675                 vdsoStart, vdsoEnd, vvarStart, vvarEnd,
 676                 rinfo->vdsoStart, rinfo->vdsoEnd, rinfo->vvarStart, rinfo->vvarEnd);
 677     mtcp_abort();
 678   }
 679 
 680   if (vdsoStart != NULL) {
 681     void *vdso = mtcp_sys_mremap(vdsoStart,
 682                                  vdsoEnd - vdsoStart,
 683                                  vdsoEnd - vdsoStart,
 684                                  MREMAP_FIXED | MREMAP_MAYMOVE,
 685                                  rinfo->vdsoStart);
 686     if (vdso == MAP_FAILED) {
 687       MTCP_PRINTF("***Error: failed to mremap vdso; errno: %d.\n", mtcp_sys_errno);
 688       mtcp_abort();
 689     }
 690     MTCP_ASSERT(vdso == rinfo->vdsoStart);
 691 
 692 #if defined(__i386__)
 693     // In commit dec2c26c1eb13eb1c12edfdc9e8e811e4cc0e3c2 , the mremap
 694     //   code above was added, and then caused a segfault on restart for
 695     //   __i386__ in CentOS 7.  In that case ENABLE_VDSO_CHECK was not defined.
 696     //   This version was needed in that commit for __i386__
 697     //   (i.e., for multi-arch.sh) to succeed.
 698     // Newer Linux kernels, such as __x86_64__, provide a separate vsyscall segment
 699     //   for kernel calls while using vdso for system calls that can be
 700     //   executed purely in user space through kernel-specific user-space code.
 701     // On older kernels like __x86__, both purposes are squeezed into vdso.
 702     //   Since vdso will use randomized addresses (unlike the standard practice
 703     //   for vsyscall), this implies that kernel calls on __x86__ can go through
 704     //   randomized addresses, and so they need special treatment.
 705     vdso = mtcp_sys_mmap(vdsoStart, vdsoEnd - vdsoStart,
 706                          PROT_EXEC | PROT_WRITE | PROT_READ,
 707                          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
 708     // The new vdso was remapped to the location of the old vdso, since the
 709     //   restarted application code remembers the old vdso address.
 710     //   But for __i386__, a kernel call will go through the old vdso address
 711     //   into the kernel, and then the kernel will return to the new vdso address
 712     //   that was created by this kernel.  So, we need to copy the new vdso
 713     //   code from its current location at the old vdso address back into
 714     //   the new vdso address that was just mmap'ed.
 715     if (vdso == MAP_FAILED) {
 716       MTCP_PRINTF("***Error: failed to mremap vdso; errno: %d\n", mtcp_sys_errno);
 717       mtcp_abort();
 718     }
 719     MTCP_ASSERT(vdso == vdsoStart);
 720     mtcp_memcpy(vdsoStart, rinfo->vdsoStart, vdsoEnd - vdsoStart);
 721 #endif
 722   }
 723 
 724   if (vvarStart != NULL) {
 725     void *vvar = mtcp_sys_mremap(vvarStart,
 726                                  vvarEnd - vvarStart,
 727                                  vvarEnd - vvarStart,
 728                                  MREMAP_FIXED | MREMAP_MAYMOVE,
 729                                  rinfo->vvarStart);
 730     if (vvar == MAP_FAILED) {
 731       MTCP_PRINTF("***Error: failed to mremap vvar; errno: %d.\n", mtcp_sys_errno);
 732       mtcp_abort();
 733     }
 734     MTCP_ASSERT(vvar == rinfo->vvarStart);
 735 
 736 #if defined(__i386__)
 737     vvar = mtcp_sys_mmap(vvarStart, vvarEnd - vvarStart,
 738                          PROT_EXEC | PROT_WRITE | PROT_READ,
 739                          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
 740     if (vvar == MAP_FAILED) {
 741       MTCP_PRINTF("***Error: failed to mremap vvar; errno: %d\n", mtcp_sys_errno);
 742       mtcp_abort();
 743     }
 744     MTCP_ASSERT(vvar == vvarStart);
 745     mtcp_memcpy(vvarStart, rinfo->vvarStart, vvarEnd - vvarStart);
 746 #endif
 747   }
 748 }
 749 
 750 /**************************************************************************
 751  *
 752  *  Read memory area descriptors from checkpoint file
 753  *  Read memory area contents and/or mmap original file
 754  *  Four cases: MAP_ANONYMOUS (if file /proc/.../maps reports file,
 755  *                 handle it as if MAP_PRIVATE and not MAP_ANONYMOUS,
 756  *                 but restore from ckpt image: no copy-on-write);
 757  *               private, currently assumes backing file exists
 758  *               shared, but need to recreate file;
 759  *               shared and file currently exists
 760  *                 (if writeable by us and memory map has write
 761  *                  protection, then write to it from checkpoint file;
 762  *                  else skip ckpt image and map current data of file)
 763  *               NOTE:  Linux option MAP_SHARED|MAP_ANONYMOUS
 764  *                  currently not supported; result is undefined.
 765  *                  If there is an important use case, we will fix this.
 766  *               (NOTE:  mmap requires that if MAP_ANONYMOUS
 767  *                 was not set, then mmap must specify a backing store.
 768  *                 Further, a reference by mmap constitutes a reference
 769  *                 to the file, and so the file cannot truly be deleted
 770  *                 until the process no longer maps it.  So, if we don't
 771  *                 see the file on restart and there is no MAP_ANONYMOUS,
 772  *                 then we have a responsibility to recreate the file.
 773  *                 MAP_ANONYMOUS is not currently POSIX.)
 774  *
 775  **************************************************************************/
 776 
 777 static void readmemoryareas(int fd)
 778 { while (1) {
 779     if (read_one_memory_area(fd) == -1) {
 780       break; /* error */
 781     }
 782   }
 783 #if defined(__arm__) || defined(__aarch64__)
 784   /* On ARM, with gzip enabled, we sometimes see SEGFAULT without this.
 785    * The SEGFAULT occurs within the initial thread, before any user threads
 786    * are unblocked.  WHY DOES THIS HAPPEN?
 787    */
 788   WMB;
 789 #endif
 790 }
 791 
 792 NO_OPTIMIZE
 793 static int read_one_memory_area(int fd)
 794 {
 795   int mtcp_sys_errno;
 796   int imagefd;
 797   void *mmappedat;
 798   int try_skipping_existing_segment = 0;
 799 
 800   /* Read header of memory area into area; mtcp_readfile() will read header */
 801   Area area;
 802   mtcp_readfile(fd, &area, sizeof area);
 803   if (area.size == -1) return -1;
 804 
 805   if (area.name && mtcp_strstr(area.name, "[heap]")
 806       && mtcp_sys_brk(NULL) != area.addr + area.size) {
 807     DPRINTF("WARNING: break (%p) not equal to end of heap (%p)\n",
 808             mtcp_sys_brk(NULL), area.addr + area.size);
 809   }
 810 
 811   // We could have replaced MAP_SHARED with MAP_PRIVATE in writeckpt.cpp
 812   // instead of here. But we do it this way for debugging purposes. This way,
 813   // readdmtcp.sh will still be able to properly list the shared memory areas.
 814   if (area.flags & MAP_SHARED) {
 815     area.flags = area.flags ^ MAP_SHARED;
 816     area.flags = area.flags | MAP_PRIVATE | MAP_ANONYMOUS;
 817   }
 818 
 819   /* Now mmap the data of the area into memory. */
 820 
 821   /* CASE MAPPED AS ZERO PAGE: */
 822   if ((area.prot & MTCP_PROT_ZERO_PAGE) != 0) {
 823     DPRINTF("restoring non-rwx anonymous area, %p bytes at %p\n",
 824             area.size, area.addr);
 825     mmappedat = mtcp_sys_mmap (area.addr, area.size,
 826                                area.prot & ~MTCP_PROT_ZERO_PAGE,
 827                                area.flags | MAP_FIXED, -1, 0);
 828 
 829     if (mmappedat != area.addr) {
 830       DPRINTF("error %d mapping %p bytes at %p\n",
 831               mtcp_sys_errno, area.size, area.addr);
 832       mtcp_abort ();
 833     }
 834   }
 835 
 836   /* CASE MAP_ANONYMOUS (usually implies MAP_PRIVATE):
 837    * For anonymous areas, the checkpoint file contains the memory contents
 838    * directly.  So mmap an anonymous area and read the file into it.
 839    * If file exists, turn off MAP_ANONYMOUS: standard private map
 840    */
 841   else if (area.flags & MAP_ANONYMOUS) {
 842 
 843     /* If there is a filename there, though, pretend like we're mapping
 844      * to it so a new /proc/self/maps will show a filename there like with
 845      * original process.  We only need read-only access because we don't
 846      * want to ever write the file.
 847      */
 848 
 849     imagefd = -1;
 850     if (area.name[0] == '/') { /* If not null string, not [stack] or [vdso] */
 851       imagefd = mtcp_sys_open (area.name, O_RDONLY, 0);
 852       if (imagefd >= 0)
 853         area.flags ^= MAP_ANONYMOUS;
 854     }
 855 
 856     if (area.flags & MAP_ANONYMOUS) {
 857       DPRINTF("restoring anonymous area, %p  bytes at %p\n",
 858               area.size, area.addr);
 859     } else {
 860       DPRINTF("restoring to non-anonymous area from anonymous area,"
 861               " %p bytes at %p from %s + 0x%X\n",
 862               area.size, area.addr, area.name, area.offset);
 863     }
 864 
 865     /* Create the memory area */
 866 
 867     /* POSIX says mmap would unmap old memory.  Munmap never fails if args
 868      * are valid.  Can we unmap vdso and vsyscall in Linux?  Used to use
 869      * mtcp_safemmap here to check for address conflicts.
 870      */
 871     mmappedat = mtcp_sys_mmap (area.addr, area.size, area.prot | PROT_WRITE,
 872                                area.flags, imagefd, area.offset);
 873 
 874     if (mmappedat == MAP_FAILED) {
 875       DPRINTF("error %d mapping %p bytes at %p\n",
 876               mtcp_sys_errno, area.size, area.addr);
 877       if (mtcp_sys_errno == ENOMEM) {
 878         MTCP_PRINTF(
 879           "\n**********************************************************\n"
 880           "****** Received ENOMEM.  Trying to continue, but may fail.\n"
 881           "****** Please run 'free' to see if you have enough swap space.\n"
 882           "**********************************************************\n\n");
 883       }
 884       try_skipping_existing_segment = 1;
 885     }
 886     if (mmappedat != area.addr && !try_skipping_existing_segment) {
 887       MTCP_PRINTF("area at %p got mmapped to %p\n", area.addr, mmappedat);
 888       mtcp_abort ();
 889     }
 890 
 891     if (imagefd >= 0)
 892       adjust_for_smaller_file_size(&area, imagefd);
 893 
 894     /* Close image file (fd only gets in the way) */
 895     if (!(area.flags & MAP_ANONYMOUS)) mtcp_sys_close (imagefd);
 896 
 897     if (try_skipping_existing_segment) {
 898       // This fails on teracluster.  Presumably extra symbols cause overflow.
 899       mtcp_skipfile(fd, area.size);
 900     } else {
 901       /* This mmapfile after prev. mmap is okay; use same args again.
 902        *  Posix says prev. map will be munmapped.
 903        */
 904       /* ANALYZE THE CONDITION FOR DOING mmapfile MORE CAREFULLY. */
 905       mtcp_readfile(fd, area.addr, area.size);
 906       if (!(area.prot & PROT_WRITE)) {
 907         if (mtcp_sys_mprotect (area.addr, area.size, area.prot) < 0) {
 908           MTCP_PRINTF("error %d write-protecting %p bytes at %p\n",
 909                       mtcp_sys_errno, area.size, area.addr);
 910           mtcp_abort ();
 911         }
 912       }
 913     }
 914   }
 915 
 916   /* CASE NOT MAP_ANONYMOUS:
 917    * Otherwise, we mmap the original file contents to the area.
 918    * This case is now delegated to DMTCP.  Nothing to do for MTCP.
 919    */
 920 
 921   else { /* Internal error. */
 922     MTCP_ASSERT(0);
 923   }
 924   return 0;
 925 }
 926 
 927 NO_OPTIMIZE
 928 static void adjust_for_smaller_file_size(Area *area, int fd)
 929 {
 930   int mtcp_sys_errno;
 931   off_t curr_size = mtcp_sys_lseek(fd, 0, SEEK_END);
 932   if (curr_size == -1) return;
 933   if (area->offset + area->size > curr_size) {
 934     size_t diff_in_size = (area->offset + area->size) - curr_size;
 935     size_t anon_area_size = (diff_in_size + MTCP_PAGE_SIZE - 1)
 936                              & MTCP_PAGE_MASK;
 937     VA anon_start_addr = area->addr + (area->size - anon_area_size);
 938 
 939     DPRINTF("For %s, current size (%ld) smaller than original (%ld).\n"
 940             "mmap()'ng the difference as anonymous.\n",
 941             area->name, curr_size, area->size);
 942     VA mmappedat = mtcp_sys_mmap (anon_start_addr, anon_area_size,
 943                                   area->prot | PROT_WRITE,
 944                                   MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
 945                                   -1, 0);
 946 
 947     if (mmappedat == MAP_FAILED) {
 948       DPRINTF("error %d mapping %p bytes at %p\n",
 949               mtcp_sys_errno, anon_area_size, anon_start_addr);
 950     }
 951     if (mmappedat != anon_start_addr) {
 952       MTCP_PRINTF("area at %p got mmapped to %p\n", anon_start_addr, mmappedat);
 953       mtcp_abort ();
 954     }
 955   }
 956 }
 957 
 958 
 959 /*****************************************************************************
 960  *
 961  *  Restore the GDT entries that are part of a thread's state
 962  *
 963  *  The kernel provides set_thread_area system call for a thread to alter a
 964  *  particular range of GDT entries, and it switches those entries on a
 965  *  per-thread basis.  So from our perspective, this is per-thread state that is
 966  *  saved outside user addressable memory that must be manually saved.
 967  *
 968  *****************************************************************************/
 969 void restore_libc(ThreadTLSInfo *tlsInfo, int tls_pid_offset,
 970                   int tls_tid_offset, MYINFO_GS_T myinfo_gs)
 971 {
 972   int mtcp_sys_errno;
 973   /* Every architecture needs a register to point to the current
 974    * TLS (thread-local storage).  This is where we set it up.
 975    */
 976 
 977   /* Patch 'struct user_desc' (gdtentrytls) of glibc to contain the
 978    * the new pid and tid.
 979    */
 980   *(pid_t *)(*(unsigned long *)&(tlsInfo->gdtentrytls[0].base_addr)
 981              + tls_pid_offset) = mtcp_sys_getpid();
 982   if (mtcp_sys_kernel_gettid() == mtcp_sys_getpid()) {
 983     *(pid_t *)(*(unsigned long *)&(tlsInfo->gdtentrytls[0].base_addr)
 984                + tls_tid_offset) = mtcp_sys_getpid();
 985   }
 986 
 987   /* Now pass this to the kernel, so it can adjust the segment descriptor.
 988    * This will make different kernel calls according to the CPU architecture. */
 989   if (tls_set_thread_area (&(tlsInfo->gdtentrytls[0]), myinfo_gs) != 0) {
 990     MTCP_PRINTF("Error restoring GDT TLS entry; errno: %d\n", mtcp_sys_errno);
 991     mtcp_abort();
 992   }
 993 
 994   /* Finally, if this is i386, we need to set %gs to refer to the segment
 995    * descriptor that we're using above.  We restore the original pointer.
 996    * For the other architectures (not i386), the kernel call above
 997    * already did the equivalent work of setting up thread registers.
 998    */
 999 #ifdef __i386__
1000   asm volatile ("movw %0,%%fs" : : "m" (tlsInfo->fs));
1001   asm volatile ("movw %0,%%gs" : : "m" (tlsInfo->gs));
1002 #elif __x86_64__
1003 /* Don't directly set fs.  It would only set 32 bits, and we just
1004  *  set the full 64-bit base of fs, using sys_set_thread_area,
1005  *  which called arch_prctl.
1006  *asm volatile ("movl %0,%%fs" : : "m" (tlsInfo->fs));
1007  *asm volatile ("movl %0,%%gs" : : "m" (tlsInfo->gs));
1008  */
1009 #elif defined(__arm__) || defined(__aarch64__)
1010 /* ARM treats this same as x86_64 above. */
1011 #endif
1012 }
1013 
1014 NO_OPTIMIZE
1015 static int doAreasOverlap(VA addr1, size_t size1, VA addr2, size_t size2)
1016 {
1017   VA end1 = (char*)addr1 + size1;
1018   VA end2 = (char*)addr2 + size2;
1019   return (addr1 >= addr2 && addr1 < end2) || (addr2 >= addr1 && addr2 < end1);
1020 }
1021 
1022 NO_OPTIMIZE
1023 static int hasOverlappingMapping(VA addr, size_t size)
1024 {
1025   int mtcp_sys_errno;
1026   int ret = 0;
1027   Area area;
1028   int mapsfd = mtcp_sys_open2("/proc/self/maps", O_RDONLY);
1029   if (mapsfd < 0) {
1030     MTCP_PRINTF("error opening /proc/self/maps: errno: %d\n", mtcp_sys_errno);
1031     mtcp_abort ();
1032   }
1033 
1034   while (mtcp_readmapsline(mapsfd, &area)) {
1035     if (doAreasOverlap(addr, size, area.addr, area.size)) {
1036       ret = 1;
1037       break;
1038     }
1039   }
1040   mtcp_sys_close (mapsfd);
1041   return ret;
1042 }
1043 
1044 NO_OPTIMIZE
1045 static void getTextAddr(VA *text_addr, size_t *size)
1046 {
1047   int mtcp_sys_errno;
1048   Area area;
1049   VA this_fn = (VA) &getTextAddr;
1050   int mapsfd = mtcp_sys_open2("/proc/self/maps", O_RDONLY);
1051   if (mapsfd < 0) {
1052     MTCP_PRINTF("error opening /proc/self/maps: errno: %d\n", mtcp_sys_errno);
1053     mtcp_abort ();
1054   }
1055 
1056   while (mtcp_readmapsline(mapsfd, &area)) {
1057     if ((mtcp_strendswith(area.name, BINARY_NAME) ||
1058          mtcp_strendswith(area.name, BINARY_NAME_M32)) &&
1059         (area.prot & PROT_EXEC) &&
1060         /* On ARM/Ubuntu 14.04, mtcp_restart is mapped twice with RWX
1061          * permissions. Not sure why? Here is an example:
1062          *
1063          * 00008000-00010000 r-xp 00000000 b3:02 144874     .../bin/mtcp_restart
1064          * 00017000-00019000 rwxp 00007000 b3:02 144874     .../bin/mtcp_restart
1065          * befdf000-bf000000 rwxp 00000000 00:00 0          [stack]
1066          * ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]
1067          */
1068         (area.addr < this_fn && (area.addr + area.size) > this_fn)) {
1069       *text_addr = area.addr;
1070       *size = area.size;
1071       break;
1072     }
1073   }
1074   mtcp_sys_close (mapsfd);
1075 }
1076 
1077 // gcc can generate calls to these.
1078 // Eventually, we'll isolate the PIC code in a library, and this can go away.
1079 void __stack_chk_fail(void)
1080 {
1081   int mtcp_sys_errno;
1082   MTCP_PRINTF("ERROR: Stack Overflow detected.\n");
1083   mtcp_abort();
1084 }
1085 
1086 void __stack_chk_fail_local(void)
1087 {
1088   int mtcp_sys_errno;
1089   MTCP_PRINTF("ERROR: Stack Overflow detected.\n");
1090   mtcp_abort();
1091 }
1092 
1093 void __stack_chk_guard(void)
1094 {
1095   int mtcp_sys_errno;
1096   MTCP_PRINTF("ERROR: Stack Overflow detected.\n");
1097   mtcp_abort();
1098 }
1099 
1100 void _Unwind_Resume(void)
1101 {
1102   int mtcp_sys_errno;
1103   MTCP_PRINTF("MTCP Internal Error: %s Not Implemented.\n", __FUNCTION__);
1104   mtcp_abort();
1105 }
1106 
1107 void __gcc_personality_v0(void)
1108 {
1109   int mtcp_sys_errno;
1110   MTCP_PRINTF("MTCP Internal Error: %s Not Implemented.\n", __FUNCTION__);
1111   mtcp_abort();
1112 }
1113 
1114 void __intel_security_cookie(void)
1115 {
1116   int mtcp_sys_errno;
1117   MTCP_PRINTF("MTCP Internal Error: %s Not Implemented.\n", __FUNCTION__);
1118   mtcp_abort();
1119 }
1120 
1121 void __intel_security_check_cookie(void)
1122 {
1123   int mtcp_sys_errno;
1124   MTCP_PRINTF("MTCP Internal Error: %s Not Implemented.\n", __FUNCTION__);
1125   mtcp_abort();
1126 }

/* [<][>][^][v][top][bottom][index][help] */