⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elfcore.c

📁 能把所有线程的数据和环境记录到文件,方便调试.
💻 C
📖 第 1 页 / 共 4 页
字号:
  prpsinfo.pr_uid   = sys_geteuid();  prpsinfo.pr_gid   = sys_getegid();  prpsinfo.pr_pid   = main_pid;  prpsinfo.pr_ppid  = sys_getppid();  prpsinfo.pr_pgrp  = sys_getpgrp();  prpsinfo.pr_sid   = sys_getsid(0);  /* scope */ {    char scratch[4096], *cmd = scratch, *ptr;    ssize_t size, len;    int cmd_fd;    memset(&scratch, 0, sizeof(scratch));    size = sys_readlink("/proc/self/exe", scratch, sizeof(scratch));    len = 0;    for (ptr = cmd; *ptr != '\000' && size-- > 0; ptr++) {      if (*ptr == '/') {        cmd = ptr+1;        len = 0;      } else        len++;    }    memcpy(prpsinfo.pr_fname, cmd,           len > sizeof(prpsinfo.pr_fname) ? sizeof(prpsinfo.pr_fname) : len);    NO_INTR(cmd_fd = sys_open("/proc/self/cmdline", O_RDONLY, 0));    if (cmd_fd >= 0) {      char *ptr;      ssize_t size = c_read(cmd_fd, &prpsinfo.pr_psargs,                            sizeof(prpsinfo.pr_psargs), &errno);      for (ptr = prpsinfo.pr_psargs; size-- > 0; ptr++)        if (*ptr == '\000')          *ptr = ' ';      NO_INTR(sys_close(cmd_fd));    }  }  /* Build the PRSTATUS data structure                                       */  /* scope */ {    int stat_fd;    memset(&prstatus, 0, sizeof(struct prstatus));    prstatus.pr_pid     = prpsinfo.pr_pid;    prstatus.pr_ppid    = prpsinfo.pr_ppid;    prstatus.pr_pgrp    = prpsinfo.pr_pgrp;    prstatus.pr_sid     = prpsinfo.pr_sid;    prstatus.pr_fpvalid = 1;    NO_INTR(stat_fd = sys_open("/proc/self/stat", O_RDONLY, 0));    if (stat_fd >= 0) {      char scratch[4096];      ssize_t size = c_read(stat_fd, scratch, sizeof(scratch) - 1, &errno);      if (size >= 0) {        unsigned long tms;        char *ptr = scratch;        scratch[size] = '\000';        /* User time                                                         */        for (i = 13; i && *ptr; ptr++) if (*ptr == ' ') i--;        tms = 0;        while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';        prstatus.pr_utime.tv_sec  = tms / 1000;        prstatus.pr_utime.tv_usec = (tms % 1000) * 1000;        /* System time                                                       */        if (*ptr) ptr++;        tms = 0;        while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';        prstatus.pr_stime.tv_sec  = tms / 1000;        prstatus.pr_stime.tv_usec = (tms % 1000) * 1000;        /* Cumulative user time                                              */        if (*ptr) ptr++;        tms = 0;        while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';        prstatus.pr_cutime.tv_sec  = tms / 1000;        prstatus.pr_cutime.tv_usec = (tms % 1000) * 1000;        /* Cumulative system time                                            */        if (*ptr) ptr++;        tms = 0;        while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';        prstatus.pr_cstime.tv_sec  = tms / 1000;        prstatus.pr_cstime.tv_usec = (tms % 1000) * 1000;        /* Pending signals                                                   */        for (i = 14; i && *ptr; ptr++) if (*ptr == ' ') i--;        while (*ptr && *ptr != ' ')          prstatus.pr_sigpend = 10*prstatus.pr_sigpend + *ptr++ - '0';        /* Held signals                                                      */        if (*ptr) ptr++;        while (*ptr && *ptr != ' ')          prstatus.pr_sigpend = 10*prstatus.pr_sigpend + *ptr++ - '0';      }      NO_INTR(sys_close(stat_fd));    }  }  /* scope */ {    int openmax  = sys_sysconf(_SC_OPEN_MAX);    int pagesize = sys_sysconf(_SC_PAGESIZE);    sigset_t old_signals, blocked_signals;    const char *file_name =      va_arg(ap, const char *);    size_t max_length =      va_arg(ap, size_t);    const char *PATH =      va_arg(ap, const char *);    const struct CoredumperCompressor *compressors =      va_arg(ap, const struct CoredumperCompressor *);    const struct CoredumperCompressor **selected_compressor =      va_arg(ap, const struct CoredumperCompressor **);    if (selected_compressor != NULL) {      /* For now, assume that the core dump is uncompressed; we will later       * override this setting, if we can find a suitable compressor program.       */      *selected_compressor = compressors;      while (*selected_compressor &&             (*selected_compressor)->compressor != NULL) {        ++*selected_compressor;      }    }    if (file_name == NULL) {      /* Create a file descriptor that can be used for reading data from       * our child process. This is a little complicated because we need       * to make sure there is no race condition with other threads       * calling fork() at the same time (this is somewhat mitigated,       * because our threads are supposedly suspended at this time). We       * have to avoid other processes holding our file handles open. We       * can do this by creating the pipe in the child and passing the       * file handle back to the parent.       */      if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0) {        /* Block signals prior to forking. Technically, POSIX requires         * us to call pthread_sigmask(), if this is a threaded         * application. When using glibc, we are OK calling         * sigprocmask(), though. We will end up blocking additional         * signals that libpthread uses internally, but that         * is actually exactly what we want.         *         * Also, POSIX claims that this should not actually be         * necessarily, but reality says otherwise.         */        sigfillset(&blocked_signals);        sys_sigprocmask(SIG_BLOCK, &blocked_signals, &old_signals);                /* Create a new core dump in child process; call sys_fork() in order to         * avoid complications with pthread_atfork() handlers. In the child         * process, we should only ever call system calls.         */        if ((rc = sys_fork()) == 0) {          int  fds[2];                    /* Create a pipe for communicating between processes. If           * necessary, add a compressor to the pipeline.           */          if (CreatePipeline(fds, openmax, PATH, &compressors) < 0 ||              (fds[0] < 0 && sys_pipe(fds) < 0)) {            sys__exit(1);          }                  /* Pass file handle to parent                                      */          /* scope */ {            char cmsg_buf[CMSG_SPACE(sizeof(int))];            struct iovec  iov;            struct msghdr msg;            struct cmsghdr *cmsg;            memset(&iov, 0, sizeof(iov));            memset(&msg, 0, sizeof(msg));            iov.iov_base            = (void *)&compressors;            iov.iov_len             = sizeof(compressors);            msg.msg_iov             = &iov;            msg.msg_iovlen          = 1;            msg.msg_control         = &cmsg_buf;            msg.msg_controllen      = sizeof(cmsg_buf);            cmsg                    = CMSG_FIRSTHDR(&msg);            if (!cmsg) {              /* This can't happen, but static analyzers still complain...   */              sys__exit(1);            }            cmsg->cmsg_level        = SOL_SOCKET;            cmsg->cmsg_type         = SCM_RIGHTS;            cmsg->cmsg_len          = CMSG_LEN(sizeof(int));            *(int *)CMSG_DATA(cmsg) = fds[0];            while (sys_sendmsg(pair[1], &msg, 0) < 0) {              if (errno != EINTR)                sys__exit(1);            }            while (sys_shutdown(pair[1], SHUT_RDWR) < 0) {              if (errno != EINTR)                sys__exit(1);            }          }                    /* Close all file handles other than the write end of our pipe     */          for (i = 0; i < openmax; i++) {            if (i != fds[1]) {              NO_INTR(sys_close(i)); }          }                    /* If compiled without threading support, this is the only           * place where we can request the parent's CPU           * registers. This function is a no-op when threading           * support is available.           */          if (!GetParentRegs(frame, thread_regs, thread_fpregs,                             thread_fpxregs, &hasSSE)) {            sys__exit(1);          }                    CreateElfCore(&fds[1], SimpleWriter, SimpleDone, &prpsinfo, &user,                        &prstatus, threads, pids, thread_regs, thread_fpregs,                        hasSSE ? thread_fpxregs : NULL, pagesize);          NO_INTR(sys_close(fds[1]));          sys__exit(0);          /* Make the compiler happy. We never actually get here.            */          return 0;        } else if (rc > 0) {          #ifndef THREADS          /* Child will double-fork, so reap the process, now.               */          sys_waitpid(rc, (void *)0, __WALL);          #endif        }        /* In the parent                                                     */        sys_sigprocmask(SIG_SETMASK, &old_signals, (void *)0);        NO_INTR(sys_close(pair[1]));                /* Get pipe file handle from child                                   */        /* scope */ {          void *buffer[1];          char cmsg_buf[CMSG_SPACE(sizeof(int))];          struct iovec  iov;          struct msghdr msg;          for (;;) {            int nbytes;            memset(&iov, 0, sizeof(iov));            memset(&msg, 0, sizeof(msg));            iov.iov_base       = buffer;            iov.iov_len        = sizeof(void *);            msg.msg_iov        = &iov;            msg.msg_iovlen     = 1;            msg.msg_control    = &cmsg_buf;            msg.msg_controllen = sizeof(cmsg_buf);            if ((nbytes = sys_recvmsg(pair[0], &msg, 0)) > 0) {              struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);              if (cmsg != NULL && cmsg->cmsg_level == SOL_SOCKET &&                  cmsg->cmsg_type == SCM_RIGHTS)                fd = *(int *)CMSG_DATA(cmsg);              if (nbytes == sizeof(void *) &&                  *buffer != NULL && selected_compressor != NULL)                *selected_compressor = *buffer;              break;            } else if (nbytes == 0 || errno != EINTR) {              break;            }          }        }        sys_shutdown(pair[0], SHUT_RDWR);        NO_INTR(sys_close(pair[0]));      }    } else {      /* Synchronously write the core to a file. If necessary, compress the       * data on the fly. All other threads are suspended during this time.       * In principle, we could use the same code that we used earlier for       * building a core file on the fly. But that results in creating a COW       * copy of the address space (as a result of the call to fork()), and       * some accounting applications are sensitive to the sudden spike in       * memory usage.       * So, instead, we run a single thread and make use of callback       * functions that internally invoke poll() for managing the I/O.       */      int fds[2] = { -1, -1 };      int saved_errno, rc;      const char *suffix = "";      struct WriterFds writer_fds;      ssize_t (*writer)(void *, const void *, size_t);      /* If compiled without threading support, this is the only       * place where we can request the parent's CPU       * registers. This function is a no-op when threading       * support is available.       */      if (!GetParentRegs(frame, thread_regs, thread_fpregs,                         thread_fpxregs, &hasSSE)) {        goto error;      }            /* Create a pipe for communicating between processes. If       * necessary, add a compressor to the pipeline.       */      if (compressors != NULL && compressors->compressor != NULL) {        if (CreatePipeline(fds, openmax, PATH, &compressors) < 0) {          goto error;        }      }      if (selected_compressor) {        *selected_compressor = compressors;      }      writer_fds.out_fd = -1;      if (max_length > 0) {        /* Open the output file. If necessary, pick a filename suffix that         * matches the selected compression type.         */        if (compressors != NULL && compressors->compressor != NULL &&            compressors->suffix != NULL) {          suffix = compressors->suffix;        }        /* scope */ {          char extended_file_name[strlen(file_name) + strlen(suffix) + 1];          strcat(strcpy(extended_file_name, file_name), suffix);          NO_INTR(writer_fds.out_fd = sys_open(extended_file_name,                                               O_WRONLY|O_CREAT|O_TRUNC,                                               0600));          if (writer_fds.out_fd < 0) {            saved_errno = errno;            if (fds[0] >= 0) NO_INTR(sys_close(fds[0]));            if (fds[1] >= 0) NO_INTR(sys_close(fds[1]));            errno = saved_errno;            goto error;          }        }                /* Set up a suitable writer funtion.                                 */        writer_fds.max_length = max_length;        if (fds[0] >= 0) {          /* The PipeWriter() can deal with multi I/O requests on the           * compression pipeline.           */          long flags;          NO_INTR(flags = sys_fcntl(fds[0], F_GETFL, 0));          NO_INTR(sys_fcntl(fds[0], F_SETFL, flags | O_NONBLOCK));          NO_INTR(flags = sys_fcntl(fds[1], F_GETFL, 0));          NO_INTR(sys_fcntl(fds[1], F_SETFL, flags | O_NONBLOCK));          writer_fds.write_fd      = fds[1];          writer_fds.compressed_fd = fds[0];          writer                   = PipeWriter;        } else {          /* If no compression is needed, then we can directly write to the           * file. This avoids quite a bit of unnecessary overhead.           */          writer                   = LimitWriter;        }                rc = CreateElfCore(&writer_fds, writer, PipeDone, &prpsinfo, &user,                           &prstatus, threads, pids, thread_regs,                           thread_fpregs, hasSSE ? thread_fpxregs : NULL,                           pagesize);        if (fds[0] >= 0) {          saved_errno = errno;          /* Close the input side of the compression pipeline, and flush           * the remaining compressed data bytes out to the file.           */          if (fds[1] >= 0) { NO_INTR(sys_close(fds[1])); fds[1] = -1; }          if (FlushPipe(&writer_fds) < 0) {            rc = -1;          } else {            errno = saved_errno;          }        }      } else {        rc = 0;      }      /* Close all remaining open file handles.                              */      saved_errno = errno;      if (writer_fds.out_fd >= 0) NO_INTR(sys_close(writer_fds.out_fd));      if (fds[0] >= 0)            NO_INTR(sys_close(fds[0]));      if (fds[1] >= 0)            NO_INTR(sys_close(fds[1]));      errno = saved_errno;      if (rc < 0) {        goto error;      }      /* If called with a filename, we do not actually return a file handle,       * but instead just signal whether the core file has been written       * successfully.       */      fd = 0;    }  }  ResumeAllProcessThreads(threads, pids);  return fd;error:  /* scope */ {    int saved_errno = errno;    if (fd > 0)      NO_INTR(sys_close(fd));    errno = saved_errno;  }  ResumeAllProcessThreads(threads, pids);  return -1;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -