Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / tcmalloc / chromium / src / base / elfcore.h
blob34a96dec3d0a9a09f648e5737cfd8c6862d1bcb8
1 /* Copyright (c) 2005-2008, Google Inc.
2 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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.
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.
30 * ---
31 * Author: Markus Gutschke, Carl Crous
34 #ifndef _ELFCORE_H
35 #define _ELFCORE_H
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
40 /* We currently only support x86-32, x86-64, ARM, and MIPS on Linux.
41 * Porting to other related platforms should not be difficult.
43 #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
44 defined(__mips__)) && defined(__linux)
46 #include <stdarg.h>
47 #include <stdint.h>
48 #include <sys/types.h>
49 #include <config.h>
52 /* Define the DUMPER symbol to make sure that there is exactly one
53 * core dumper built into the library.
55 #define DUMPER "ELF"
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.
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
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.
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.
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.
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
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.
343 * This function works for both single- and multi-threaded core
344 * dumps. If called as
346 * FRAME(frame);
347 * InternalGetCoreDump(&frame, 0, NULL, ap);
349 * it creates a core file that only contains information about the
350 * calling thread.
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.
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.
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.
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.
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 */);
380 #endif
382 #ifdef __cplusplus
384 #endif
385 #endif /* _ELFCORE_H */