elfcore.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. /* Copyright (c) 2005-2008, Google Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following disclaimer
  13. * in the documentation and/or other materials provided with the
  14. * distribution.
  15. * * Neither the name of Google Inc. nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * ---
  32. * Author: Markus Gutschke, Carl Crous
  33. */
  34. #ifndef _ELFCORE_H
  35. #define _ELFCORE_H
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. /* We currently only support x86-32, x86-64, ARM, MIPS, PPC on Linux.
  40. * Porting to other related platforms should not be difficult.
  41. */
  42. #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
  43. defined(__mips__) || defined(__PPC__)) && defined(__linux)
  44. #include <stdarg.h>
  45. #include <stdint.h>
  46. #include <sys/types.h>
  47. #include <config.h>
  48. /* Define the DUMPER symbol to make sure that there is exactly one
  49. * core dumper built into the library.
  50. */
  51. #define DUMPER "ELF"
  52. /* By the time that we get a chance to read CPU registers in the
  53. * calling thread, they are already in a not particularly useful
  54. * state. Besides, there will be multiple frames on the stack that are
  55. * just making the core file confusing. To fix this problem, we take a
  56. * snapshot of the frame pointer, stack pointer, and instruction
  57. * pointer at an earlier time, and then insert these values into the
  58. * core file.
  59. */
  60. #if defined(__i386__) || defined(__x86_64__)
  61. typedef struct i386_regs { /* Normal (non-FPU) CPU registers */
  62. #ifdef __x86_64__
  63. #define BP rbp
  64. #define SP rsp
  65. #define IP rip
  66. uint64_t r15,r14,r13,r12,rbp,rbx,r11,r10;
  67. uint64_t r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
  68. uint64_t rip,cs,eflags;
  69. uint64_t rsp,ss;
  70. uint64_t fs_base, gs_base;
  71. uint64_t ds,es,fs,gs;
  72. #else
  73. #define BP ebp
  74. #define SP esp
  75. #define IP eip
  76. uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
  77. uint16_t ds, __ds, es, __es;
  78. uint16_t fs, __fs, gs, __gs;
  79. uint32_t orig_eax, eip;
  80. uint16_t cs, __cs;
  81. uint32_t eflags, esp;
  82. uint16_t ss, __ss;
  83. #endif
  84. } i386_regs;
  85. #elif defined(__ARM_ARCH_3__)
  86. typedef struct arm_regs { /* General purpose registers */
  87. #define BP uregs[11] /* Frame pointer */
  88. #define SP uregs[13] /* Stack pointer */
  89. #define IP uregs[15] /* Program counter */
  90. #define LR uregs[14] /* Link register */
  91. long uregs[18];
  92. } arm_regs;
  93. #elif defined(__mips__)
  94. typedef struct mips_regs {
  95. unsigned long pad[6]; /* Unused padding to match kernel structures */
  96. unsigned long uregs[32]; /* General purpose registers. */
  97. unsigned long hi; /* Used for multiplication and division. */
  98. unsigned long lo;
  99. unsigned long cp0_epc; /* Program counter. */
  100. unsigned long cp0_badvaddr;
  101. unsigned long cp0_status;
  102. unsigned long cp0_cause;
  103. unsigned long unused;
  104. } mips_regs;
  105. #elif defined (__PPC__)
  106. typedef struct ppc_regs {
  107. #define SP uregs[1] /* Stack pointer */
  108. #define IP rip /* Program counter */
  109. #define LR lr /* Link register */
  110. unsigned long uregs[32]; /* General Purpose Registers - r0-r31. */
  111. double fpr[32]; /* Floating-Point Registers - f0-f31. */
  112. unsigned long rip; /* Program counter. */
  113. unsigned long msr;
  114. unsigned long ccr;
  115. unsigned long lr;
  116. unsigned long ctr;
  117. unsigned long xeq;
  118. unsigned long mq;
  119. } ppc_regs;
  120. #endif
  121. #if defined(__i386__) && defined(__GNUC__)
  122. /* On x86 we provide an optimized version of the FRAME() macro, if the
  123. * compiler supports a GCC-style asm() directive. This results in somewhat
  124. * more accurate values for CPU registers.
  125. */
  126. typedef struct Frame {
  127. struct i386_regs uregs;
  128. int errno_;
  129. pid_t tid;
  130. } Frame;
  131. #define FRAME(f) Frame f; \
  132. do { \
  133. f.errno_ = errno; \
  134. f.tid = sys_gettid(); \
  135. __asm__ volatile ( \
  136. "push %%ebp\n" \
  137. "push %%ebx\n" \
  138. "mov %%ebx,0(%%eax)\n" \
  139. "mov %%ecx,4(%%eax)\n" \
  140. "mov %%edx,8(%%eax)\n" \
  141. "mov %%esi,12(%%eax)\n" \
  142. "mov %%edi,16(%%eax)\n" \
  143. "mov %%ebp,20(%%eax)\n" \
  144. "mov %%eax,24(%%eax)\n" \
  145. "mov %%ds,%%ebx\n" \
  146. "mov %%ebx,28(%%eax)\n" \
  147. "mov %%es,%%ebx\n" \
  148. "mov %%ebx,32(%%eax)\n" \
  149. "mov %%fs,%%ebx\n" \
  150. "mov %%ebx,36(%%eax)\n" \
  151. "mov %%gs,%%ebx\n" \
  152. "mov %%ebx, 40(%%eax)\n" \
  153. "call 0f\n" \
  154. "0:pop %%ebx\n" \
  155. "add $1f-0b,%%ebx\n" \
  156. "mov %%ebx,48(%%eax)\n" \
  157. "mov %%cs,%%ebx\n" \
  158. "mov %%ebx,52(%%eax)\n" \
  159. "pushf\n" \
  160. "pop %%ebx\n" \
  161. "mov %%ebx,56(%%eax)\n" \
  162. "mov %%esp,%%ebx\n" \
  163. "add $8,%%ebx\n" \
  164. "mov %%ebx,60(%%eax)\n" \
  165. "mov %%ss,%%ebx\n" \
  166. "mov %%ebx,64(%%eax)\n" \
  167. "pop %%ebx\n" \
  168. "pop %%ebp\n" \
  169. "1:" \
  170. : : "a" (&f) : "memory"); \
  171. } while (0)
  172. #define SET_FRAME(f,r) \
  173. do { \
  174. errno = (f).errno_; \
  175. (r) = (f).uregs; \
  176. } while (0)
  177. #elif defined(__x86_64__) && defined(__GNUC__)
  178. /* The FRAME and SET_FRAME macros for x86_64. */
  179. typedef struct Frame {
  180. struct i386_regs uregs;
  181. int errno_;
  182. pid_t tid;
  183. } Frame;
  184. #define FRAME(f) Frame f; \
  185. do { \
  186. f.errno_ = errno; \
  187. f.tid = sys_gettid(); \
  188. __asm__ volatile ( \
  189. "push %%rbp\n" \
  190. "push %%rbx\n" \
  191. "mov %%r15,0(%%rax)\n" \
  192. "mov %%r14,8(%%rax)\n" \
  193. "mov %%r13,16(%%rax)\n" \
  194. "mov %%r12,24(%%rax)\n" \
  195. "mov %%rbp,32(%%rax)\n" \
  196. "mov %%rbx,40(%%rax)\n" \
  197. "mov %%r11,48(%%rax)\n" \
  198. "mov %%r10,56(%%rax)\n" \
  199. "mov %%r9,64(%%rax)\n" \
  200. "mov %%r8,72(%%rax)\n" \
  201. "mov %%rax,80(%%rax)\n" \
  202. "mov %%rcx,88(%%rax)\n" \
  203. "mov %%rdx,96(%%rax)\n" \
  204. "mov %%rsi,104(%%rax)\n" \
  205. "mov %%rdi,112(%%rax)\n" \
  206. "mov %%ds,%%rbx\n" \
  207. "mov %%rbx,184(%%rax)\n" \
  208. "mov %%es,%%rbx\n" \
  209. "mov %%rbx,192(%%rax)\n" \
  210. "mov %%fs,%%rbx\n" \
  211. "mov %%rbx,200(%%rax)\n" \
  212. "mov %%gs,%%rbx\n" \
  213. "mov %%rbx,208(%%rax)\n" \
  214. "call 0f\n" \
  215. "0:pop %%rbx\n" \
  216. "add $1f-0b,%%rbx\n" \
  217. "mov %%rbx,128(%%rax)\n" \
  218. "mov %%cs,%%rbx\n" \
  219. "mov %%rbx,136(%%rax)\n" \
  220. "pushf\n" \
  221. "pop %%rbx\n" \
  222. "mov %%rbx,144(%%rax)\n" \
  223. "mov %%rsp,%%rbx\n" \
  224. "add $16,%%ebx\n" \
  225. "mov %%rbx,152(%%rax)\n" \
  226. "mov %%ss,%%rbx\n" \
  227. "mov %%rbx,160(%%rax)\n" \
  228. "pop %%rbx\n" \
  229. "pop %%rbp\n" \
  230. "1:" \
  231. : : "a" (&f) : "memory"); \
  232. } while (0)
  233. #define SET_FRAME(f,r) \
  234. do { \
  235. errno = (f).errno_; \
  236. (f).uregs.fs_base = (r).fs_base; \
  237. (f).uregs.gs_base = (r).gs_base; \
  238. (r) = (f).uregs; \
  239. } while (0)
  240. #elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
  241. /* ARM calling conventions are a little more tricky. A little assembly
  242. * helps in obtaining an accurate snapshot of all registers.
  243. */
  244. typedef struct Frame {
  245. struct arm_regs arm;
  246. int errno_;
  247. pid_t tid;
  248. } Frame;
  249. #define FRAME(f) Frame f; \
  250. do { \
  251. long cpsr; \
  252. f.errno_ = errno; \
  253. f.tid = sys_gettid(); \
  254. __asm__ volatile( \
  255. "stmia %0, {r0-r15}\n" /* All integer regs */\
  256. : : "r"(&f.arm) : "memory"); \
  257. f.arm.uregs[16] = 0; \
  258. __asm__ volatile( \
  259. "mrs %0, cpsr\n" /* Condition code reg */\
  260. : "=r"(cpsr)); \
  261. f.arm.uregs[17] = cpsr; \
  262. } while (0)
  263. #define SET_FRAME(f,r) \
  264. do { \
  265. /* Don't override the FPU status register. */\
  266. /* Use the value obtained from ptrace(). This*/\
  267. /* works, because our code does not perform */\
  268. /* any FPU operations, itself. */\
  269. long fps = (f).arm.uregs[16]; \
  270. errno = (f).errno_; \
  271. (r) = (f).arm; \
  272. (r).uregs[16] = fps; \
  273. } while (0)
  274. #elif defined(__mips__) && defined(__GNUC__)
  275. typedef struct Frame {
  276. struct mips_regs mips_regs;
  277. int errno_;
  278. pid_t tid;
  279. } Frame;
  280. #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
  281. #define FRAME(f) Frame f = { 0 }; \
  282. do { \
  283. unsigned long hi, lo; \
  284. register unsigned long pc __asm__("$31"); \
  285. f.mips_regs.uregs[ 0] = MIPSREG( 0); \
  286. f.mips_regs.uregs[ 1] = MIPSREG( 1); \
  287. f.mips_regs.uregs[ 2] = MIPSREG( 2); \
  288. f.mips_regs.uregs[ 3] = MIPSREG( 3); \
  289. f.mips_regs.uregs[ 4] = MIPSREG( 4); \
  290. f.mips_regs.uregs[ 5] = MIPSREG( 5); \
  291. f.mips_regs.uregs[ 6] = MIPSREG( 6); \
  292. f.mips_regs.uregs[ 7] = MIPSREG( 7); \
  293. f.mips_regs.uregs[ 8] = MIPSREG( 8); \
  294. f.mips_regs.uregs[ 9] = MIPSREG( 9); \
  295. f.mips_regs.uregs[10] = MIPSREG(10); \
  296. f.mips_regs.uregs[11] = MIPSREG(11); \
  297. f.mips_regs.uregs[12] = MIPSREG(12); \
  298. f.mips_regs.uregs[13] = MIPSREG(13); \
  299. f.mips_regs.uregs[14] = MIPSREG(14); \
  300. f.mips_regs.uregs[15] = MIPSREG(15); \
  301. f.mips_regs.uregs[16] = MIPSREG(16); \
  302. f.mips_regs.uregs[17] = MIPSREG(17); \
  303. f.mips_regs.uregs[18] = MIPSREG(18); \
  304. f.mips_regs.uregs[19] = MIPSREG(19); \
  305. f.mips_regs.uregs[20] = MIPSREG(20); \
  306. f.mips_regs.uregs[21] = MIPSREG(21); \
  307. f.mips_regs.uregs[22] = MIPSREG(22); \
  308. f.mips_regs.uregs[23] = MIPSREG(23); \
  309. f.mips_regs.uregs[24] = MIPSREG(24); \
  310. f.mips_regs.uregs[25] = MIPSREG(25); \
  311. f.mips_regs.uregs[26] = MIPSREG(26); \
  312. f.mips_regs.uregs[27] = MIPSREG(27); \
  313. f.mips_regs.uregs[28] = MIPSREG(28); \
  314. f.mips_regs.uregs[29] = MIPSREG(29); \
  315. f.mips_regs.uregs[30] = MIPSREG(30); \
  316. f.mips_regs.uregs[31] = MIPSREG(31); \
  317. __asm__ volatile ("mfhi %0" : "=r"(hi)); \
  318. __asm__ volatile ("mflo %0" : "=r"(lo)); \
  319. __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \
  320. f.mips_regs.hi = hi; \
  321. f.mips_regs.lo = lo; \
  322. f.mips_regs.cp0_epc = pc; \
  323. f.errno_ = errno; \
  324. f.tid = sys_gettid(); \
  325. } while (0)
  326. #define SET_FRAME(f,r) \
  327. do { \
  328. errno = (f).errno_; \
  329. memcpy((r).uregs, (f).mips_regs.uregs, \
  330. 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) Frame f; do { f.tid = sys_gettid(); } while (0)
  344. #define SET_FRAME(f,r) do { } while (0)
  345. #endif
  346. /* Internal function for generating a core file. This API can change without
  347. * notice and is only supposed to be used internally by the core dumper.
  348. *
  349. * This function works for both single- and multi-threaded core
  350. * dumps. If called as
  351. *
  352. * FRAME(frame);
  353. * InternalGetCoreDump(&frame, 0, NULL, ap);
  354. *
  355. * it creates a core file that only contains information about the
  356. * calling thread.
  357. *
  358. * Optionally, the caller can provide information about other threads
  359. * by passing their process ids in "thread_pids". The process id of
  360. * the caller should not be included in this array. All of the threads
  361. * must have been attached to with ptrace(), prior to calling this
  362. * function. They will be detached when "InternalGetCoreDump()" returns.
  363. *
  364. * This function either returns a file handle that can be read for obtaining
  365. * a core dump, or "-1" in case of an error. In the latter case, "errno"
  366. * will be set appropriately.
  367. *
  368. * While "InternalGetCoreDump()" is not technically async signal safe, you
  369. * might be tempted to invoke it from a signal handler. The code goes to
  370. * great lengths to make a best effort that this will actually work. But in
  371. * any case, you must make sure that you preserve the value of "errno"
  372. * yourself. It is guaranteed to be clobbered otherwise.
  373. *
  374. * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
  375. * it makes a best effort to behave reasonably when called in a multi-
  376. * threaded environment, but it is ultimately the caller's responsibility
  377. * to provide locking.
  378. */
  379. int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
  380. va_list ap
  381. /* const struct CoreDumpParameters *params,
  382. const char *file_name,
  383. const char *PATH
  384. */);
  385. #endif
  386. #ifdef __cplusplus
  387. }
  388. #endif
  389. #endif /* _ELFCORE_H */