| #include "Python.h" |
| |
| #include "pycore_ceval.h" |
| #include "pycore_jit_publish.h" |
| #include "pycore_jit_unwind.h" |
| |
| #ifdef _Py_JIT |
| |
| #if defined(PY_HAVE_JIT_GDB_UNWIND) \ |
| || defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| struct _PyJitCodeRegistration { |
| void *gdb_handle; |
| void *gnu_backtrace_handle; |
| }; |
| #endif |
| |
| static void |
| jit_register_perf_code(const void *code_addr, size_t code_size, |
| const char *entry, const char *filename) |
| { |
| #ifdef PY_HAVE_PERF_TRAMPOLINE |
| _PyPerf_Callbacks callbacks; |
| _PyPerfTrampoline_GetCallbacks(&callbacks); |
| if (callbacks.write_state == _Py_perfmap_jit_callbacks.write_state) { |
| _PyPerfJit_WriteNamedCode( |
| code_addr, code_size, entry, filename); |
| } |
| #else |
| (void)code_addr; |
| (void)code_size; |
| (void)entry; |
| (void)filename; |
| #endif |
| } |
| |
| #if defined(PY_HAVE_JIT_GDB_UNWIND) |
| static void |
| jit_register_gdb_code(_PyJitCodeRegistration *registration, |
| const void *code_addr, size_t code_size, |
| const char *entry, const char *filename) |
| { |
| registration->gdb_handle = _PyJitUnwind_GdbRegisterCode( |
| code_addr, code_size, entry, filename); |
| } |
| |
| static void |
| jit_unregister_gdb_code(_PyJitCodeRegistration *registration) |
| { |
| if (registration->gdb_handle != NULL) { |
| _PyJitUnwind_GdbUnregisterCode(registration->gdb_handle); |
| registration->gdb_handle = NULL; |
| } |
| } |
| #endif |
| |
| #if defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| static void |
| jit_register_gnu_backtrace_code(_PyJitCodeRegistration *registration, |
| const void *code_addr, size_t code_size) |
| { |
| registration->gnu_backtrace_handle = |
| _PyJitUnwind_GnuBacktraceRegisterCode(code_addr, code_size); |
| } |
| |
| static void |
| jit_unregister_gnu_backtrace_code(_PyJitCodeRegistration *registration) |
| { |
| if (registration->gnu_backtrace_handle != NULL) { |
| _PyJitUnwind_GnuBacktraceUnregisterCode( |
| registration->gnu_backtrace_handle); |
| registration->gnu_backtrace_handle = NULL; |
| } |
| } |
| #endif |
| |
| _PyJitCodeRegistration * |
| _PyJit_RegisterCode(const void *code_addr, size_t code_size, |
| const char *entry, const char *filename) |
| { |
| jit_register_perf_code(code_addr, code_size, entry, filename); |
| // Perf publication has no teardown handle, so it is intentionally |
| // not counted below. |
| |
| #if !defined(PY_HAVE_JIT_GDB_UNWIND) \ |
| && !defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| return NULL; |
| #else |
| _PyJitCodeRegistration *registration = PyMem_RawCalloc( |
| 1, sizeof(*registration)); |
| if (registration == NULL) { |
| return NULL; |
| } |
| |
| // Partial failures are non-fatal: the JIT code can still execute, but |
| // unavailable tooling may not be able to unwind it. |
| int any_registered = 0; |
| # if defined(PY_HAVE_JIT_GDB_UNWIND) |
| jit_register_gdb_code( |
| registration, code_addr, code_size, entry, filename); |
| any_registered |= registration->gdb_handle != NULL; |
| # endif |
| # if defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| jit_register_gnu_backtrace_code( |
| registration, code_addr, code_size); |
| any_registered |= registration->gnu_backtrace_handle != NULL; |
| # endif |
| if (!any_registered) { |
| PyMem_RawFree(registration); |
| return NULL; |
| } |
| return registration; |
| #endif |
| } |
| |
| void |
| _PyJit_UnregisterCode(_PyJitCodeRegistration *registration) |
| { |
| #if !defined(PY_HAVE_JIT_GDB_UNWIND) \ |
| && !defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| assert(registration == NULL); |
| (void)registration; |
| #else |
| if (registration == NULL) { |
| return; |
| } |
| |
| # if defined(PY_HAVE_JIT_GNU_BACKTRACE_UNWIND) |
| jit_unregister_gnu_backtrace_code(registration); |
| # endif |
| # if defined(PY_HAVE_JIT_GDB_UNWIND) |
| jit_unregister_gdb_code(registration); |
| # endif |
| PyMem_RawFree(registration); |
| #endif |
| } |
| |
| #endif // _Py_JIT |