Example #1
0
int
dmtcp::findLib_byname(string pattern, string &libpath)
{
  // /proc/self/maps looks like: "<start addr>-<end addr> <mode> <offset>
  // <device> <inode> <libpath>
  // we need to extract libpath
  ProcMapsArea area;
  int ret = -1;

  ProcSelfMaps procSelfMaps;

  while (procSelfMaps.getNextArea(&area)) {
    libpath = area.name;

    // JTRACE("Inspect new /proc/seft/maps line")(libpath);
    if (libpath.size() == 0) {
      // JTRACE("anonymous region, skip");
      continue;
    }

    if (libpath.find(pattern) != string::npos) {
      // This is the library path that contains libtorque.  This is what we
      // need.
      // JTRACE("Found libpath")(pattern)(libpath);
      ret = 0;
      break;
    } else {
      // JTRACE("Libpath not found")(pattern)(libpath);
    }
  }

  return ret;
}
Example #2
0
int
dmtcp::findLib_byfunc(string fname, string &libpath)
{
  // /proc/self/maps looks like: "<start addr>-<end addr> <mode> <offset>
  // <device> <inode> <libpath>
  // We need to extract libpath.
  ProcMapsArea area;
  int ret = -1;

  ProcSelfMaps procSelfMaps;

  while (procSelfMaps.getNextArea(&area)) {
    libpath = area.name;

    // JTRACE("Inspect new /proc/seft/maps line")(libpath);
    if (libpath.size() == 0) {
      // JTRACE("anonymous region, skip");
      continue;
    }

    if (libpath.find("libdmtcp") != string::npos) {
      // JTRACE("dmtcp plugin, skip")(libpath);
      continue;
    }

    void *handle = dlopen(libpath.c_str(), RTLD_LAZY);
    if (handle == NULL) {
      // JTRACE("Cannot open libpath, skip")(libpath);
      continue;
    }
    void *fptr = dlsym(handle, fname.c_str());
    if (fptr != NULL) {
      // Able to find the requested symbol.
      // JTRACE("Found libpath by content:")(fname)(libpath);
      dlclose(handle);
      ret = 0;
      break;
    }
    dlclose(handle);

    // JTRACE("Function not found in Libpath")(fname)(libpath);
  }

  return ret;
}
Example #3
0
void mtcp_writememoryareas(int fd)
{
  Area area;
  //DeviceInfo dev_info;
  int stack_was_seen = 0;

  JTRACE("Performing checkpoint.");

  // Here we want to sync the shared memory pages with the backup files
  // FIXME: Why do we need this?
  //JTRACE("syncing shared memory with backup files");
  //sync_shared_mem();

  /**************************************************************************/
  /* We can't do any more mallocing at this point because malloc stuff is   */
  /* outside the limits of the libmtcp.so image, so it won't get            */
  /* checkpointed, and it's possible that we would checkpoint an            */
  /* inconsistent state.  See note in restoreverything routine.             */
  /**************************************************************************/

  {
    if (nscdAreas == NULL) {
      nscdAreas = new vector<ProcMapsArea>();
    }
    nscdAreas->clear();
    // This block is to ensure that the object is deleted as soon as we leave
    // this block.
    ProcSelfMaps procSelfMaps;
    // Preprocess memory regions as needed.
    while (procSelfMaps.getNextArea(&area)) {
      if (Util::isNscdArea(area)) {
        /* Special Case Handling: nscd is enabled*/
        JNOTE("NSCD daemon shared memory area present.\n"
            "  MTCP will now try to remap this area in read/write mode as\n"
            "  private (zero pages), so that glibc will automatically\n"
            "  stop using NSCD or ask NSCD daemon for new shared area\n")
          (area.name);

        nscdAreas->push_back(area);
      }
    }
  }

  if (procSelfMaps != NULL) {
    // We need to explicitly delete this object here because on restart, we
    // never get back to this function and the object is never released.
    delete procSelfMaps;
  };

  /* Finally comes the memory contents */
  procSelfMaps = new ProcSelfMaps();
  while (procSelfMaps->getNextArea(&area)) {
    // TODO(kapil): Verify that we are not doing any operation that might
    // result in a change of memory layout. For example, a call to JALLOC_NEW
    // will invoke mmap if the JAlloc arena is full. Similarly, for STL objects
    // such as vector and string.

    if ((uint64_t)area.addr == ProcessInfo::instance().restoreBufAddr()) {
      JASSERT(area.size == ProcessInfo::instance().restoreBufLen())
        ((void*) area.addr) (area.size) (ProcessInfo::instance().restoreBufLen());
      continue;
    }

    /* Original comment:  Skip anything in kernel address space ---
     *   beats me what's at FFFFE000..FFFFFFFF - we can't even read it;
     * Added: That's the vdso section for earlier Linux 2.6 kernels.  For later
     *  2.6 kernels, vdso occurs at an earlier address.  If it's unreadable,
     *  then we simply won't copy it.  But let's try to read all areas, anyway.
     * **COMMENTED OUT:** if (area.addr >= HIGHEST_VA) continue;
     */
    /* If it's readable, but it's VDSO, it will be dangerous to restore it.
     * In 32-bit mode later Red Hat RHEL Linux 2.6.9 releases use 0xffffe000,
     * the last page of virtual memory.  Note 0xffffe000 >= HIGHEST_VA
     * implies we're in 32-bit mode.
     */
    if (area.addr >= HIGHEST_VA && area.addr == (VA)0xffffe000)
      continue;
#ifdef __x86_64__
    /* And in 64-bit mode later Red Hat RHEL Linux 2.6.9 releases
     * use 0xffffffffff600000 for VDSO.
     */
    if (area.addr >= HIGHEST_VA && area.addr == (VA)0xffffffffff600000)
      continue;
#endif

    /* Skip anything that has no read or execute permission.  This occurs
     * on one page in a Linux 2.6.9 installation.  No idea why.  This code
     * would also take care of kernel sections since we don't have read/execute
     * permission there.
     *
     * EDIT: We should only skip the "---p" section for the shared libraries.
     * Anonymous memory areas with no rwx permission should be saved regardless
     * as the process might have removed the permissions temporarily and might
     * want to use it later.
     *
     * This happens, for example, with libpthread where the pthread library
     * tries to recycle thread stacks. When a thread exits, libpthread will
     * remove the access permissions from the thread stack and later, when a
     * new thread is created, it will provide the proper permission to this
     * area and use it as the thread stack.
     *
     * If we do not restore this area on restart, the area might be returned by
     * some mmap() call. Later on, when pthread wants to use this area, it will
     * just try to use this area which now belongs to some other object. Even
     * worse, the other object can then call munmap() on that area after
     * libpthread started using it as thread stack causing the parts of thread
     * stack getting munmap()'d from the memory resulting in a SIGSEGV.
     *
     * We suspect that libpthread is using mmap() instead of mprotect to change
     * the permission from "---p" to "rw-p".
     */

    if (!((area.prot & PROT_READ) || (area.prot & PROT_WRITE)) &&
        area.name[0] != '\0') {
      continue;
    }

    if (Util::strStartsWith(area.name, DEV_ZERO_DELETED_STR) ||
        Util::strStartsWith(area.name, DEV_NULL_DELETED_STR)) {
      /* If the process has an area labelled as "/dev/zero (deleted)", we mark
       *   the area as Anonymous and save the contents to the ckpt image file.
       * If this area has a MAP_SHARED attribute, it should be replaced with
       *   MAP_PRIVATE and we won't do any harm because, the /dev/zero file is
       *   an absolute source and sink. Anything written to it will be
       *   discarded and anything read from it will be all zeros.
       * The following call to mmap will create "/dev/zero (deleted)" area
       *         mmap(addr, size, protection, MAP_SHARED | MAP_ANONYMOUS, 0, 0)
       *
       * The above explanation also applies to "/dev/null (deleted)"
       */
      JTRACE("saving area as Anonymous") (area.name);
      area.flags = MAP_PRIVATE | MAP_ANONYMOUS;
      area.name[0] = '\0';
    } else if (Util::isSysVShmArea(area)) {
      JTRACE("saving area as Anonymous") (area.name);
      area.flags = MAP_PRIVATE | MAP_ANONYMOUS;
      area.name[0] = '\0';
    } else if (Util::isNscdArea(area)) {
      /* Special Case Handling: nscd is enabled*/
      area.prot = PROT_READ | PROT_WRITE | MTCP_PROT_ZERO_PAGE;
      area.flags = MAP_PRIVATE | MAP_ANONYMOUS;
      Util::writeAll(fd, &area, sizeof(area));
      continue;
    } else if (Util::isIBShmArea(area)) {
      // TODO: Don't checkpoint infiniband shared area for now.
      continue;
    } else if (Util::strEndsWith(area.name, DELETED_FILE_SUFFIX)) {
      /* Deleted File */
    } else if (area.name[0] == '/' && strstr(&area.name[1], "/") != NULL) {
      /* If an absolute pathname
       * Posix and SysV shared memory segments can be mapped as /XYZ
       */
    }

    /* Force the anonymous flag if it's a private writeable section, as the
     * data has probably changed from the contents of the original images.
     */

    /* We also do this for read-only private sections as it's possible
     * to modify a page there, too (via mprotect).
     */

    if ((area.flags & MAP_PRIVATE) /*&& (area.prot & PROT_WRITE)*/) {
      area.flags |= MAP_ANONYMOUS;
    }

    /* Only write this image if it is not CS_RESTOREIMAGE.
     * Skip any mapping for this image - it got saved as CS_RESTOREIMAGE
     * at the beginning.
     */

    if (strstr (area.name, "[stack]"))
      stack_was_seen = 1;
    // the whole thing comes after the restore image
    writememoryarea(fd, &area, stack_was_seen);
  }

  // Release the memory.
  delete procSelfMaps;
  procSelfMaps = NULL;

  /* It's now safe to do this, since we're done using mtcp_readmapsline() */
  remap_nscd_areas(*nscdAreas);

  area.addr = NULL; // End of data
  area.size = -1; // End of data
  Util::writeAll(fd, &area, sizeof(area));

  /* That's all folks */
  JASSERT(_real_close (fd) == 0);
}
Example #4
0
void FileConnList::prepareShmList()
{
  ProcSelfMaps procSelfMaps;
  ProcMapsArea area;

  shmAreas.clear();
  unlinkedShmAreas.clear();
  missingUnlinkedShmFiles.clear();
  shmAreaConn.clear();
  while (procSelfMaps.getNextArea(&area)) {
    if ((area.flags & MAP_SHARED) && area.prot != 0) {
      if (strstr(area.name, "ptraceSharedInfo") != NULL ||
          strstr(area.name, "dmtcpPidMap") != NULL ||
          strstr(area.name, "dmtcpSharedArea") != NULL ||
          strstr(area.name, "dmtcpSharedArea") != NULL ||
          strstr(area.name, "synchronization-log") != NULL ||
          strstr(area.name, "infiniband") != NULL ||
          strstr(area.name, "synchronization-read-log") != NULL) {
        continue;
      }

      if (Util::isNscdArea(area) ||
          Util::isIBShmArea(area) ||
          Util::isSysVShmArea(area)) {
        continue;
      }

      /* Invalidate shared memory pages so that the next read to it (when we are
       * writing them to ckpt file) will cause them to be reloaded from the
       * disk.
       */
      JWARNING(msync(area.addr, area.size, MS_INVALIDATE) == 0)
        (area.addr) (area.size) (area.name) (area.offset) (JASSERT_ERRNO);

      if (jalib::Filesystem::FileExists(area.name)) {
        if (_real_access(area.name, W_OK) == 0) {
          JTRACE("Will checkpoint shared memory area") (area.name);
          int flags = Util::memProtToOpenFlags(area.prot);
          int fd = _real_open(area.name, flags, 0);
          JASSERT(fd != -1) (JASSERT_ERRNO) (area.name);
          FileConnection *fileConn =
            new FileConnection(area.name, flags, 0, FileConnection::FILE_SHM);
          add(fd, fileConn);
          shmAreas.push_back(area);
          shmAreaConn.push_back(fileConn);
          /* Instead of unmapping the shared memory area, we make it
           * non-readable. This way mtcp will skip the region while at the same
           * time, we prevent JALLOC arena to grow over it.
           *
           * By munmapping the area, a bug was observed on CCIS linux with
           * 'make check-java'. Once the region was unmapped, the JALLOC arena
           * grew over it. During restart, the JALLOC'd area was reclaimed for
           * remapping the shm file without informing JALLOC. Finally, during
           * the second checkpoint cycle, the area was again unmapped and later
           * JALLOC tried to access it, causing a SIGSEGV.
           */
          JASSERT(_real_mmap(area.addr, area.size, PROT_NONE,
                             MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
                             -1, 0) != MAP_FAILED) (JASSERT_ERRNO);
        } else {
          JTRACE("Will not checkpoint shared memory area") (area.name);
        }
      } else {
        // TODO: Shared memory areas with unlinked backing files.
        JASSERT(Util::strEndsWith(area.name, DELETED_FILE_SUFFIX)) (area.name);
        if (Util::strStartsWith(area.name, DEV_ZERO_DELETED_STR) ||
            Util::strStartsWith(area.name, DEV_NULL_DELETED_STR)) {
          JWARNING(false) (area.name)
            .Text("Ckpt/Restart of anonymous shared memory not supported.");
        } else {
          JTRACE("Will recreate shm file on restart.") (area.name);

          // Remove the DELETED suffix.
          area.name[strlen(area.name) - strlen(DELETED_FILE_SUFFIX)] = '\0';
          unlinkedShmAreas.push_back(area);
        }
      }
    }
  }
}