root/mtcp/restore_libc.c

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

DEFINITIONS

This source file includes following definitions.
  1. STATIC_TLS_TID_OFFSET
  2. TLSInfo_GetTidOffset
  3. TLSInfo_GetPidOffset
  4. memsubarray
  5. get_tls_segreg
  6. get_tls_base_addr
  7. get_at_sysinfo
  8. TLSInfo_HaveThreadSysinfoOffset
  9. TLSInfo_GetThreadSysinfo
  10. TLSInfo_SetThreadSysinfo
  11. TLSInfo_VerifyPidTid
  12. TLSInfo_UpdatePid
  13. TLSInfo_SaveTLSState
  14. TLSInfo_RestoreTLSState
  15. TLSInfo_PostRestart

   1 /*****************************************************************************
   2  * Copyright (C) 2010-2014 Kapil Arya <kapil@ccs.neu.edu>                    *
   3  * Copyright (C) 2010-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 #include <elf.h>
  20 #include <stdlib.h>
  21 #include <unistd.h>
  22 #include <string.h>
  23 #include <errno.h>
  24 #include <sys/syscall.h>
  25 #include <sys/resource.h>
  26 #include <sys/personality.h>
  27 #include <linux/version.h>
  28 #include <gnu/libc-version.h>
  29 #include "mtcp_sys.h"
  30 #include "restore_libc.h"
  31 #include "tlsutil.h"
  32 
  33 int mtcp_sys_errno;
  34 
  35 #if defined(__x86_64__) || defined(__aarch64__)
  36 # define ELF_AUXV_T Elf64_auxv_t
  37 # define UINT_T uint64_t
  38 #else
  39   // else __i386__ and __arm__
  40 # define ELF_AUXV_T Elf32_auxv_t
  41 # define UINT_T uint32_t
  42 #endif
  43 
  44 extern MYINFO_GS_T myinfo_gs;
  45 
  46 
  47 /* Offset computed (&x.pid - &x) for
  48  *   struct pthread x;
  49  * as found in:  glibc-2.5/nptl/descr.h
  50  * It was 0x4c and 0x48 for pid and tid for i386.
  51  * Roughly, the definition is:
  52  *glibc-2.5/nptl/descr.h:
  53  * struct pthread
  54  * {
  55  *  union {
  56  *   tcbheader_t tcbheader;
  57  *   void *__padding[16];
  58  *  };
  59  *  list_t list;
  60  *  pid_t tid;
  61  *  pid_t pid;
  62  *  ...
  63  * } __attribute ((aligned (TCB_ALIGNMENT)));
  64  *
  65  *glibc-2.5/nptl/sysdeps/pthread/list.h:
  66  * typedef struct list_head
  67  * {
  68  *  struct list_head *next;
  69  *  struct list_head *prev;
  70  * } list_t;
  71  *
  72  * NOTE: glibc-2.10 changes the size of __padding from 16 to 24.  --KAPIL
  73  *
  74  * NOTE: glibc-2.11 further changes the size tcphead_t without updating the
  75  *       size of __padding in struct pthread. We need to add an extra 512 bytes
  76  *       to accommodate this.                                    -- KAPIL
  77  */
  78 
  79 #if !__GLIBC_PREREQ (2,1)
  80 # error "glibc version too old"
  81 #endif
  82 
  83 // NOTE: tls_tid_offset, tls_pid_offset determine offset independently of
  84 //     glibc version.  These STATIC_... versions serve as a double check.
  85 // Calculate offsets of pid/tid in pthread 'struct user_desc'
  86 // The offsets are needed for two reasons:
  87 //  1. glibc pthread functions cache the pid; must update this after restart
  88 //  2. glibc pthread functions cache the tid; pthread functions pass address
  89 //     of cached tid to clone, and MTCP grabs it; But MTCP is still missing
  90 //     the address where pthread cached the tid of motherofall.  So, it can't
  91 //     update.
  92 static int STATIC_TLS_TID_OFFSET()
  93 {
  94   static int offset = -1;
  95   if (offset != -1)
  96     return offset;
  97 
  98   char *ptr;
  99   long major = strtol(gnu_get_libc_version(), &ptr, 10);
 100   long minor = strtol(ptr+1, NULL, 10);
 101   ASSERT (major == 2);
 102 
 103   if (minor >= 11) {
 104 #ifdef __x86_64__
 105     offset = 26*sizeof(void *) + 512;
 106 #else
 107     offset = 26*sizeof(void *);
 108 #endif
 109   } else if (minor == 10) {
 110     offset = 26*sizeof(void *);
 111   } else {
 112     offset = 18*sizeof(void *);
 113   }
 114 
 115   return offset;
 116 }
 117 
 118 #if 0
 119 # if __GLIBC_PREREQ (2,11)
 120 #  ifdef __x86_64__
 121 #   define STATIC_TLS_TID_OFFSET() (26*sizeof(void *) + 512)
 122 #  else
 123 #   define STATIC_TLS_TID_OFFSET() (26*sizeof(void *))
 124 #  endif
 125 
 126 # elif __GLIBC_PREREQ (2,10)
 127 #   define STATIC_TLS_TID_OFFSET() (26*sizeof(void *))
 128 
 129 # else
 130 #   define STATIC_TLS_TID_OFFSET() (18*sizeof(void *))
 131 # endif
 132 #endif
 133 
 134 # define STATIC_TLS_PID_OFFSET() (STATIC_TLS_TID_OFFSET() + sizeof(pid_t))
 135 
 136 /* WHEN WE HAVE CONFIDENCE IN THIS VERSION, REMOVE ALL OTHER __GLIBC_PREREQ
 137  * AND MAKE THIS THE ONLY VERSION.  IT SHOULD BE BACKWARDS COMPATIBLE.
 138  */
 139 /* These function definitions should succeed independently of the glibc version.
 140  * They use get_thread_area() to match (tid, pid) and find offset.
 141  * In other code, on restart, that offset is used to set (tid,pid) to
 142  *   the latest tid and pid of the new thread, instead of the (tid,pid)
 143  *   of the original thread.
 144  * SEE: "struct pthread" in glibc-2.XX/nptl/descr.h for 'struct pthread'.
 145  */
 146 
 147 /* Can remove the unused attribute when this __GLIBC_PREREQ is the only one. */
 148 static char *memsubarray (char *array, char *subarray, size_t len)
 149                                          __attribute__ ((unused));
 150 static uint64_t get_tls_segreg(void);
 151 static void *get_tls_base_addr(void);
 152 extern void **motherofall_saved_sp;
 153 extern ThreadTLSInfo *motherofall_tlsInfo;
 154 
 155 /*****************************************************************************
 156  *
 157  *****************************************************************************/
 158 int TLSInfo_GetTidOffset(void)
 159 
 160 {
 161   static int tid_offset = -1;
 162   if (tid_offset == -1) {
 163     struct {pid_t tid; pid_t pid;} tid_pid;
 164     /* struct pthread has adjacent fields, tid and pid, in that order.
 165      * Try to find at what offset that bit patttern occurs in struct pthread.
 166      */
 167     char * tmp;
 168     tid_pid.tid = mtcp_sys_getpid();
 169     tid_pid.pid = mtcp_sys_getpid();
 170     /* Get entry number of current thread descriptor from its segment register:
 171      * Segment register / 8 is the entry_number for the "thread area", which
 172      * is of type 'struct user_desc'.   The base_addr field of that struct
 173      * points to the struct pthread for the thread with that entry_number.
 174      * The tid and pid are contained in the 'struct pthread'.
 175      *   So, to access the tid/pid fields, first find the entry number.
 176      * Then fill in the entry_number field of an empty 'struct user_desc', and
 177      * get_thread_area(struct user_desc *uinfo) will fill in the rest.
 178      * Then use the filled in base_address field to get the 'struct pthread'.
 179      * The function tcp_get_tls_base_addr() returns this 'struct pthread' addr.
 180      */
 181     void * pthread_desc = get_tls_base_addr();
 182     /* A false hit for tid_offset probably can't happen since a new
 183      * 'struct pthread' is zeroed out before adding tid and pid.
 184      * pthread_desc below is defined as 'struct pthread' in glibc:nptl/descr.h
 185      */
 186     tmp = memsubarray((char *)pthread_desc, (char *)&tid_pid, sizeof(tid_pid));
 187     if (tmp == NULL) {
 188       PRINTF("WARNING: Couldn't find offsets of tid/pid in thread_area.\n"
 189              "  Now relying on the value determined using the\n"
 190              "  glibc version with which DMTCP was compiled.");
 191       return STATIC_TLS_TID_OFFSET();
 192       //mtcp_abort();
 193     }
 194 
 195     tid_offset = tmp - (char *)pthread_desc;
 196     if (tid_offset != STATIC_TLS_TID_OFFSET()) {
 197       PRINTF("WARNING: tid_offset (%d) different from expected.\n"
 198              "  It is possible that DMTCP was compiled with a different\n"
 199              "  glibc version than the one it's dynamically linking to.\n"
 200              "  Continuing anyway.  If this fails, please try again.",
 201              tid_offset);
 202     }
 203     DPRINTF("tid_offset: %d\n", tid_offset);
 204     if (tid_offset % sizeof(int) != 0) {
 205       PRINTF("WARNING: tid_offset is not divisible by sizeof(int).\n"
 206              "  Now relying on the value determined using the\n"
 207              "  glibc version with which DMTCP was compiled.");
 208       return STATIC_TLS_TID_OFFSET();
 209       //mtcp_abort();
 210     }
 211     /* Should we do a double-check, and spawn a new thread and see
 212      *  if its TID matches at this tid_offset?  This would give greater
 213      *  confidence, but for the reasons above, it's probably not necessary.
 214      */
 215   }
 216   return tid_offset;
 217 }
 218 
 219 /*****************************************************************************
 220  *
 221  *****************************************************************************/
 222 int TLSInfo_GetPidOffset(void)
 223 {
 224   static int pid_offset = -1;
 225   struct {pid_t tid; pid_t pid;} tid_pid;
 226   if (pid_offset == -1) {
 227     int tid_offset = TLSInfo_GetTidOffset();
 228     pid_offset = tid_offset + (char *)&(tid_pid.pid) - (char *)&tid_pid;
 229     DPRINTF("pid_offset: %d\n", pid_offset);
 230   }
 231   return pid_offset;
 232 }
 233 
 234 static char *memsubarray (char *array, char *subarray, size_t len)
 235 {
 236    char *i_ptr;
 237    size_t j;
 238    int word1 = *(int *)subarray;
 239    // Assume subarray length is at least sizeof(int) and < 2048.
 240    ASSERT (len >= sizeof(int));
 241    for (i_ptr = array; i_ptr < array+2048; i_ptr++) {
 242      if (*(int *)i_ptr == word1) {
 243        for (j = 0; j < len; j++)
 244          if (i_ptr[j] != subarray[j])
 245            break;
 246         if (j == len)
 247           return i_ptr;
 248      }
 249    }
 250    return NULL;
 251 }
 252 
 253 static uint64_t get_tls_segreg(void)
 254 {
 255   segreg_t tlssegreg;
 256 #ifdef __i386__
 257   asm volatile ("movw %%gs,%0" : "=g" (tlssegreg)); /* any general register */
 258 #elif __x86_64__
 259   /* q = a,b,c,d for i386; 8 low bits of r class reg for x86_64 */
 260   asm volatile ("movw %%fs,%0" : "=g" (tlssegreg));
 261 #elif __arm__
 262   asm volatile ("mrc     p15, 0, %0, c13, c0, 3  @ load_tp_hard\n\t"
 263                 : "=r" (tlssegreg));
 264 #elif defined(__aarch64__)
 265   asm volatile ("mrs  %0, tpidr_el0" : "=r" (tlssegreg) );
 266 #endif
 267   return (uint64_t)tlssegreg;
 268 }
 269 
 270 /*
 271 static int
 272 tls_get_thread_area(void *uinfo, MYINFO_GS_T dummy)
 273 {
 274   asm volatile ("mrs   %0, tpidr_el0" : "=r" (myinfo_gs) );
 275   myinfo_gs = myinfo_gs - 1776;
 276   *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr) = myinfo_gs;
 277    return myinfo_gs;
 278 }
 279 
 280 static int
 281 tls_set_thread_area(void *uinfo, MYINFO_GS_T dummy)
 282 {
 283   myinfo_gs = *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr);
 284   myinfo_gs = myinfo_gs + 1776;
 285   asm volatile ("msr     tpidr_el0, %[gs]" : : [gs] "r" (myinfo_gs) );
 286 }
 287 */
 288 
 289 static void* get_tls_base_addr()
 290 {
 291   struct user_desc gdtentrytls;
 292 
 293   gdtentrytls.entry_number = get_tls_segreg() / 8;
 294   if (tls_get_thread_area(&gdtentrytls, myinfo_gs) == -1) {
 295     PRINTF("Error getting GDT TLS entry: %d\n", errno);
 296     _exit(0);
 297   }
 298   return (void *)(*(unsigned long *)&(gdtentrytls.base_addr));
 299 }
 300 
 301 // Returns value for AT_SYSINFO in kernel's auxv
 302 // Ideally:  mtcp_at_sysinfo() == *mtcp_addr_sysinfo()
 303 // Best if we call this early, before the user makes problems
 304 // by moving environment variables, putting in a weird stack, etc.
 305 extern char **environ;
 306 static void * get_at_sysinfo()
 307 {
 308   void **stack;
 309   int i;
 310   ELF_AUXV_T *auxv;
 311   static char **my_environ = NULL;
 312 
 313   if (my_environ == NULL)
 314     my_environ = environ;
 315 #if 0
 316   // Walk the stack.
 317 #if defined(__i386__) || defined(__x86_64__)
 318   asm volatile (CLEAN_FOR_64_BIT(mov %%ebp, %0\n\t)
 319                 : "=g" (stack) );
 320 #else
 321 # error "current architecture not supported"
 322 #endif
 323   MTCP_PRINTF("stack 2: %p\n", stack);
 324 
 325   // When popping stack/%ebp yields zero, that's the ELF loader telling us that
 326   // this is "_start", the first call frame, which was created by ELF.
 327   for ( ; *stack != NULL; stack = *stack )
 328     ;
 329 
 330   // Go beyond first call frame:
 331   // Next look for &(argv[argc]) on stack;  (argv[argc] == NULL)
 332   for (i = 1; stack[i] != NULL; i++)
 333     ;
 334   // Do some error checks
 335   if ( &(stack[i]) - stack > 100000 ) {
 336     MTCP_PRINTF("Error:  overshot stack\n");
 337     exit(1);
 338   }
 339   stack = &stack[i];
 340 #else
 341   stack = (void **)&my_environ[-1];
 342 
 343   if (*stack != NULL) {
 344     PRINTF("Error: This should be argv[argc] == NULL and it's not. NO &argv[argc]");
 345     _exit(0);
 346   }
 347 #endif
 348   // stack[-1] should be argv[argc-1]
 349   if ( (void **)stack[-1] < stack || (void **)stack[-1] > stack + 100000 ) {
 350     PRINTF("Error: candidate argv[argc-1] failed consistency check");
 351     _exit(0);
 352   }
 353   for (i = 1; stack[i] != NULL; i++)
 354     if ( (void **)stack[i] < stack || (void **)stack[i] > stack + 10000 ) {
 355       PRINTF("Error: candidate argv[i] failed consistency check");
 356       _exit(0);
 357     }
 358   stack = &stack[i+1];
 359   // Now stack is beginning of auxiliary vector (auxv)
 360   // auxv->a_type = AT_NULL marks the end of auxv
 361   for (auxv = (ELF_AUXV_T *)stack; auxv->a_type != AT_NULL; auxv++) {
 362     // mtcp_printf("0x%x 0x%x\n", auxv->a_type, auxv->a_un.a_val);
 363     if ( auxv->a_type == (UINT_T)AT_SYSINFO ) {
 364       //JNOTE("AT_SYSINFO") (&auxv->a_un.a_val) (auxv->a_un.a_val);
 365       return (void *)auxv->a_un.a_val;
 366     }
 367   }
 368   return NULL;  /* Couldn't find AT_SYSINFO */
 369 }
 370 
 371 // From glibc-2.7: glibc-2.7/nptl/sysdeps/i386/tls.h
 372 // SYSINFO_OFFSET given by:
 373 //  #include "glibc-2.7/nptl/sysdeps/i386/tls.h"
 374 //  tcbhead_t dummy;
 375 //  #define SYSINFO_OFFSET &(dummy.sysinfo) - &dummy
 376 
 377 // Some reports say it was 0x18 in past.  Should we also check that?
 378 #define DEFAULT_SYSINFO_OFFSET "0x10"
 379 
 380 int TLSInfo_HaveThreadSysinfoOffset()
 381 {
 382 #ifdef RESET_THREAD_SYSINFO
 383   static int result = -1; // Reset to 0 or 1 on first call.
 384 #else
 385   static int result = 0;
 386 #endif
 387   if (result == -1) {
 388     void * sysinfo;
 389 #if defined(__i386__) || defined(__x86_64__)
 390   asm volatile (CLEAN_FOR_64_BIT(mov %%gs:) DEFAULT_SYSINFO_OFFSET ", %0\n\t"
 391                 : "=r" (sysinfo) );
 392 #elif defined(__arm__)
 393   asm volatile ("mrc     p15, 0, %0, c13, c0, 3  @ load_tp_hard\n\t"
 394                 : "=r" (sysinfo) );
 395 #elif defined(__aarch64__)
 396   asm volatile ("mrs     %0, tpidr_el0" : "=r" (sysinfo) );
 397 #else
 398 # error "current architecture not supported"
 399 #endif
 400     result = (sysinfo == get_at_sysinfo());
 401   }
 402   return result;
 403 }
 404 
 405 // AT_SYSINFO is what kernel calls sysenter address in vdso segment.
 406 // Kernel saves it for each thread in %gs:SYSINFO_OFFSET ??
 407 //  as part of kernel TCB (thread control block) at beginning of TLS ??
 408 void *TLSInfo_GetThreadSysinfo()
 409 {
 410   void *sysinfo;
 411 #if defined(__i386__) || defined(__x86_64__)
 412   asm volatile (CLEAN_FOR_64_BIT(mov %%gs:) DEFAULT_SYSINFO_OFFSET ", %0\n\t"
 413                 : "=r" (sysinfo) );
 414 #elif defined(__arm__)
 415   asm volatile ("mrc     p15, 0, %0, c13, c0, 3  @ load_tp_hard\n\t"
 416                 : "=r" (sysinfo) );
 417 #elif defined(__aarch64__)
 418   asm volatile ("mrs     %0, tpidr_el0" : "=r" (sysinfo) );
 419 #else
 420 # error "current architecture not supported"
 421 #endif
 422   return sysinfo;
 423 }
 424 
 425 void TLSInfo_SetThreadSysinfo(void *sysinfo) {
 426 #if defined(__i386__) || defined(__x86_64__)
 427   asm volatile (CLEAN_FOR_64_BIT(mov %0, %%gs:) DEFAULT_SYSINFO_OFFSET "\n\t"
 428                 : : "r" (sysinfo) );
 429 #elif defined(__arm__)
 430   mtcp_sys_kernel_set_tls(sysinfo);
 431 #elif defined(__aarch64__)
 432   asm volatile ("msr     tpidr_el0, %[gs]" : : [gs] "r" (sysinfo) );
 433 #else
 434 # error "current architecture not supported"
 435 #endif
 436 }
 437 
 438 /*****************************************************************************
 439  *
 440  *
 441  *****************************************************************************/
 442 void TLSInfo_VerifyPidTid(pid_t pid, pid_t tid)
 443 {
 444   pid_t tls_pid, tls_tid;
 445   char *addr = (char*)get_tls_base_addr();
 446   tls_pid = *(pid_t *) (addr + TLSInfo_GetPidOffset());
 447   tls_tid = *(pid_t *) (addr + TLSInfo_GetTidOffset());
 448 
 449   if ((tls_pid != pid) || (tls_tid != tid)) {
 450     PRINTF("ERROR: getpid(%d), tls pid(%d), and tls tid(%d) must all match\n",
 451            (int)mtcp_sys_getpid(), tls_pid, tls_tid);
 452     _exit(0);
 453   }
 454 }
 455 
 456 void TLSInfo_UpdatePid()
 457 {
 458   pid_t  *tls_pid = (pid_t *) ((char*)get_tls_base_addr() +
 459                                TLSInfo_GetPidOffset());
 460   *tls_pid = mtcp_sys_getpid();
 461 }
 462 
 463 /*****************************************************************************
 464  *
 465  *  Save state necessary for TLS restore
 466  *  Linux saves stuff in the GDT, switching it on a per-thread basis
 467  *
 468  *****************************************************************************/
 469 void TLSInfo_SaveTLSState (ThreadTLSInfo *tlsInfo)
 470 {
 471   int i;
 472 
 473 #ifdef __i386__
 474   asm volatile ("movw %%fs,%0" : "=m" (tlsInfo->fs));
 475   asm volatile ("movw %%gs,%0" : "=m" (tlsInfo->gs));
 476 #elif __x86_64__
 477   //asm volatile ("movl %%fs,%0" : "=m" (tlsInfo->fs));
 478   //asm volatile ("movl %%gs,%0" : "=m" (tlsInfo->gs));
 479 #elif __arm__ || __aarch64__
 480   // Follow x86_64 for arm.
 481 #endif
 482 
 483   memset (tlsInfo->gdtentrytls, 0, sizeof tlsInfo->gdtentrytls);
 484 
 485 /* FIXME:  IF %fs IS NOT READ into tlsInfo->fs AT BEGINNING OF THIS
 486  *   FUNCTION, HOW CAN WE REFER TO IT AS  tlsInfo->TLSSEGREG?
 487  *   WHAT IS THIS CODE DOING?
 488  */
 489   i = tlsInfo->TLSSEGREG / 8;
 490   tlsInfo->gdtentrytls[0].entry_number = i;
 491   if (tls_get_thread_area (&(tlsInfo->gdtentrytls[0]), myinfo_gs) == -1) {
 492     PRINTF("Error saving GDT TLS entry: %d\n", errno);
 493     _exit(0);
 494   }
 495   //PRINTF("TLSINFO base_addr: %p \n\n", tlsInfo->gdtentrytls[0].base_addr);
 496 }
 497 
 498 /*****************************************************************************
 499  *
 500  *  Restore the GDT entries that are part of a thread's state
 501  *
 502  *  The kernel provides set_thread_area system call for a thread to alter a
 503  *  particular range of GDT entries, and it switches those entries on a
 504  *  per-thread basis.  So from our perspective, this is per-thread state that is
 505  *  saved outside user addressable memory that must be manually saved.
 506  *
 507  *****************************************************************************/
 508 void TLSInfo_RestoreTLSState(ThreadTLSInfo *tlsInfo)
 509 {
 510   /* Every architecture needs a register to point to the current
 511    * TLS (thread-local storage).  This is where we set it up.
 512    */
 513 
 514   /* Patch 'struct user_desc' (gdtentrytls) of glibc to contain the
 515    * the new pid and tid.
 516    */
 517   *(pid_t *)(*(unsigned long *)&(tlsInfo->gdtentrytls[0].base_addr)
 518              + TLSInfo_GetPidOffset()) = mtcp_sys_getpid();
 519   if (mtcp_sys_kernel_gettid() == mtcp_sys_getpid()) {
 520     *(pid_t *)(*(unsigned long *)&(tlsInfo->gdtentrytls[0].base_addr)
 521                + TLSInfo_GetTidOffset()) = mtcp_sys_getpid();
 522   }
 523 
 524   /* Now pass this to the kernel, so it can adjust the segment descriptor.
 525    * This will make different kernel calls according to the CPU architecture. */
 526   if (tls_set_thread_area (&(tlsInfo->gdtentrytls[0]), myinfo_gs) != 0) {
 527     PRINTF("Error restoring GDT TLS entry: %d\n", errno);
 528     mtcp_abort();
 529   }
 530 
 531   /* Finally, if this is i386, we need to set %gs to refer to the segment
 532    * descriptor that we're using above.  We restore the original pointer.
 533    * For the other architectures (not i386), the kernel call above
 534    * already did the equivalent work of setting up thread registers.
 535    */
 536 #ifdef __i386__
 537   asm volatile ("movw %0,%%fs" : : "m" (tlsInfo->fs));
 538   asm volatile ("movw %0,%%gs" : : "m" (tlsInfo->gs));
 539 #elif __x86_64__
 540 /* Don't directly set fs.  It would only set 32 bits, and we just
 541  *  set the full 64-bit base of fs, using sys_set_thread_area,
 542  *  which called arch_prctl.
 543  *asm volatile ("movl %0,%%fs" : : "m" (tlsInfo->fs));
 544  *asm volatile ("movl %0,%%gs" : : "m" (tlsInfo->gs));
 545  */
 546 #elif __arm__
 547 /* ARM treats this same as x86_64 above. */
 548 #elif defined(__aarch64__)
 549 # warning "TODO: Implementation for ARM64?"
 550 #endif
 551 }
 552 
 553 #if 0
 554 /*****************************************************************************
 555  *
 556  *  The original program's memory and files have been restored
 557  *
 558  *****************************************************************************/
 559 void TLSInfo_PostRestart()
 560 {
 561 
 562   /* Now we can access all of the memory from the time of the checkpoint.
 563    * We will continue to use the temporary stack from mtcp_restart.c, for now.
 564    * When we return from the signal handler, this primary thread will
 565    *   return to its original stack.
 566    */
 567 
 568   /* However, we can only make direct kernel calls, and not libc calls.
 569    * TLSInfo_RestoreTLSState will do the following:
 570    * Step 1:  Patch 'struct user_desc' (gdtentrytls) of glibc to have
 571    *     the new pid and tid.
 572    * Step 2:  Make kernel call to set up the corresponding
 573    *     segment descriptor and/or set any TLS per-thread register.
 574    * Step 3 (for Intel only):  Restore %fs and %gs to refer to the the
 575    *     segment descriptor for this primary thread (only %gs needed for i386).
 576    */
 577   //TLSInfo_RestoreTLSState(motherofall_tlsInfo);
 578 
 579 #if 0
 580   /* FOR DEBUGGING:  Now test if we can make a kernel call through libc. */
 581   mtcp_sys_write(1, "shell ../../util/gdb-add-libdmtcp-symbol-file.py PID PC\n",
 582            sizeof("shell ../../util/gdb-add-libdmtcp-symbol-file.py PID PC\n"));
 583 #if defined(__i386__) || defined(__x86_64__)
 584       asm volatile ("int3"); // Do breakpoint; send SIGTRAP, caught by gdb
 585 #elif defined(__aarch64__)
 586       asm("brk 0");
 587 #else
 588       DPRINTF("IN GDB: interrupt (^C); add-symbol-file ...; (gdb) print x=0\n");
 589       { int x = 1; while (x); } // Stop execution for user to type command.
 590 #endif
 591   int rc = nice(0);
 592 #endif
 593 
 594   // We have now verified that libc functionality is restored.
 595   Thread_RestoreAllThreads();
 596 }
 597 #endif

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