-static void mprot_handle_pf(int sig, siginfo_t *si, void *unused)
-{
- if (si->si_code == SEGV_MAPERR) {
- model_print("Real Fault at %p\n", si->si_addr);
- print_trace();
- model_print("For debugging, place breakpoint at: %s:%d\n",
- __FILE__, __LINE__);
- exit(EXIT_FAILURE);
- }
- void* addr = ReturnPageAlignedAddress(si->si_addr);
-
- unsigned int backingpage = mprot_snap->lastBackingPage++; //Could run out of pages...
- if (backingpage == mprot_snap->maxBackingPages) {
- model_print("Out of backing pages at %p\n", si->si_addr);
- exit(EXIT_FAILURE);
- }
-
- //copy page
- memcpy(&(mprot_snap->backingStore[backingpage]), addr, sizeof(snapshot_page_t));
- //remember where to copy page back to
- mprot_snap->backingRecords[backingpage].basePtrOfPage = addr;
- //set protection to read/write
- if (mprotect(addr, sizeof(snapshot_page_t), PROT_READ | PROT_WRITE)) {
- perror("mprotect");
- // Handle error by quitting?
- }
-}
-
-static void mprot_snapshot_init(unsigned int numbackingpages,
- unsigned int numsnapshots, unsigned int nummemoryregions,
- unsigned int numheappages, VoidFuncPtr entryPoint)
-{
- /* Setup a stack for our signal handler.... */
- stack_t ss;
- ss.ss_sp = PageAlignAddressUpward(model_malloc(SIGSTACKSIZE + PAGESIZE - 1));
- ss.ss_size = SIGSTACKSIZE;
- ss.ss_flags = 0;
- sigaltstack(&ss, NULL);
-
- struct sigaction sa;
- sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART | SA_ONSTACK;
- sigemptyset(&sa.sa_mask);
- sa.sa_sigaction = mprot_handle_pf;
-#ifdef MAC
- if (sigaction(SIGBUS, &sa, NULL) == -1) {
- model_print("SIGACTION CANNOT BE INSTALLED\n");
- exit(EXIT_FAILURE);
- }
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) == -1) {
- model_print("SIGACTION CANNOT BE INSTALLED\n");
- exit(EXIT_FAILURE);
- }
-
- mprot_snap = new mprot_snapshotter(numbackingpages, numsnapshots, nummemoryregions);
-
- // EVIL HACK: We need to make sure that calls into the mprot_handle_pf method don't cause dynamic links
- // The problem is that we end up protecting state in the dynamic linker...
- // Solution is to call our signal handler before we start protecting stuff...
-
- siginfo_t si;
- memset(&si, 0, sizeof(si));
- si.si_addr = ss.ss_sp;
- mprot_handle_pf(SIGSEGV, &si, NULL);
- mprot_snap->lastBackingPage--; //remove the fake page we copied
-
- void *basemySpace = model_malloc((numheappages + 1) * PAGESIZE);
- void *pagealignedbase = PageAlignAddressUpward(basemySpace);
- user_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
- addMemoryRegionToSnapShot(pagealignedbase, numheappages);
-
- void *base_model_snapshot_space = model_malloc((numheappages + 1) * PAGESIZE);
- pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space);
- model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
- addMemoryRegionToSnapShot(pagealignedbase, numheappages);
-
- entryPoint();
-}
-
-static void mprot_add_to_snapshot(void *addr, unsigned int numPages)
-{
- unsigned int memoryregion = mprot_snap->lastRegion++;
- if (memoryregion == mprot_snap->maxRegions) {
- model_print("Exceeded supported number of memory regions!\n");
- exit(EXIT_FAILURE);
- }
-
- mprot_snap->regionsToSnapShot[memoryregion].basePtr = addr;
- mprot_snap->regionsToSnapShot[memoryregion].sizeInPages = numPages;
-}