// -*- eval: (read-only-mode) -*- // WARNING: this file is autogenerated. // Change and run gen_getpc.rb >getpc-inl.h if you want to // update. (And submit both files) // What this file does? We have several possible ways of fetching PC // (program counter) of signal's ucontext. We explicitly choose to // avoid ifdef-ing specific OSes (or even specific versions), to // increase our chances that stuff simply works. Comments below refer // to OS/architecture combos for documentation purposes, but what // works is what is used. // How it does it? It uses lightweight C++ template magic where // "wrong" ucontext_t{nullptr}-> combos are // automagically filtered out (via SFINAE). // Each known case is represented as a template class. For SFINAE // reasons we masquerade ucontext_t type behind U template // parameter. And we also parameterize by parent class. This allows us // to arrange all template instantiations in a single ordered chain of // inheritance. See RawUCToPC below. // Note, we do anticipate that most times exactly one of those access // methods works. But we're prepared there could be several. In // particular, according to previous comments Solaris/x86 also has // REG_RIP defined, but it is somehow wrong. So we're careful about // preserving specific order. We couldn't handle this "multiplicity" // aspect in pure C++, so we use code generation. namespace internal { struct Empty { #ifdef DEFINE_TRIVIAL_GET #define HAVE_TRIVIAL_GET // special thing for stacktrace_generic_fp-inl which wants no-op case static void* Get(...) { return nullptr; } #endif }; // NetBSD has really nice portable macros template struct get_c47a30af : public P { }; #ifdef _UC_MACHINE_PC template struct get_c47a30af> : public P { static void* Get(const U* uc) { // NetBSD has really nice portable macros return (void*)(_UC_MACHINE_PC(uc)); } }; #endif // _UC_MACHINE_PC // Solaris/x86 template struct get_c4719e8d : public P { }; #ifdef REG_PC template struct get_c4719e8duc_mcontext.gregs[REG_PC])>> : public P { static void* Get(const U* uc) { // Solaris/x86 return (void*)(uc->uc_mcontext.gregs[REG_PC]); } }; #endif // REG_PC // Linux/i386 template struct get_278cba85 : public P { }; #ifdef REG_EIP template struct get_278cba85uc_mcontext.gregs[REG_EIP])>> : public P { static void* Get(const U* uc) { // Linux/i386 return (void*)(uc->uc_mcontext.gregs[REG_EIP]); } }; #endif // REG_EIP // Linux/amd64 template struct get_b49f2593 : public P { }; #ifdef REG_RIP template struct get_b49f2593uc_mcontext.gregs[REG_RIP])>> : public P { static void* Get(const U* uc) { // Linux/amd64 return (void*)(uc->uc_mcontext.gregs[REG_RIP]); } }; #endif // REG_RIP // Linux/ia64 template struct get_8fda99d3 : public P { }; template struct get_8fda99d3uc_mcontext.sc_ip)>> : public P { static void* Get(const U* uc) { // Linux/ia64 return (void*)(uc->uc_mcontext.sc_ip); } }; // Linux/loongarch64 template struct get_4e9b682d : public P { }; template struct get_4e9b682duc_mcontext.__pc)>> : public P { static void* Get(const U* uc) { // Linux/loongarch64 return (void*)(uc->uc_mcontext.__pc); } }; // Linux/{mips,aarch64} template struct get_b94b7246 : public P { }; template struct get_b94b7246uc_mcontext.pc)>> : public P { static void* Get(const U* uc) { // Linux/{mips,aarch64} return (void*)(uc->uc_mcontext.pc); } }; // Linux/ppc template struct get_d0eeceae : public P { }; #ifdef PT_NIP template struct get_d0eeceaeuc_mcontext.uc_regs->gregs[PT_NIP])>> : public P { static void* Get(const U* uc) { // Linux/ppc return (void*)(uc->uc_mcontext.uc_regs->gregs[PT_NIP]); } }; #endif // PT_NIP // Linux/ppc template struct get_a81f6801 : public P { }; #ifdef PT_NIP template struct get_a81f6801uc_mcontext.gp_regs[PT_NIP])>> : public P { static void* Get(const U* uc) { // Linux/ppc return (void*)(uc->uc_mcontext.gp_regs[PT_NIP]); } }; #endif // PT_NIP // Linux/riscv template struct get_24e794ef : public P { }; #ifdef REG_PC template struct get_24e794efuc_mcontext.__gregs[REG_PC])>> : public P { static void* Get(const U* uc) { // Linux/riscv return (void*)(uc->uc_mcontext.__gregs[REG_PC]); } }; #endif // REG_PC // Linux/s390 template struct get_d9a75ed3 : public P { }; template struct get_d9a75ed3uc_mcontext.psw.addr)>> : public P { static void* Get(const U* uc) { // Linux/s390 return (void*)(uc->uc_mcontext.psw.addr); } }; // Linux/arm (32-bit; legacy) template struct get_07114491 : public P { }; template struct get_07114491uc_mcontext.arm_pc)>> : public P { static void* Get(const U* uc) { // Linux/arm (32-bit; legacy) return (void*)(uc->uc_mcontext.arm_pc); } }; // FreeBSD/i386 template struct get_9be162e6 : public P { }; template struct get_9be162e6uc_mcontext.mc_eip)>> : public P { static void* Get(const U* uc) { // FreeBSD/i386 return (void*)(uc->uc_mcontext.mc_eip); } }; // FreeBSD/ppc template struct get_2812b129 : public P { }; template struct get_2812b129uc_mcontext.mc_srr0)>> : public P { static void* Get(const U* uc) { // FreeBSD/ppc return (void*)(uc->uc_mcontext.mc_srr0); } }; // FreeBSD/x86_64 template struct get_5bb1da03 : public P { }; template struct get_5bb1da03uc_mcontext.mc_rip)>> : public P { static void* Get(const U* uc) { // FreeBSD/x86_64 return (void*)(uc->uc_mcontext.mc_rip); } }; // OS X (i386, <=10.4) template struct get_880f83fe : public P { }; template struct get_880f83feuc_mcontext->ss.eip)>> : public P { static void* Get(const U* uc) { // OS X (i386, <=10.4) return (void*)(uc->uc_mcontext->ss.eip); } }; // OS X (i386, >=10.5) template struct get_92fcd89a : public P { }; template struct get_92fcd89auc_mcontext->__ss.__eip)>> : public P { static void* Get(const U* uc) { // OS X (i386, >=10.5) return (void*)(uc->uc_mcontext->__ss.__eip); } }; // OS X (x86_64) template struct get_773e27c8 : public P { }; template struct get_773e27c8uc_mcontext->ss.rip)>> : public P { static void* Get(const U* uc) { // OS X (x86_64) return (void*)(uc->uc_mcontext->ss.rip); } }; // OS X (>=10.5 [untested]) template struct get_6627078a : public P { }; template struct get_6627078auc_mcontext->__ss.__rip)>> : public P { static void* Get(const U* uc) { // OS X (>=10.5 [untested]) return (void*)(uc->uc_mcontext->__ss.__rip); } }; // OS X (ppc, ppc64 [untested]) template struct get_da992aca : public P { }; template struct get_da992acauc_mcontext->ss.srr0)>> : public P { static void* Get(const U* uc) { // OS X (ppc, ppc64 [untested]) return (void*)(uc->uc_mcontext->ss.srr0); } }; // OS X (>=10.5 [untested]) template struct get_cce47a40 : public P { }; template struct get_cce47a40uc_mcontext->__ss.__srr0)>> : public P { static void* Get(const U* uc) { // OS X (>=10.5 [untested]) return (void*)(uc->uc_mcontext->__ss.__srr0); } }; // OS X (arm64) template struct get_0a082e42 : public P { }; template struct get_0a082e42uc_mcontext->__ss.__pc)>> : public P { static void* Get(const U* uc) { // OS X (arm64) return (void*)(uc->uc_mcontext->__ss.__pc); } }; // OpenBSD/i386 template struct get_3baa113a : public P { }; template struct get_3baa113asc_eip)>> : public P { static void* Get(const U* uc) { // OpenBSD/i386 return (void*)(uc->sc_eip); } }; // OpenBSD/x86_64 template struct get_79f33851 : public P { }; template struct get_79f33851sc_rip)>> : public P { static void* Get(const U* uc) { // OpenBSD/x86_64 return (void*)(uc->sc_rip); } }; inline void* RawUCToPC(const ucontext_t* uc) { // OpenBSD/x86_64 using g_79f33851 = get_79f33851; // OpenBSD/i386 using g_3baa113a = get_3baa113a; // OS X (arm64) using g_0a082e42 = get_0a082e42; // OS X (>=10.5 [untested]) using g_cce47a40 = get_cce47a40; // OS X (ppc, ppc64 [untested]) using g_da992aca = get_da992aca; // OS X (>=10.5 [untested]) using g_6627078a = get_6627078a; // OS X (x86_64) using g_773e27c8 = get_773e27c8; // OS X (i386, >=10.5) using g_92fcd89a = get_92fcd89a; // OS X (i386, <=10.4) using g_880f83fe = get_880f83fe; // FreeBSD/x86_64 using g_5bb1da03 = get_5bb1da03; // FreeBSD/ppc using g_2812b129 = get_2812b129; // FreeBSD/i386 using g_9be162e6 = get_9be162e6; // Linux/arm (32-bit; legacy) using g_07114491 = get_07114491; // Linux/s390 using g_d9a75ed3 = get_d9a75ed3; // Linux/riscv (with #ifdef REG_PC) using g_24e794ef = get_24e794ef; // Linux/ppc (with #ifdef PT_NIP) using g_a81f6801 = get_a81f6801; // Linux/ppc (with #ifdef PT_NIP) using g_d0eeceae = get_d0eeceae; // Linux/{mips,aarch64} using g_b94b7246 = get_b94b7246; // Linux/loongarch64 using g_4e9b682d = get_4e9b682d; // Linux/ia64 using g_8fda99d3 = get_8fda99d3; // Linux/amd64 (with #ifdef REG_RIP) using g_b49f2593 = get_b49f2593; // Linux/i386 (with #ifdef REG_EIP) using g_278cba85 = get_278cba85; // Solaris/x86 (with #ifdef REG_PC) using g_c4719e8d = get_c4719e8d; // NetBSD has really nice portable macros (with #ifdef _UC_MACHINE_PC) using g_c47a30af = get_c47a30af; return g_c47a30af::Get(uc); } } // namespace internal