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