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