📄 elfcore.h
字号:
#elif defined(__x86_64__) && defined(__GNUC__) /* The FRAME and SET_FRAME macros for x86_64. */ typedef struct Frame { struct i386_regs uregs; int errno_; pid_t tid; } Frame; #define FRAME(f) Frame f; \ do { \ f.errno_ = errno; \ f.tid = sys_gettid(); \ __asm__ volatile ( \ "push %%rbp\n" \ "push %%rbx\n" \ "mov %%r15,0(%%rax)\n" \ "mov %%r14,8(%%rax)\n" \ "mov %%r13,16(%%rax)\n" \ "mov %%r12,24(%%rax)\n" \ "mov %%rbp,32(%%rax)\n" \ "mov %%rbx,40(%%rax)\n" \ "mov %%r11,48(%%rax)\n" \ "mov %%r10,56(%%rax)\n" \ "mov %%r9,64(%%rax)\n" \ "mov %%r8,72(%%rax)\n" \ "mov %%rax,80(%%rax)\n" \ "mov %%rcx,88(%%rax)\n" \ "mov %%rdx,96(%%rax)\n" \ "mov %%rsi,104(%%rax)\n" \ "mov %%rdi,112(%%rax)\n" \ "mov %%ds,%%rbx\n" \ "mov %%rbx,184(%%rax)\n" \ "mov %%es,%%rbx\n" \ "mov %%rbx,192(%%rax)\n" \ "mov %%fs,%%rbx\n" \ "mov %%rbx,200(%%rax)\n" \ "mov %%gs,%%rbx\n" \ "mov %%rbx,208(%%rax)\n" \ "call 0f\n" \ "0:pop %%rbx\n" \ "add $1f-0b,%%rbx\n" \ "mov %%rbx,128(%%rax)\n" \ "mov %%cs,%%rbx\n" \ "mov %%rbx,136(%%rax)\n" \ "pushf\n" \ "pop %%rbx\n" \ "mov %%rbx,144(%%rax)\n" \ "mov %%rsp,%%rbx\n" \ "add $16,%%ebx\n" \ "mov %%rbx,152(%%rax)\n" \ "mov %%ss,%%rbx\n" \ "mov %%rbx,160(%%rax)\n" \ "pop %%rbx\n" \ "pop %%rbp\n" \ "1:" \ : : "a" (&f) : "memory"); \ } while (0) #define SET_FRAME(f,r) \ do { \ errno = (f).errno_; \ (f).uregs.fs_base = (r).fs_base; \ (f).uregs.gs_base = (r).gs_base; \ (r) = (f).uregs; \ } while (0)#elif defined(__ARM_ARCH_3__) && defined(__GNUC__) /* ARM calling conventions are a little more tricky. A little assembly * helps in obtaining an accurate snapshot of all registers. */ typedef struct Frame { struct arm_regs arm; int errno_; pid_t tid; } Frame; #define FRAME(f) Frame f; \ do { \ long cpsr; \ f.errno_ = errno; \ f.tid = sys_gettid(); \ __asm__ volatile( \ "stmia %0, {r0-r15}\n" /* All integer regs */\ : : "r"(&f.arm) : "memory"); \ f.arm.uregs[16] = 0; \ __asm__ volatile( \ "mrs %0, cpsr\n" /* Condition code reg */\ : "=r"(cpsr)); \ f.arm.uregs[17] = cpsr; \ } while (0) #define SET_FRAME(f,r) \ do { \ /* Don't override the FPU status register. */\ /* Use the value obtained from ptrace(). This*/\ /* works, because our code does not perform */\ /* any FPU operations, itself. */\ long fps = (f).arm.uregs[16]; \ errno = (f).errno_; \ (r) = (f).arm; \ (r).uregs[16] = fps; \ } while (0)#else /* If we do not have a hand-optimized assembly version of the FRAME() * macro, we cannot reliably unroll the stack. So, we show a few additional * stack frames for the coredumper. */ typedef struct Frame { pid_t tid; } Frame; #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0) #define SET_FRAME(f,r) do { } while (0)#endif/* Internal function for generating a core file. This API can change without * notice and is only supposed to be used internally by the core dumper. * * This function works for both single- and multi-threaded core * dumps. If called as * * FRAME(frame); * InternalGetCoreDump(&frame, 0, NULL, ap); * * it creates a core file that only contains information about the * calling thread. * * Optionally, the caller can provide information about other threads * by passing their process ids in "thread_pids". The process id of * the caller should not be included in this array. All of the threads * must have been attached to with ptrace(), prior to calling this * function. They will be detached when "InternalGetCoreDump()" returns. * * This function either returns a file handle that can be read for obtaining * a core dump, or "-1" in case of an error. In the latter case, "errno" * will be set appropriately. * * While "InternalGetCoreDump()" is not technically async signal safe, you * might be tempted to invoke it from a signal handler. The code goes to * great lengths to make a best effort that this will actually work. But in * any case, you must make sure that you preserve the value of "errno" * yourself. It is guaranteed to be clobbered otherwise. * * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again, * it makes a best effort to behave reasonably when called in a multi- * threaded environment, but it is ultimately the caller's responsibility * to provide locking. */int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids, va_list ap /* const char *PATH, const struct CoredumperCompressor *compressors, const struct CoredumperCompressor **selected_comp */);#endif#endif /* _ELFCORE_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -