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