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
37extern "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 */
373int 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