15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2005-2008, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Markus Gutschke, Carl Crous 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _ELFCORE_H 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ELFCORE_H 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __cplusplus 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We currently only support x86-32, x86-64, ARM, and MIPS on Linux. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Porting to other related platforms should not be difficult. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defined(__mips__)) && defined(__linux) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h> 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h> 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Define the DUMPER symbol to make sure that there is exactly one 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * core dumper built into the library. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DUMPER "ELF" 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* By the time that we get a chance to read CPU registers in the 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * calling thread, they are already in a not particularly useful 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * state. Besides, there will be multiple frames on the stack that are 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * just making the core file confusing. To fix this problem, we take a 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * snapshot of the frame pointer, stack pointer, and instruction 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pointer at an earlier time, and then insert these values into the 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * core file. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__i386__) || defined(__x86_64__) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct i386_regs { /* Normal (non-FPU) CPU registers */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #ifdef __x86_64__ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define BP rbp 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SP rsp 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define IP rip 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t r15,r14,r13,r12,rbp,rbx,r11,r10; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t rip,cs,eflags; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t rsp,ss; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t fs_base, gs_base; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t ds,es,fs,gs; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #else 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define BP ebp 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SP esp 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define IP eip 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t ebx, ecx, edx, esi, edi, ebp, eax; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t ds, __ds, es, __es; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t fs, __fs, gs, __gs; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t orig_eax, eip; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t cs, __cs; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t eflags, esp; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t ss, __ss; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #endif 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } i386_regs; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__ARM_ARCH_3__) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct arm_regs { /* General purpose registers */ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define BP uregs[11] /* Frame pointer */ 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SP uregs[13] /* Stack pointer */ 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define IP uregs[15] /* Program counter */ 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define LR uregs[14] /* Link register */ 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long uregs[18]; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } arm_regs; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__mips__) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct mips_regs { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long pad[6]; /* Unused padding to match kernel structures */ 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long uregs[32]; /* General purpose registers. */ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long hi; /* Used for multiplication and division. */ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long lo; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long cp0_epc; /* Program counter. */ 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long cp0_badvaddr; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long cp0_status; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long cp0_cause; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long unused; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } mips_regs; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__i386__) && defined(__GNUC__) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* On x86 we provide an optimized version of the FRAME() macro, if the 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * compiler supports a GCC-style asm() directive. This results in somewhat 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * more accurate values for CPU registers. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct Frame { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct i386_regs uregs; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errno_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t tid; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } Frame; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define FRAME(f) Frame f; \ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.errno_ = errno; \ 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.tid = sys_gettid(); \ 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile ( \ 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "push %%ebp\n" \ 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "push %%ebx\n" \ 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,0(%%eax)\n" \ 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ecx,4(%%eax)\n" \ 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%edx,8(%%eax)\n" \ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%esi,12(%%eax)\n" \ 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%edi,16(%%eax)\n" \ 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebp,20(%%eax)\n" \ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%eax,24(%%eax)\n" \ 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ds,%%ebx\n" \ 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,28(%%eax)\n" \ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%es,%%ebx\n" \ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,32(%%eax)\n" \ 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%fs,%%ebx\n" \ 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,36(%%eax)\n" \ 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%gs,%%ebx\n" \ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx, 40(%%eax)\n" \ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "call 0f\n" \ 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "0:pop %%ebx\n" \ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "add $1f-0b,%%ebx\n" \ 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,48(%%eax)\n" \ 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%cs,%%ebx\n" \ 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,52(%%eax)\n" \ 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pushf\n" \ 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%ebx\n" \ 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,56(%%eax)\n" \ 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%esp,%%ebx\n" \ 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "add $8,%%ebx\n" \ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,60(%%eax)\n" \ 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ss,%%ebx\n" \ 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ebx,64(%%eax)\n" \ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%ebx\n" \ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%ebp\n" \ 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "1:" \ 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : : "a" (&f) : "memory"); \ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SET_FRAME(f,r) \ 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = (f).errno_; \ 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r) = (f).uregs; \ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__x86_64__) && defined(__GNUC__) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The FRAME and SET_FRAME macros for x86_64. */ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct Frame { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct i386_regs uregs; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errno_; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t tid; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } Frame; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define FRAME(f) Frame f; \ 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.errno_ = errno; \ 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.tid = sys_gettid(); \ 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile ( \ 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "push %%rbp\n" \ 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "push %%rbx\n" \ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r15,0(%%rax)\n" \ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r14,8(%%rax)\n" \ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r13,16(%%rax)\n" \ 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r12,24(%%rax)\n" \ 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbp,32(%%rax)\n" \ 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,40(%%rax)\n" \ 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r11,48(%%rax)\n" \ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r10,56(%%rax)\n" \ 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r9,64(%%rax)\n" \ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%r8,72(%%rax)\n" \ 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rax,80(%%rax)\n" \ 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rcx,88(%%rax)\n" \ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rdx,96(%%rax)\n" \ 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rsi,104(%%rax)\n" \ 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rdi,112(%%rax)\n" \ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ds,%%rbx\n" \ 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,184(%%rax)\n" \ 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%es,%%rbx\n" \ 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,192(%%rax)\n" \ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%fs,%%rbx\n" \ 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,200(%%rax)\n" \ 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%gs,%%rbx\n" \ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,208(%%rax)\n" \ 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "call 0f\n" \ 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "0:pop %%rbx\n" \ 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "add $1f-0b,%%rbx\n" \ 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,128(%%rax)\n" \ 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%cs,%%rbx\n" \ 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,136(%%rax)\n" \ 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pushf\n" \ 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%rbx\n" \ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,144(%%rax)\n" \ 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rsp,%%rbx\n" \ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "add $16,%%ebx\n" \ 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,152(%%rax)\n" \ 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%ss,%%rbx\n" \ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mov %%rbx,160(%%rax)\n" \ 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%rbx\n" \ 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pop %%rbp\n" \ 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "1:" \ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : : "a" (&f) : "memory"); \ 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SET_FRAME(f,r) \ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = (f).errno_; \ 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (f).uregs.fs_base = (r).fs_base; \ 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (f).uregs.gs_base = (r).gs_base; \ 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r) = (f).uregs; \ 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__ARM_ARCH_3__) && defined(__GNUC__) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ARM calling conventions are a little more tricky. A little assembly 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * helps in obtaining an accurate snapshot of all registers. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct Frame { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct arm_regs arm; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errno_; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t tid; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } Frame; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define FRAME(f) Frame f; \ 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long cpsr; \ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.errno_ = errno; \ 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.tid = sys_gettid(); \ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile( \ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "stmia %0, {r0-r15}\n" /* All integer regs */\ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : : "r"(&f.arm) : "memory"); \ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.arm.uregs[16] = 0; \ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile( \ 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "mrs %0, cpsr\n" /* Condition code reg */\ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : "=r"(cpsr)); \ 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.arm.uregs[17] = cpsr; \ 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SET_FRAME(f,r) \ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Don't override the FPU status register. */\ 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Use the value obtained from ptrace(). This*/\ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* works, because our code does not perform */\ 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* any FPU operations, itself. */\ 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long fps = (f).arm.uregs[16]; \ 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = (f).errno_; \ 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r) = (f).arm; \ 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r).uregs[16] = fps; \ 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__mips__) && defined(__GNUC__) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct Frame { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct mips_regs mips_regs; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errno_; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t tid; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } Frame; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; }) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define FRAME(f) Frame f = { 0 }; \ 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long hi, lo; \ 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register unsigned long pc __asm__("$31"); \ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 0] = MIPSREG( 0); \ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 1] = MIPSREG( 1); \ 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 2] = MIPSREG( 2); \ 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 3] = MIPSREG( 3); \ 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 4] = MIPSREG( 4); \ 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 5] = MIPSREG( 5); \ 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 6] = MIPSREG( 6); \ 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 7] = MIPSREG( 7); \ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 8] = MIPSREG( 8); \ 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[ 9] = MIPSREG( 9); \ 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[10] = MIPSREG(10); \ 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[11] = MIPSREG(11); \ 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[12] = MIPSREG(12); \ 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[13] = MIPSREG(13); \ 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[14] = MIPSREG(14); \ 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[15] = MIPSREG(15); \ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[16] = MIPSREG(16); \ 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[17] = MIPSREG(17); \ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[18] = MIPSREG(18); \ 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[19] = MIPSREG(19); \ 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[20] = MIPSREG(20); \ 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[21] = MIPSREG(21); \ 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[22] = MIPSREG(22); \ 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[23] = MIPSREG(23); \ 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[24] = MIPSREG(24); \ 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[25] = MIPSREG(25); \ 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[26] = MIPSREG(26); \ 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[27] = MIPSREG(27); \ 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[28] = MIPSREG(28); \ 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[29] = MIPSREG(29); \ 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[30] = MIPSREG(30); \ 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.uregs[31] = MIPSREG(31); \ 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile ("mfhi %0" : "=r"(hi)); \ 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile ("mflo %0" : "=r"(lo)); \ 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \ 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.hi = hi; \ 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.lo = lo; \ 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.mips_regs.cp0_epc = pc; \ 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.errno_ = errno; \ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.tid = sys_gettid(); \ 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SET_FRAME(f,r) \ 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = (f).errno_; \ 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy((r).uregs, (f).mips_regs.uregs, \ 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32*sizeof(unsigned long)); \ 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r).hi = (f).mips_regs.hi; \ 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r).lo = (f).mips_regs.lo; \ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (r).cp0_epc = (f).mips_regs.cp0_epc; \ 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we do not have a hand-optimized assembly version of the FRAME() 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * macro, we cannot reliably unroll the stack. So, we show a few additional 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * stack frames for the coredumper. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef struct Frame { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t tid; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } Frame; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SET_FRAME(f,r) do { } while (0) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Internal function for generating a core file. This API can change without 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice and is only supposed to be used internally by the core dumper. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This function works for both single- and multi-threaded core 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dumps. If called as 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FRAME(frame); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * InternalGetCoreDump(&frame, 0, NULL, ap); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it creates a core file that only contains information about the 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * calling thread. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Optionally, the caller can provide information about other threads 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * by passing their process ids in "thread_pids". The process id of 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the caller should not be included in this array. All of the threads 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * must have been attached to with ptrace(), prior to calling this 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * function. They will be detached when "InternalGetCoreDump()" returns. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This function either returns a file handle that can be read for obtaining 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a core dump, or "-1" in case of an error. In the latter case, "errno" 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be set appropriately. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * While "InternalGetCoreDump()" is not technically async signal safe, you 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * might be tempted to invoke it from a signal handler. The code goes to 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * great lengths to make a best effort that this will actually work. But in 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * any case, you must make sure that you preserve the value of "errno" 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * yourself. It is guaranteed to be clobbered otherwise. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it makes a best effort to behave reasonably when called in a multi- 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * threaded environment, but it is ultimately the caller's responsibility 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to provide locking. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list ap 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* const struct CoreDumpParameters *params, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *file_name, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *PATH 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __cplusplus 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* _ELFCORE_H */ 386