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

📄 elfcore.c

📁 能把所有线程的数据和环境记录到文件,方便调试.
💻 C
📖 第 1 页 / 共 4 页
字号:
      NO_INTR(rc = write(fds->write_fd, buf, len));      if (rc < 0 && errno != EAGAIN) {        return -1;      }      buf += rc;      len -= rc;    }  }  return bytes - len;}/* Flush the remaining data (if any) from the pipe. */static int FlushPipe(struct WriterFds *fds) {  long flags;  NO_INTR(flags = sys_fcntl(fds->compressed_fd, F_GETFL, 0));  NO_INTR(sys_fcntl(fds->compressed_fd, F_SETFL, flags & ~O_NONBLOCK));  while (fds->max_length > 0) {    char    scratch[4096];    size_t  l = sizeof(scratch);    ssize_t rc;    if (l > fds->max_length) {      l = fds->max_length;    }    if (l > 0) {      NO_INTR(rc = read(fds->compressed_fd, scratch, l));      if (rc < 0) {        return -1;      } else if (rc == 0) {        break;      }      if (c_write(fds->out_fd, scratch, rc, &errno) != rc) {        return -1;      }      fds->max_length -= rc;    }  }  return 0;}struct io {  int fd;  unsigned char *data, *end;  unsigned char buf[4096];};/* Reads one character from the "io" file. This function has the same * semantics as fgetc(), but we cannot call any library functions at this * time. */static int GetChar(struct io *io) {  unsigned char *ptr = io->data;  if (ptr == io->end) {    /* Even though we are parsing one character at a time, read in larger     * chunks.     */    ssize_t n = c_read(io->fd, io->buf, sizeof(io->buf), &errno);    if (n <= 0) {      if (n == 0)        errno = 0;      return -1;    }    ptr = &io->buf[0];    io->end = &io->buf[n];  }  io->data = ptr+1;  return *ptr;}/* Place the hex number read from "io" into "*hex".  The first non-hex * character is returned (or -1 in the case of end-of-file). */static int GetHex(struct io *io, size_t *hex) {  int ch;  *hex = 0;  while (((ch = GetChar(io)) >= '0' && ch <= '9') ||         (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))    *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9);  return ch;}/* Computes the amount of leading zeros in a memory region. */static size_t LeadingZeros(int *loopback, void *mem, size_t len,                           size_t pagesize) {  char   buf[pagesize];  size_t count;  char *ptr = buf;  for (count = 0; count < len; ) {    /* Read a page by going through the pipe. Assume that we can write at     * least one page without blocking.     *     * "Normal" kernels do not require this hack. But some of the security     * patches (e.g. grsec) can be configured to disallow read access of     * executable pages. So, directly scanning the memory range would     * result in a segmentation fault.     *     * If we cannot access a page, we assume that it was all zeros.     */    if ((count % pagesize) == 0) {      if (c_write(loopback[1], (char *)mem + count, pagesize, &errno) < 0 ||          c_read(loopback[0],  buf,                 pagesize, &errno) < 0) {        count += pagesize;        continue;      } else {        ptr = buf;      }    }    if (*ptr++) {      break;    }    count++;  }  return count & ~(pagesize-1);}/* Dynamically determines the byte sex of the system. Returns non-zero * for big-endian machines. */static inline int sex() {  int probe = 1;  return !*(char *)&probe;}/* This function is invoked from a seperate process. It has access to a * copy-on-write copy of the parents address space, and all crucial * information about the parent has been computed by the caller. */static int CreateElfCore(void *handle,                         ssize_t (*writer)(void *, const void *, size_t),                         int (*is_done)(void *), prpsinfo *prpsinfo,                         user *user, prstatus *prstatus, int num_threads,                         pid_t *pids, regs *regs, fpregs *fpregs,                         fpxregs *fpxregs, size_t pagesize) {  /* Count the number of mappings in "/proc/self/maps". We are guaranteed   * that this number is not going to change while this function executes.   */  int       rc = -1, num_mappings = 0;  struct io io;  int       loopback[2] = { -1, -1 };  if (sys_pipe(loopback) < 0)    goto done;  io.data = io.end = 0;  NO_INTR(io.fd = sys_open("/proc/self/maps", O_RDONLY, 0));  if (io.fd >= 0) {    int i, ch;    while ((ch = GetChar(&io)) >= 0) {      num_mappings += (ch == '\n');    }    if (errno != 0) {   read_error:      NO_INTR(sys_close(io.fd));      goto done;    }    NO_INTR(sys_close(io.fd));    /* Read all mappings. This requires re-opening "/proc/self/maps"         */    /* scope */ {      static const int PF_ANONYMOUS = 0x80000000;      static const int PF_MASK      = 0x00000007;      struct {        size_t start_address, end_address, offset;        int   flags;      } mappings[num_mappings];      io.data = io.end = 0;      NO_INTR(io.fd = sys_open("/proc/self/maps", O_RDONLY, 0));      if (io.fd >= 0) {        size_t note_align;        /* Parse entries of the form:         * "^[0-9A-F]*-[0-9A-F]* [r-][w-][x-][p-] [0-9A-F]*.*$"         */        for (i = 0; i < num_mappings;) {          static const char * const dev_zero = "/dev/zero";          const char *dev = dev_zero;          int    j, is_device, is_anonymous;          size_t zeros;          memset(&mappings[i], 0, sizeof(mappings[i]));          /* Read start and end addresses                                    */          if (GetHex(&io, &mappings[i].start_address) != '-' ||              GetHex(&io, &mappings[i].end_address)   != ' ')            goto read_error;          /* Read flags                                                      */          while ((ch = GetChar(&io)) != ' ') {            if (ch < 0)              goto read_error;            mappings[i].flags = (mappings[i].flags << 1) | (ch != '-');          }          /* Read offset                                                     */          if ((ch = GetHex(&io, &mappings[i].offset)) != ' ')            goto read_error;          /* Skip over device numbers, and inode number                      */          for (j = 0; j < 2; j++) {            while (ch == ' ') {              ch = GetChar(&io);            }            while (ch != ' ' && ch != '\n') {              if (ch < 0)                goto read_error;              ch = GetChar(&io);            }            while (ch == ' ') {              ch = GetChar(&io);            }            if (ch < 0)              goto read_error;          }          /* Check whether this is a mapping for a device                    */          is_anonymous = (ch == '\n' || ch == '[');          while (*dev && ch == *dev) {            ch = GetChar(&io);            dev++;          }          is_device = dev >= dev_zero + 5 &&                      ((ch != '\n' && ch != ' ') || *dev != '\000');          /* Drop the private/shared bit. This makes the flags compatible with           * the ELF access bits           */          mappings[i].flags    = (mappings[i].flags >> 1) & PF_MASK;          if (is_anonymous) {            mappings[i].flags |= PF_ANONYMOUS;          }          /* Skip until end of line                                          */          while (ch != '\n') {            if (ch < 0)              goto read_error;            ch = GetChar(&io);          }          /* Skip leading zeroed pages (as found in the stack segment)       */          if ((mappings[i].flags & PF_R) && !is_device) {            zeros = LeadingZeros(loopback, (void *)mappings[i].start_address,                         mappings[i].end_address - mappings[i].start_address,                         pagesize);            mappings[i].start_address += zeros;          }          /* Remove mapping, if it was not readable, or completely zero           * anyway. The former is usually the case of stack guard pages, and           * the latter occasionally happens for unused memory.           * Also, be careful not to touch mapped devices.           */          if ((mappings[i].flags & PF_R) == 0 ||              mappings[i].start_address == mappings[i].end_address ||              is_device) {            num_mappings--;          } else {            i++;          }        }        NO_INTR(sys_close(io.fd));        /* Write out the ELF header                                          */        /* scope */ {          Ehdr ehdr;          memset(&ehdr, 0, sizeof(Ehdr));          ehdr.e_ident[0] = ELFMAG0;          ehdr.e_ident[1] = ELFMAG1;          ehdr.e_ident[2] = ELFMAG2;          ehdr.e_ident[3] = ELFMAG3;          ehdr.e_ident[4] = ELF_CLASS;          ehdr.e_ident[5] = sex() ? ELFDATA2MSB : ELFDATA2LSB;          ehdr.e_ident[6] = EV_CURRENT;          ehdr.e_type     = ET_CORE;          ehdr.e_machine  = ELF_ARCH;          ehdr.e_version  = EV_CURRENT;          ehdr.e_phoff    = sizeof(Ehdr);          ehdr.e_ehsize   = sizeof(Ehdr);          ehdr.e_phentsize= sizeof(Phdr);          ehdr.e_phnum    = num_mappings + 1;          ehdr.e_shentsize= sizeof(Shdr);          if (writer(handle, &ehdr, sizeof(Ehdr)) != sizeof(Ehdr)) {            goto done;          }        }        /* Write program headers, starting with the PT_NOTE entry            */        /* scope */ {          Phdr   phdr;          size_t offset   = sizeof(Ehdr) + (num_mappings + 1)*sizeof(Phdr);          size_t filesz   = sizeof(Nhdr) + 4 + sizeof(struct prpsinfo) +                            sizeof(Nhdr) + 4 + sizeof(struct user) +                            num_threads*(                            + sizeof(Nhdr) + 4 + sizeof(struct prstatus)                            + sizeof(Nhdr) + 4 + sizeof(struct fpregs));          #if defined(__i386__) && !defined(__x86_64__)          if (fpxregs) {            filesz       += num_threads*(                             sizeof(Nhdr) + 8 + sizeof(struct fpxregs));          }          #endif          memset(&phdr, 0, sizeof(Phdr));          phdr.p_type     = PT_NOTE;          phdr.p_offset   = offset;          phdr.p_filesz   = filesz;          if (writer(handle, &phdr, sizeof(Phdr)) != sizeof(Phdr)) {            goto done;          }          /* Now follow with program headers for each of the memory segments */          phdr.p_type     = PT_LOAD;          phdr.p_align    = pagesize;          phdr.p_paddr    = 0;          note_align      = phdr.p_align - ((offset+filesz) % phdr.p_align);          if (note_align == phdr.p_align)            note_align    = 0;          offset         += note_align;          for (i = 0; i < num_mappings; i++) {            offset       += filesz;            filesz        = mappings[i].end_address -mappings[i].start_address;            phdr.p_offset = offset;            phdr.p_vaddr  = mappings[i].start_address;            phdr.p_memsz  = filesz;            /* Do not write contents for memory segments that are read-only  */            if ((mappings[i].flags & (PF_ANONYMOUS|PF_W)) == 0) {              filesz      = 0;            }            phdr.p_filesz = filesz;            phdr.p_flags  = mappings[i].flags & PF_MASK;            if (writer(handle, &phdr, sizeof(Phdr)) != sizeof(Phdr)) {              goto done;            }          }        }        /* Write note section                                                */        /* scope */ {          Nhdr nhdr;          memset(&nhdr, 0, sizeof(Nhdr));          nhdr.n_namesz   = 4;          nhdr.n_descsz   = sizeof(struct prpsinfo);          nhdr.n_type     = NT_PRPSINFO;          if (writer(handle, &nhdr, sizeof(Nhdr)) != sizeof(Nhdr) ||              writer(handle, "CORE", 4) != 4 ||              writer(handle, prpsinfo, sizeof(struct prpsinfo)) !=              sizeof(struct prpsinfo)) {            goto done;          }          nhdr.n_descsz   = sizeof(struct user);          nhdr.n_type     = NT_PRXREG;          if (writer(handle, &nhdr, sizeof(Nhdr)) != sizeof(Nhdr) ||              writer(handle, "CORE", 4) != 4 ||              writer(handle, user, sizeof(struct user)) !=sizeof(struct user)){            goto done;          }          for (i = num_threads; i-- > 0; ) {            /* Process status and integer registers                          */            nhdr.n_descsz = sizeof(struct prstatus);            nhdr.n_type   = NT_PRSTATUS;            prstatus->pr_pid = pids[i];            prstatus->pr_reg = regs[i];            if (writer(handle, &nhdr, sizeof(Nhdr)) != sizeof(Nhdr) ||                writer(handle, "CORE", 4) != 4 ||                writer(handle, prstatus, sizeof(struct prstatus)) !=                sizeof(struct prstatus)) {              goto done;            }            /* FPU registers                                                 */            nhdr.n_descsz = sizeof(struct fpregs);            nhdr.n_type   = NT_FPREGSET;            if (writer(handle, &nhdr, sizeof(Nhdr)) != sizeof(Nhdr) ||                writer(handle, "CORE", 4) != 4 ||                writer(handle, fpregs+1, sizeof(struct fpregs)) !=                sizeof(struct fpregs)) {              goto done;            }            /* SSE registers                                                 */            #if defined(__i386__) && !defined( __x86_64__)            /* Linux on x86-64 stores all FPU registers in the SSE structure */            if (fpxregs) {              nhdr.n_namesz = 8;              nhdr.n_descsz = sizeof(struct fpxregs);              nhdr.n_type   = NT_PRXFPREG;              if (writer(handle, &nhdr, sizeof(Nhdr)) != sizeof(Nhdr) ||                  writer(handle, "LINUX\000\000", 8) != 8 ||                  writer(handle, fpxregs+1, sizeof(struct fpxregs)) !=                  sizeof(struct fpxregs)) {                goto done;              }              nhdr.n_namesz = 4;            }

⌨️ 快捷键说明

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