Home | History | Annotate | Download | only in base
      1 /* Copyright (c) 2005-2008, Google Inc.
      2  * All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  * ---
     31  * Author: Markus Gutschke, Carl Crous
     32  */
     33 
     34 #ifndef _ELFCORE_H
     35 #define _ELFCORE_H
     36 #ifdef __cplusplus
     37 extern "C" {
     38 #endif
     39 
     40 /* We currently only support x86-32, x86-64, ARM, and MIPS on Linux.
     41  * Porting to other related platforms should not be difficult.
     42  */
     43 #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
     44      defined(__mips__)) && defined(__linux)
     45 
     46 #include <stdarg.h>
     47 #include <stdint.h>
     48 #include <sys/types.h>
     49 #include <config.h>
     50 
     51 
     52 /* Define the DUMPER symbol to make sure that there is exactly one
     53  * core dumper built into the library.
     54  */
     55 #define DUMPER "ELF"
     56 
     57 /* By the time that we get a chance to read CPU registers in the
     58  * calling thread, they are already in a not particularly useful
     59  * state. Besides, there will be multiple frames on the stack that are
     60  * just making the core file confusing. To fix this problem, we take a
     61  * snapshot of the frame pointer, stack pointer, and instruction
     62  * pointer at an earlier time, and then insert these values into the
     63  * core file.
     64  */
     65 
     66 #if defined(__i386__) || defined(__x86_64__)
     67   typedef struct i386_regs {    /* Normal (non-FPU) CPU registers            */
     68   #ifdef __x86_64__
     69     #define BP rbp
     70     #define SP rsp
     71     #define IP rip
     72     uint64_t  r15,r14,r13,r12,rbp,rbx,r11,r10;
     73     uint64_t  r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
     74     uint64_t  rip,cs,eflags;
     75     uint64_t  rsp,ss;
     76     uint64_t  fs_base, gs_base;
     77     uint64_t  ds,es,fs,gs;
     78   #else
     79     #define BP ebp
     80     #define SP esp
     81     #define IP eip
     82     uint32_t  ebx, ecx, edx, esi, edi, ebp, eax;
     83     uint16_t  ds, __ds, es, __es;
     84     uint16_t  fs, __fs, gs, __gs;
     85     uint32_t  orig_eax, eip;
     86     uint16_t  cs, __cs;
     87     uint32_t  eflags, esp;
     88     uint16_t  ss, __ss;
     89   #endif
     90   } i386_regs;
     91 #elif defined(__ARM_ARCH_3__)
     92   typedef struct arm_regs {     /* General purpose registers                 */
     93     #define BP uregs[11]        /* Frame pointer                             */
     94     #define SP uregs[13]        /* Stack pointer                             */
     95     #define IP uregs[15]        /* Program counter                           */
     96     #define LR uregs[14]        /* Link register                             */
     97     long uregs[18];
     98   } arm_regs;
     99 #elif defined(__mips__)
    100   typedef struct mips_regs {
    101     unsigned long pad[6];       /* Unused padding to match kernel structures */
    102     unsigned long uregs[32];    /* General purpose registers.                */
    103     unsigned long hi;           /* Used for multiplication and division.     */
    104     unsigned long lo;
    105     unsigned long cp0_epc;      /* Program counter.                          */
    106     unsigned long cp0_badvaddr;
    107     unsigned long cp0_status;
    108     unsigned long cp0_cause;
    109     unsigned long unused;
    110   } mips_regs;
    111 #endif
    112 
    113 #if defined(__i386__) && defined(__GNUC__)
    114   /* On x86 we provide an optimized version of the FRAME() macro, if the
    115    * compiler supports a GCC-style asm() directive. This results in somewhat
    116    * more accurate values for CPU registers.
    117    */
    118   typedef struct Frame {
    119     struct i386_regs uregs;
    120     int              errno_;
    121     pid_t            tid;
    122   } Frame;
    123   #define FRAME(f) Frame f;                                           \
    124                    do {                                               \
    125                      f.errno_ = errno;                                \
    126                      f.tid    = sys_gettid();                         \
    127                      __asm__ volatile (                               \
    128                        "push %%ebp\n"                                 \
    129                        "push %%ebx\n"                                 \
    130                        "mov  %%ebx,0(%%eax)\n"                        \
    131                        "mov  %%ecx,4(%%eax)\n"                        \
    132                        "mov  %%edx,8(%%eax)\n"                        \
    133                        "mov  %%esi,12(%%eax)\n"                       \
    134                        "mov  %%edi,16(%%eax)\n"                       \
    135                        "mov  %%ebp,20(%%eax)\n"                       \
    136                        "mov  %%eax,24(%%eax)\n"                       \
    137                        "mov  %%ds,%%ebx\n"                            \
    138                        "mov  %%ebx,28(%%eax)\n"                       \
    139                        "mov  %%es,%%ebx\n"                            \
    140                        "mov  %%ebx,32(%%eax)\n"                       \
    141                        "mov  %%fs,%%ebx\n"                            \
    142                        "mov  %%ebx,36(%%eax)\n"                       \
    143                        "mov  %%gs,%%ebx\n"                            \
    144                        "mov  %%ebx, 40(%%eax)\n"                      \
    145                        "call 0f\n"                                    \
    146                      "0:pop %%ebx\n"                                  \
    147                        "add  $1f-0b,%%ebx\n"                          \
    148                        "mov  %%ebx,48(%%eax)\n"                       \
    149                        "mov  %%cs,%%ebx\n"                            \
    150                        "mov  %%ebx,52(%%eax)\n"                       \
    151                        "pushf\n"                                      \
    152                        "pop  %%ebx\n"                                 \
    153                        "mov  %%ebx,56(%%eax)\n"                       \
    154                        "mov  %%esp,%%ebx\n"                           \
    155                        "add  $8,%%ebx\n"                              \
    156                        "mov  %%ebx,60(%%eax)\n"                       \
    157                        "mov  %%ss,%%ebx\n"                            \
    158                        "mov  %%ebx,64(%%eax)\n"                       \
    159                        "pop  %%ebx\n"                                 \
    160                        "pop  %%ebp\n"                                 \
    161                      "1:"                                             \
    162                        : : "a" (&f) : "memory");                      \
    163                      } while (0)
    164   #define SET_FRAME(f,r)                                              \
    165                      do {                                             \
    166                        errno = (f).errno_;                            \
    167                        (r)   = (f).uregs;                             \
    168                      } while (0)
    169 #elif defined(__x86_64__) && defined(__GNUC__)
    170   /* The FRAME and SET_FRAME macros for x86_64.  */
    171   typedef struct Frame {
    172     struct i386_regs uregs;
    173     int              errno_;
    174     pid_t            tid;
    175   } Frame;
    176   #define FRAME(f) Frame f;                                           \
    177                    do {                                               \
    178                      f.errno_ = errno;                                \
    179                      f.tid    = sys_gettid();                         \
    180                      __asm__ volatile (                               \
    181                        "push %%rbp\n"                                 \
    182                        "push %%rbx\n"                                 \
    183                        "mov  %%r15,0(%%rax)\n"                        \
    184                        "mov  %%r14,8(%%rax)\n"                        \
    185                        "mov  %%r13,16(%%rax)\n"                       \
    186                        "mov  %%r12,24(%%rax)\n"                       \
    187                        "mov  %%rbp,32(%%rax)\n"                       \
    188                        "mov  %%rbx,40(%%rax)\n"                       \
    189                        "mov  %%r11,48(%%rax)\n"                       \
    190                        "mov  %%r10,56(%%rax)\n"                       \
    191                        "mov  %%r9,64(%%rax)\n"                        \
    192                        "mov  %%r8,72(%%rax)\n"                        \
    193                        "mov  %%rax,80(%%rax)\n"                       \
    194                        "mov  %%rcx,88(%%rax)\n"                       \
    195                        "mov  %%rdx,96(%%rax)\n"                       \
    196                        "mov  %%rsi,104(%%rax)\n"                      \
    197                        "mov  %%rdi,112(%%rax)\n"                      \
    198                        "mov  %%ds,%%rbx\n"                            \
    199                        "mov  %%rbx,184(%%rax)\n"                      \
    200                        "mov  %%es,%%rbx\n"                            \
    201                        "mov  %%rbx,192(%%rax)\n"                      \
    202                        "mov  %%fs,%%rbx\n"                            \
    203                        "mov  %%rbx,200(%%rax)\n"                      \
    204                        "mov  %%gs,%%rbx\n"                            \
    205                        "mov  %%rbx,208(%%rax)\n"                      \
    206                        "call 0f\n"                                    \
    207                      "0:pop %%rbx\n"                                  \
    208                        "add  $1f-0b,%%rbx\n"                          \
    209                        "mov  %%rbx,128(%%rax)\n"                      \
    210                        "mov  %%cs,%%rbx\n"                            \
    211                        "mov  %%rbx,136(%%rax)\n"                      \
    212                        "pushf\n"                                      \
    213                        "pop  %%rbx\n"                                 \
    214                        "mov  %%rbx,144(%%rax)\n"                      \
    215                        "mov  %%rsp,%%rbx\n"                           \
    216                        "add  $16,%%ebx\n"                             \
    217                        "mov  %%rbx,152(%%rax)\n"                      \
    218                        "mov  %%ss,%%rbx\n"                            \
    219                        "mov  %%rbx,160(%%rax)\n"                      \
    220                        "pop  %%rbx\n"                                 \
    221                        "pop  %%rbp\n"                                 \
    222                      "1:"                                             \
    223                        : : "a" (&f) : "memory");                      \
    224                      } while (0)
    225   #define SET_FRAME(f,r)                                              \
    226                      do {                                             \
    227                        errno = (f).errno_;                            \
    228                        (f).uregs.fs_base = (r).fs_base;               \
    229                        (f).uregs.gs_base = (r).gs_base;               \
    230                        (r)   = (f).uregs;                             \
    231                      } while (0)
    232 #elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
    233   /* ARM calling conventions are a little more tricky. A little assembly
    234    * helps in obtaining an accurate snapshot of all registers.
    235    */
    236   typedef struct Frame {
    237     struct arm_regs arm;
    238     int             errno_;
    239     pid_t           tid;
    240   } Frame;
    241   #define FRAME(f) Frame f;                                           \
    242                    do {                                               \
    243                      long cpsr;                                       \
    244                      f.errno_ = errno;                                \
    245                      f.tid    = sys_gettid();                         \
    246                      __asm__ volatile(                                \
    247                        "stmia %0, {r0-r15}\n" /* All integer regs   */\
    248                        : : "r"(&f.arm) : "memory");                   \
    249                      f.arm.uregs[16] = 0;                             \
    250                      __asm__ volatile(                                \
    251                        "mrs %0, cpsr\n"       /* Condition code reg */\
    252                        : "=r"(cpsr));                                 \
    253                      f.arm.uregs[17] = cpsr;                          \
    254                    } while (0)
    255   #define SET_FRAME(f,r)                                              \
    256                      do {                                             \
    257                        /* Don't override the FPU status register.   */\
    258                        /* Use the value obtained from ptrace(). This*/\
    259                        /* works, because our code does not perform  */\
    260                        /* any FPU operations, itself.               */\
    261                        long fps      = (f).arm.uregs[16];             \
    262                        errno         = (f).errno_;                    \
    263                        (r)           = (f).arm;                       \
    264                        (r).uregs[16] = fps;                           \
    265                      } while (0)
    266 #elif defined(__mips__) && defined(__GNUC__)
    267   typedef struct Frame {
    268     struct mips_regs mips_regs;
    269     int              errno_;
    270     pid_t            tid;
    271   } Frame;
    272   #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
    273   #define FRAME(f) Frame f = { 0 };                                   \
    274                    do {                                               \
    275                      unsigned long hi, lo;                            \
    276                      register unsigned long pc __asm__("$31");        \
    277                      f.mips_regs.uregs[ 0] = MIPSREG( 0);             \
    278                      f.mips_regs.uregs[ 1] = MIPSREG( 1);             \
    279                      f.mips_regs.uregs[ 2] = MIPSREG( 2);             \
    280                      f.mips_regs.uregs[ 3] = MIPSREG( 3);             \
    281                      f.mips_regs.uregs[ 4] = MIPSREG( 4);             \
    282                      f.mips_regs.uregs[ 5] = MIPSREG( 5);             \
    283                      f.mips_regs.uregs[ 6] = MIPSREG( 6);             \
    284                      f.mips_regs.uregs[ 7] = MIPSREG( 7);             \
    285                      f.mips_regs.uregs[ 8] = MIPSREG( 8);             \
    286                      f.mips_regs.uregs[ 9] = MIPSREG( 9);             \
    287                      f.mips_regs.uregs[10] = MIPSREG(10);             \
    288                      f.mips_regs.uregs[11] = MIPSREG(11);             \
    289                      f.mips_regs.uregs[12] = MIPSREG(12);             \
    290                      f.mips_regs.uregs[13] = MIPSREG(13);             \
    291                      f.mips_regs.uregs[14] = MIPSREG(14);             \
    292                      f.mips_regs.uregs[15] = MIPSREG(15);             \
    293                      f.mips_regs.uregs[16] = MIPSREG(16);             \
    294                      f.mips_regs.uregs[17] = MIPSREG(17);             \
    295                      f.mips_regs.uregs[18] = MIPSREG(18);             \
    296                      f.mips_regs.uregs[19] = MIPSREG(19);             \
    297                      f.mips_regs.uregs[20] = MIPSREG(20);             \
    298                      f.mips_regs.uregs[21] = MIPSREG(21);             \
    299                      f.mips_regs.uregs[22] = MIPSREG(22);             \
    300                      f.mips_regs.uregs[23] = MIPSREG(23);             \
    301                      f.mips_regs.uregs[24] = MIPSREG(24);             \
    302                      f.mips_regs.uregs[25] = MIPSREG(25);             \
    303                      f.mips_regs.uregs[26] = MIPSREG(26);             \
    304                      f.mips_regs.uregs[27] = MIPSREG(27);             \
    305                      f.mips_regs.uregs[28] = MIPSREG(28);             \
    306                      f.mips_regs.uregs[29] = MIPSREG(29);             \
    307                      f.mips_regs.uregs[30] = MIPSREG(30);             \
    308                      f.mips_regs.uregs[31] = MIPSREG(31);             \
    309                      __asm__ volatile ("mfhi %0" : "=r"(hi));         \
    310                      __asm__ volatile ("mflo %0" : "=r"(lo));         \
    311                      __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc));   \
    312                      f.mips_regs.hi       = hi;                       \
    313                      f.mips_regs.lo       = lo;                       \
    314                      f.mips_regs.cp0_epc  = pc;                       \
    315                      f.errno_             = errno;                    \
    316                      f.tid                = sys_gettid();             \
    317                    } while (0)
    318   #define SET_FRAME(f,r)                                              \
    319                    do {                                               \
    320                      errno       = (f).errno_;                        \
    321                      memcpy((r).uregs, (f).mips_regs.uregs,           \
    322                             32*sizeof(unsigned long));                \
    323                      (r).hi      = (f).mips_regs.hi;                  \
    324                      (r).lo      = (f).mips_regs.lo;                  \
    325                      (r).cp0_epc = (f).mips_regs.cp0_epc;             \
    326                    } while (0)
    327 #else
    328   /* If we do not have a hand-optimized assembly version of the FRAME()
    329    * macro, we cannot reliably unroll the stack. So, we show a few additional
    330    * stack frames for the coredumper.
    331    */
    332   typedef struct Frame {
    333     pid_t tid;
    334   } Frame;
    335   #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0)
    336   #define SET_FRAME(f,r) do { } while (0)
    337 #endif
    338 
    339 
    340 /* Internal function for generating a core file. This API can change without
    341  * notice and is only supposed to be used internally by the core dumper.
    342  *
    343  * This function works for both single- and multi-threaded core
    344  * dumps. If called as
    345  *
    346  *   FRAME(frame);
    347  *   InternalGetCoreDump(&frame, 0, NULL, ap);
    348  *
    349  * it creates a core file that only contains information about the
    350  * calling thread.
    351  *
    352  * Optionally, the caller can provide information about other threads
    353  * by passing their process ids in "thread_pids". The process id of
    354  * the caller should not be included in this array. All of the threads
    355  * must have been attached to with ptrace(), prior to calling this
    356  * function. They will be detached when "InternalGetCoreDump()" returns.
    357  *
    358  * This function either returns a file handle that can be read for obtaining
    359  * a core dump, or "-1" in case of an error. In the latter case, "errno"
    360  * will be set appropriately.
    361  *
    362  * While "InternalGetCoreDump()" is not technically async signal safe, you
    363  * might be tempted to invoke it from a signal handler. The code goes to
    364  * great lengths to make a best effort that this will actually work. But in
    365  * any case, you must make sure that you preserve the value of "errno"
    366  * yourself. It is guaranteed to be clobbered otherwise.
    367  *
    368  * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
    369  * it makes a best effort to behave reasonably when called in a multi-
    370  * threaded environment, but it is ultimately the caller's responsibility
    371  * to provide locking.
    372  */
    373 int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
    374                         va_list ap
    375                      /* const struct CoreDumpParameters *params,
    376                         const char *file_name,
    377                         const char *PATH
    378                       */);
    379 
    380 #endif
    381 
    382 #ifdef __cplusplus
    383 }
    384 #endif
    385 #endif /* _ELFCORE_H */
    386