/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- __libc_start_main
- __libc_csu_init
- __libc_csu_fini
- abort
- memset
- memcpy
- main
- restore_brk
- restart_fast_path
- restart_slow_path
- mtcp_simulateread
- restorememoryareas
- unmap_memory_areas_and_restore_vdso
- readmemoryareas
- read_one_memory_area
- adjust_for_smaller_file_size
- restore_libc
- doAreasOverlap
- hasOverlappingMapping
- getTextAddr
- __stack_chk_fail
- __stack_chk_fail_local
- __stack_chk_guard
- _Unwind_Resume
- __gcc_personality_v0
- __intel_security_cookie
- __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 }