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

📄 elfcore.c

📁 能把所有线程的数据和环境记录到文件,方便调试.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright (c) 2005-2007, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * *     * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. *     * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. *     * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * --- * Author: Markus Gutschke */#include "elfcore.h"#if defined DUMPER#include <elf.h>#include <fcntl.h>#include <limits.h>#include <pthread.h>#include <signal.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <sys/poll.h>#include <sys/prctl.h>#include <sys/socket.h>#include <sys/sysctl.h>#include <sys/time.h>#include <sys/uio.h>#include <sys/wait.h>#include "google/coredumper.h"#include "linux_syscall_support.h"#include "linuxthreads.h"#include "thread_lister.h"#ifndef CLONE_UNTRACED#define CLONE_UNTRACED 0x00800000#endif/* Data structures found in x86-32/64 and ARM core dumps on Linux; similar * data structures are defined in /usr/include/{linux,asm}/... but those * headers conflict with the rest of the libc headers. So we cannot * include them here. */#if defined(__i386__) || defined(__x86_64__)  #if !defined(__x86_64__)    typedef struct fpregs {     /* FPU registers                             */      uint32_t  cwd;      uint32_t  swd;      uint32_t  twd;      uint32_t  fip;      uint32_t  fcs;      uint32_t  foo;      uint32_t  fos;      uint32_t  st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes     */    } fpregs;    typedef struct fpxregs {    /* SSE registers                             */    #define FPREGS fpxregs  #else    typedef struct fpxregs {    /* x86-64 stores FPU registers in SSE struct */    } fpxregs;    typedef struct fpregs {     /* FPU registers                             */    #define FPREGS fpregs  #endif    uint16_t  cwd;    uint16_t  swd;    uint16_t  twd;    uint16_t  fop;    uint32_t  fip;    uint32_t  fcs;    uint32_t  foo;    uint32_t  fos;    uint32_t  mxcsr;    uint32_t  mxcsr_mask;    uint32_t  st_space[32];     /*  8*16 bytes for each FP-reg  = 128 bytes  */    uint32_t  xmm_space[64];    /* 16*16 bytes for each XMM-reg = 128 bytes  */    uint32_t  padding[24];  } FPREGS;  #undef FPREGS  #define regs i386_regs        /* General purpose registers                 */#elif defined(__ARM_ARCH_3__)  typedef struct fpxregs {      /* No extended FPU registers on ARM          */  } fpxregs;  typedef struct fpregs {       /* FPU registers                             */    struct fp_reg {      unsigned int sign1:1;      unsigned int unused:15;      unsigned int sign2:1;      unsigned int exponent:14;      unsigned int j:1;      unsigned int mantissa1:31;      unsigned int mantissa0:32;    } fpregs[8];    unsigned int   fpsr:32;    unsigned int   fpcr:32;    unsigned char  ftype[8];    unsigned int   init_flag;  } fpregs;  #define regs arm_regs         /* General purpose registers                 */#endiftypedef struct elf_timeval {    /* Time value with microsecond resolution    */  long tv_sec;                  /* Seconds                                   */  long tv_usec;                 /* Microseconds                              */} elf_timeval;typedef struct elf_siginfo {    /* Information about signal (unused)         */  int32_t si_signo;             /* Signal number                             */  int32_t si_code;              /* Extra code                                */  int32_t si_errno;             /* Errno                                     */} elf_siginfo;typedef struct prstatus {       /* Information about thread; includes CPU reg*/  elf_siginfo    pr_info;       /* Info associated with signal               */  uint16_t       pr_cursig;     /* Current signal                            */  unsigned long  pr_sigpend;    /* Set of pending signals                    */  unsigned long  pr_sighold;    /* Set of held signals                       */  pid_t          pr_pid;        /* Process ID                                */  pid_t          pr_ppid;       /* Parent's process ID                       */  pid_t          pr_pgrp;       /* Group ID                                  */  pid_t          pr_sid;        /* Session ID                                */  elf_timeval    pr_utime;      /* User time                                 */  elf_timeval    pr_stime;      /* System time                               */  elf_timeval    pr_cutime;     /* Cumulative user time                      */  elf_timeval    pr_cstime;     /* Cumulative system time                    */  regs           pr_reg;        /* CPU registers                             */  uint32_t       pr_fpvalid;    /* True if math co-processor being used      */} prstatus;typedef struct prpsinfo {       /* Information about process                 */  unsigned char  pr_state;      /* Numeric process state                     */  char           pr_sname;      /* Char for pr_state                         */  unsigned char  pr_zomb;       /* Zombie                                    */  signed char    pr_nice;       /* Nice val                                  */  unsigned long  pr_flag;       /* Flags                                     */#ifdef __x86_64__  uint32_t       pr_uid;        /* User ID                                   */  uint32_t       pr_gid;        /* Group ID                                  */#else  uint16_t       pr_uid;        /* User ID                                   */  uint16_t       pr_gid;        /* Group ID                                  */#endif  pid_t          pr_pid;        /* Process ID                                */  pid_t          pr_ppid;       /* Parent's process ID                       */  pid_t          pr_pgrp;       /* Group ID                                  */  pid_t          pr_sid;        /* Session ID                                */  char           pr_fname[16];  /* Filename of executable                    */  char           pr_psargs[80]; /* Initial part of arg list                  */} prpsinfo;typedef struct user {           /* Ptrace returns this data for thread state */  regs           regs;          /* CPU registers                             */  unsigned long  fpvalid;       /* True if math co-processor being used      */#if defined(__i386__) || defined(__x86_64__)  fpregs         fpregs;        /* FPU registers                             */#endif  unsigned long  tsize;         /* Text segment size in pages                */  unsigned long  dsize;         /* Data segment size in pages                */  unsigned long  ssize;         /* Stack segment size in pages               */  unsigned long  start_code;    /* Starting virtual address of text          */  unsigned long  start_stack;   /* Starting virtual address of stack area    */  unsigned long  signal;        /* Signal that caused the core dump          */  unsigned long  reserved;      /* No longer used                            */  regs           *regs_ptr;     /* Used by gdb to help find the CPU registers*/#if defined(__i386__) || defined(__x86_64__)  fpregs         *fpregs_ptr;   /* Pointer to FPU registers                  */#endif  unsigned long  magic;         /* Magic for old A.OUT core files            */  char           comm[32];      /* User command that was responsible         */  unsigned long  debugreg[8];#if defined(__i386__) || defined(__x86_64__)  unsigned long  error_code;    /* CPU error code or 0                       */  unsigned long  fault_address; /* CR3 or 0                                  */#elif defined(__ARM_ARCH_3__)  fpregs         fpregs;        /* FPU registers                             */  fpregs         *fpregs_ptr;   /* Pointer to FPU registers                  */#endif} user;#if __WORDSIZE == 64  #define ELF_CLASS ELFCLASS64  #define Ehdr      Elf64_Ehdr  #define Phdr      Elf64_Phdr  #define Shdr      Elf64_Shdr  #define Nhdr      Elf64_Nhdr#else  #define ELF_CLASS ELFCLASS32  #define Ehdr      Elf32_Ehdr  #define Phdr      Elf32_Phdr  #define Shdr      Elf32_Shdr  #define Nhdr      Elf32_Nhdr#endif#if defined(__x86_64__)  #define ELF_ARCH  EM_X86_64#elif defined(__i386__)  #define ELF_ARCH  EM_386#elif defined(__ARM_ARCH_3__)  #define ELF_ARCH  EM_ARM#endif/* Re-runs fn until it doesn't cause EINTR */#define NO_INTR(fn)    do {} while ((fn) < 0 && errno == EINTR)#define MY_NO_INTR(fn) do {} while ((fn) < 0 && my_errno == EINTR)/* Wrapper for read() which is guaranteed to never return EINTR. */static ssize_t c_read(int f, void *buf, size_t bytes, int *errno_) {  int my_errno;  /* scope */ {    /* Define a private copy of syscall macros, which does not modify the     * global copy of errno.     */    #define SYS_ERRNO my_errno    #define SYS_INLINE inline    #undef  SYS_LINUX_SYSCALL_SUPPORT_H    #define SYS_PREFIX 0    #include "linux_syscall_support.h"      if (bytes > 0) {      ssize_t rc;      MY_NO_INTR(rc = sys0_read(f, buf, bytes));      if (rc < 0) {        *errno_ = my_errno;      }      return rc;    }    return 0;  }}/* Wrapper for write() which is guaranteed to never return EINTR nor * short writes. */static ssize_t c_write(int f, const void *void_buf, size_t bytes, int *errno_){  int my_errno;  /* scope */ {    /* Define a private copy of syscall macros, which does not modify the     * global copy of errno.     */    #define SYS_ERRNO my_errno    #define SYS_INLINE inline    #undef  SYS_LINUX_SYSCALL_SUPPORT_H    #define SYS_PREFIX 0    #include "linux_syscall_support.h"      const unsigned char *buf = (const unsigned char*)void_buf;    size_t len = bytes;    while (len > 0) {      ssize_t rc;      MY_NO_INTR(rc = sys0_write(f, buf, len));      if (rc < 0) {        *errno_ = my_errno;        return rc;      } else if (rc == 0) {        break;      }      buf += rc;      len -= rc;    }    return bytes - len;  }}/* The simple synchronous writer is only used when outputting to a pipe * instead of a file. In that case, we do not enforce a pre-determined * maximum output size. */static int SimpleDone(void *f) {  return 0;}/* Simple synchronous writer function used by CreateElfCore() when writing * directly to a pipe. */static ssize_t SimpleWriter(void *f, const void *void_buf, size_t bytes) {  return c_write(*(int *)f, void_buf, bytes, &errno);}struct WriterFds {  size_t max_length;  int    write_fd;  int    compressed_fd;  int    out_fd;};/* Checks whether the maximum number of allowed bytes has been written * to the output file already. */static int PipeDone(void *f) {  struct WriterFds *fds = (struct WriterFds *)f;  return fds->max_length == 0;}/* Writer function that writes directly to a file and honors size limits. */static ssize_t LimitWriter(void *f, const void *void_buf, size_t bytes) {  struct WriterFds *fds = (struct WriterFds *)f;  ssize_t rc;  if (bytes > fds->max_length) {    bytes = fds->max_length;  }  rc = c_write(fds->out_fd, void_buf, bytes, &errno);  if (rc > 0) {    fds->max_length -= rc;  }  return rc;}/* Writer function that can handle writing to one end of a compression * pipeline, reading from the other end of the pipe as compressed data * becomes available, and finally outputting it to a file. */static ssize_t PipeWriter(void *f, const void *void_buf, size_t bytes) {  const unsigned char *buf = (const unsigned char *)void_buf;  struct WriterFds *fds    = (struct WriterFds *)f;  size_t len               = bytes;  while (fds->max_length > 0 && len > 0) {    ssize_t rc;    struct pollfd pfd[2]   = { { fds->compressed_fd, POLLIN, 0 },                               { fds->write_fd, POLLOUT, 0 } };    int nfds = sys_poll(pfd, 2, -1);        if (nfds < 0) {      /* Abort on fatal unexpected I/O errors.                               */      break;    }    if (nfds > 0 && (pfd[0].revents & POLLIN)) {      /* Some compressed data has become available. Copy to output file.     */      char scratch[4096];      for (;;) {        size_t l = sizeof(scratch);        if (l > fds->max_length) {          l = fds->max_length;        }        NO_INTR(rc = read(fds->compressed_fd, scratch, l));        if (rc < 0) {          /* The file handle is set to be non-blocking, so we loop until           * read() returns -1.           */          if (errno == EAGAIN) {            break;          }          return -1;        } else if (rc == 0) {          fds->max_length = 0;          break;        }        rc = c_write(fds->out_fd, scratch, rc, &errno);        if (rc <= 0) {          return -1;        }        fds->max_length -= rc;      }      nfds--;    }    if (nfds > 0 && (pfd[1].revents & POLLOUT)) {      /* The compressor has consumed all previous data and is ready to       * receive more.       */

⌨️ 快捷键说明

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