plframe_error_t plframe_get_reg (plframe_cursor_t *cursor, plframe_regnum_t regnum, plframe_greg_t *reg) { ucontext_t *uap = cursor->uap; tinyunw_regnum_t unwreg; if (cursor->nframe != 0) { if (regnum == PLFRAME_X86_64_RIP) { tinyunw_get_register(&cursor->unwind_cursor, TINYUNW_X86_64_RIP, reg); return PLFRAME_ESUCCESS; } return PLFRAME_ENOTSUP; } #define MAP_REG(reg) \ case PLFRAME_X86_64_ ## reg: \ unwreg = TINYUNW_X86_64_ ## reg; \ break switch (regnum) { MAP_REG(RAX); MAP_REG(RBX); MAP_REG(RCX); MAP_REG(RDX); MAP_REG(RDI); MAP_REG(RSI); MAP_REG(RBP); MAP_REG(RSP); MAP_REG(R10); MAP_REG(R11); MAP_REG(R12); MAP_REG(R13); MAP_REG(R14); MAP_REG(R15); MAP_REG(RIP); /* These registers are not available through the libtinyunwind API, as they either can not be easily or safely read at async-signal time from the current thread, or have no meaning in x86_64 anyway. */ case PLFRAME_X86_64_RFLAGS: RETGEN(rflags, ss, uap, reg); case PLFRAME_X86_64_CS: RETGEN(cs, ss, uap, reg); case PLFRAME_X86_64_FS: RETGEN(fs, ss, uap, reg); case PLFRAME_X86_64_GS: RETGEN(gs, ss, uap, reg); default: return PLFRAME_ENOTSUP; } #undef MAP_REG return plframe_error_from_tinyunwerror(tinyunw_get_register(&cursor->unwind_cursor, unwreg, reg)); }
/** * @internal * 64-bit implementation of plcrash_async_thread_state_get_reg() */ static apigee_plcrash_greg_t plcrash_async_thread_state_get_reg_64 (const apigee_plcrash_async_thread_state_t *thread_state, apigee_plcrash_regnum_t regnum) { const apigee_plcrash_async_thread_state_t *ts = thread_state; switch (regnum) { case APIGEE_PLCRASH_X86_64_RAX: RETGEN(rax, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RBX: RETGEN(rbx, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RCX: RETGEN(rcx, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RDX: RETGEN(rdx, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RDI: RETGEN(rdi, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RSI: RETGEN(rsi, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RBP: RETGEN(rbp, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RSP: RETGEN(rsp, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R8: RETGEN(r8, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R9: RETGEN(r9, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R10: RETGEN(r10, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R11: RETGEN(r11, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R12: RETGEN(r12, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R13: RETGEN(r13, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R14: RETGEN(r14, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_R15: RETGEN(r15, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RIP: RETGEN(rip, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_RFLAGS: RETGEN(rflags, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_CS: RETGEN(cs, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_FS: RETGEN(fs, thread.uts.ts64, ts); case APIGEE_PLCRASH_X86_64_GS: RETGEN(gs, thread.uts.ts64, ts); default: // Unsupported register __builtin_trap(); } /* Should not be reachable */ return 0; }
/** * @internal * 32-bit implementation of plcrash_async_thread_state_get_reg() */ static apigee_plcrash_greg_t plcrash_async_thread_state_get_reg_32 (const apigee_plcrash_async_thread_state_t *thread_state, apigee_plcrash_regnum_t regnum) { const apigee_plcrash_async_thread_state_t *ts = thread_state; /* All word-sized registers */ switch (regnum) { case APIGEE_PLCRASH_X86_EAX: RETGEN(eax, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EDX: RETGEN(edx, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_ECX: RETGEN(ecx, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EBX: RETGEN(ebx, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EBP: RETGEN(ebp, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_ESI: RETGEN(esi, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EDI: RETGEN(edi, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_ESP: RETGEN(esp, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EIP: RETGEN(eip, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_EFLAGS: RETGEN(eflags, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_TRAPNO: RETGEN(trapno, exception.ues.es32, ts); case APIGEE_PLCRASH_X86_CS: RETGEN(cs, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_DS: RETGEN(ds, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_ES: RETGEN(es, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_FS: RETGEN(fs, thread.uts.ts32, ts); case APIGEE_PLCRASH_X86_GS: RETGEN(gs, thread.uts.ts32, ts); default: // Unsupported register __builtin_trap(); } /* Shouldn't be reachable */ return 0; }
// PLFrameWalker API Apigee_plframe_error_t Apigee_plframe_get_reg (Apigee_plframe_cursor_t *cursor, Apigee_plframe_regnum_t regnum, Apigee_plframe_greg_t *reg) { ucontext_t *uap = cursor->uap; /* Supported register for this context state? */ if (cursor->fp[0] != NULL) { if (regnum == Apigee_PLFRAME_PDEF_REG_IP) { *reg = (Apigee_plframe_greg_t) cursor->fp[2] - 4; // offset by 1 instruction return Apigee_PLFRAME_ESUCCESS; } return Apigee_PLFRAME_ENOTSUP; } /* All GP registers */ switch (regnum) { case Apigee_PLFRAME_PPC_SRR0: RETGEN(srr0, ss, uap, reg); case Apigee_PLFRAME_PPC_SRR1: RETGEN(srr1, ss, uap, reg); case Apigee_PLFRAME_PPC_DAR: RETGEN(dar, es, uap, reg); case Apigee_PLFRAME_PPC_DSISR: RETGEN(dsisr, es, uap, reg); case Apigee_PLFRAME_PPC_R0: RETGEN(r0, ss, uap, reg); case Apigee_PLFRAME_PPC_R1: RETGEN(r1, ss, uap, reg); case Apigee_PLFRAME_PPC_R2: RETGEN(r2, ss, uap, reg); case Apigee_PLFRAME_PPC_R3: RETGEN(r3, ss, uap, reg); case Apigee_PLFRAME_PPC_R4: RETGEN(r4, ss, uap, reg); case Apigee_PLFRAME_PPC_R5: RETGEN(r5, ss, uap, reg); case Apigee_PLFRAME_PPC_R6: RETGEN(r6, ss, uap, reg); case Apigee_PLFRAME_PPC_R7: RETGEN(r7, ss, uap, reg); case Apigee_PLFRAME_PPC_R8: RETGEN(r8, ss, uap, reg); case Apigee_PLFRAME_PPC_R9: RETGEN(r9, ss, uap, reg); case Apigee_PLFRAME_PPC_R10: RETGEN(r10, ss, uap, reg); case Apigee_PLFRAME_PPC_R11: RETGEN(r11, ss, uap, reg); case Apigee_PLFRAME_PPC_R12: RETGEN(r12, ss, uap, reg); case Apigee_PLFRAME_PPC_R13: RETGEN(r13, ss, uap, reg); case Apigee_PLFRAME_PPC_R14: RETGEN(r14, ss, uap, reg); case Apigee_PLFRAME_PPC_R15: RETGEN(r15, ss, uap, reg); case Apigee_PLFRAME_PPC_R16: RETGEN(r16, ss, uap, reg); case Apigee_PLFRAME_PPC_R17: RETGEN(r17, ss, uap, reg); case Apigee_PLFRAME_PPC_R18: RETGEN(r18, ss, uap, reg); case Apigee_PLFRAME_PPC_R19: RETGEN(r19, ss, uap, reg); case Apigee_PLFRAME_PPC_R20: RETGEN(r20, ss, uap, reg); case Apigee_PLFRAME_PPC_R21: RETGEN(r21, ss, uap, reg); case Apigee_PLFRAME_PPC_R22: RETGEN(r22, ss, uap, reg); case Apigee_PLFRAME_PPC_R23: RETGEN(r23, ss, uap, reg); case Apigee_PLFRAME_PPC_R24: RETGEN(r24, ss, uap, reg); case Apigee_PLFRAME_PPC_R25: RETGEN(r25, ss, uap, reg); case Apigee_PLFRAME_PPC_R26: RETGEN(r26, ss, uap, reg); case Apigee_PLFRAME_PPC_R27: RETGEN(r27, ss, uap, reg); case Apigee_PLFRAME_PPC_R28: RETGEN(r28, ss, uap, reg); case Apigee_PLFRAME_PPC_R29: RETGEN(r29, ss, uap, reg); case Apigee_PLFRAME_PPC_R30: RETGEN(r30, ss, uap, reg); case Apigee_PLFRAME_PPC_R31: RETGEN(r31, ss, uap, reg); case Apigee_PLFRAME_PPC_CR: RETGEN(cr, ss, uap, reg); case Apigee_PLFRAME_PPC_XER: RETGEN(xer, ss, uap, reg); case Apigee_PLFRAME_PPC_LR: RETGEN(lr, ss, uap, reg); case Apigee_PLFRAME_PPC_CTR: RETGEN(ctr, ss, uap, reg); case Apigee_PLFRAME_PPC_VRSAVE: RETGEN(vrsave, ss, uap, reg); default: // Unsupported register return Apigee_PLFRAME_EBADREG; } /* Shouldn't be reachable */ return Apigee_PLFRAME_EUNKNOWN; }
// PLFrameWalker API plframe_error_t plframe_get_reg (plframe_cursor_t *cursor, plframe_regnum_t regnum, plframe_greg_t *reg) { ucontext_t *uap = cursor->uap; /* Supported register for this context state? */ if (cursor->fp[0] != NULL) { if (regnum == PLFRAME_X86_64_RIP) { *reg = (plframe_greg_t) cursor->fp[1]; return PLFRAME_ESUCCESS; } return PLFRAME_ENOTSUP; } switch (regnum) { case PLFRAME_X86_64_RAX: RETGEN(rax, ss, uap, reg); case PLFRAME_X86_64_RBX: RETGEN(rbx, ss, uap, reg); case PLFRAME_X86_64_RCX: RETGEN(rcx, ss, uap, reg); case PLFRAME_X86_64_RDX: RETGEN(rdx, ss, uap, reg); case PLFRAME_X86_64_RDI: RETGEN(rdi, ss, uap, reg); case PLFRAME_X86_64_RSI: RETGEN(rsi, ss, uap, reg); case PLFRAME_X86_64_RBP: RETGEN(rbp, ss, uap, reg); case PLFRAME_X86_64_RSP: RETGEN(rsp, ss, uap, reg); case PLFRAME_X86_64_R10: RETGEN(r10, ss, uap, reg); case PLFRAME_X86_64_R11: RETGEN(r11, ss, uap, reg); case PLFRAME_X86_64_R12: RETGEN(r12, ss, uap, reg); case PLFRAME_X86_64_R13: RETGEN(r13, ss, uap, reg); case PLFRAME_X86_64_R14: RETGEN(r14, ss, uap, reg); case PLFRAME_X86_64_R15: RETGEN(r15, ss, uap, reg); case PLFRAME_X86_64_RIP: RETGEN(rip, ss, uap, reg); case PLFRAME_X86_64_RFLAGS: RETGEN(rflags, ss, uap, reg); case PLFRAME_X86_64_CS: RETGEN(cs, ss, uap, reg); case PLFRAME_X86_64_FS: RETGEN(fs, ss, uap, reg); case PLFRAME_X86_64_GS: RETGEN(gs, ss, uap, reg); default: // Unsupported register break; } return PLFRAME_ENOTSUP; }