Add cpptrace::can_get_safe_object_frame and add ctrace prefix for can_signal_safe_unwind

This commit is contained in:
Jeremy Rifkin 2025-02-20 21:36:19 -06:00
parent 98ea78445c
commit 6877782d96
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
9 changed files with 32 additions and 6 deletions

View File

@ -774,6 +774,7 @@ namespace cpptrace {
}; };
void get_safe_object_frame(frame_ptr address, safe_object_frame* out); void get_safe_object_frame(frame_ptr address, safe_object_frame* out);
bool can_signal_safe_unwind(); bool can_signal_safe_unwind();
bool can_get_safe_object_frame();
} }
``` ```
@ -790,9 +791,9 @@ see the comprehensive overview and demo at [signal-safe-tracing.md](docs/signal-
> [!IMPORTANT] > [!IMPORTANT]
> Currently signal-safe stack unwinding is only possible with `libunwind`, which must be > Currently signal-safe stack unwinding is only possible with `libunwind`, which must be
> [manually enabled](#library-back-ends). If signal-safe unwinding isn't supported, `safe_generate_raw_trace` will just > [manually enabled](#library-back-ends). If signal-safe unwinding isn't supported, `safe_generate_raw_trace` will just
> produce an empty trace. `can_signal_safe_unwind` can be used to check for signal-safe unwinding support. If object > produce an empty trace. `can_signal_safe_unwind` can be used to check for signal-safe unwinding support and
> information can't be resolved in a signal-safe way then `get_safe_object_frame` will not populate fields beyond the > `can_get_safe_object_frame` can be used to check `get_safe_object_frame` support. If object information can't be
> `raw_address`. > resolved in a signal-safe way then `get_safe_object_frame` will not populate fields beyond the `raw_address`.
> [!IMPORTANT] > [!IMPORTANT]
> `_dl_find_object` is required for signal-safe stack tracing. This is a relatively recent addition to glibc, added in > `_dl_find_object` is required for signal-safe stack tracing. This is a relatively recent addition to glibc, added in

View File

@ -168,5 +168,6 @@ struct ctrace_safe_object_frame {
}; };
size_t ctrace_safe_generate_raw_trace(ctrace_frame_ptr* buffer, size_t size, size_t skip, size_t max_depth); size_t ctrace_safe_generate_raw_trace(ctrace_frame_ptr* buffer, size_t size, size_t skip, size_t max_depth);
void ctrace_get_safe_object_frame(ctrace_frame_ptr address, ctrace_safe_object_frame* out); void ctrace_get_safe_object_frame(ctrace_frame_ptr address, ctrace_safe_object_frame* out);
ctrace_bool can_signal_safe_unwind(); ctrace_bool ctrace_can_signal_safe_unwind();
ctrace_bool ctrace_can_get_safe_object_frame();
``` ```

View File

@ -73,6 +73,7 @@ namespace cpptrace {
void get_safe_object_frame(frame_ptr address, safe_object_frame* out); void get_safe_object_frame(frame_ptr address, safe_object_frame* out);
// signal-safe // signal-safe
bool can_signal_safe_unwind(); bool can_signal_safe_unwind();
bool can_get_safe_object_frame();
} }
``` ```
@ -104,6 +105,9 @@ only ways to do this safely as far as I can tell.
`safe_generate_raw_trace` will just produce an empty trace and if object information can't be resolved in a signal-safe `safe_generate_raw_trace` will just produce an empty trace and if object information can't be resolved in a signal-safe
way then `get_safe_object_frame` will not populate fields beyond the `raw_address`. way then `get_safe_object_frame` will not populate fields beyond the `raw_address`.
`cpptrace::can_signal_safe_unwind` and `cpptrace::can_get_safe_object_frame` can be used to check for safe tracing
support.
Currently the only back-end that can unwind safely is libunwind. Currently, the only way I know to get `dladdr`'s Currently the only back-end that can unwind safely is libunwind. Currently, the only way I know to get `dladdr`'s
information in a signal-safe manner is `_dl_find_object`, which doesn't exist on macos (or windows of course). If anyone information in a signal-safe manner is `_dl_find_object`, which doesn't exist on macos (or windows of course). If anyone
knows ways to do these safely on other platforms, I'd be much appreciative. knows ways to do these safely on other platforms, I'd be much appreciative.

View File

@ -235,6 +235,7 @@ namespace cpptrace {
// signal-safe // signal-safe
CPPTRACE_EXPORT void get_safe_object_frame(frame_ptr address, safe_object_frame* out); CPPTRACE_EXPORT void get_safe_object_frame(frame_ptr address, safe_object_frame* out);
CPPTRACE_EXPORT bool can_signal_safe_unwind(); CPPTRACE_EXPORT bool can_signal_safe_unwind();
CPPTRACE_EXPORT bool can_get_safe_object_frame();
} }
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -131,7 +131,8 @@ CTRACE_BEGIN_DEFINITIONS
/* ctrace::safe: */ /* ctrace::safe: */
CPPTRACE_EXPORT size_t ctrace_safe_generate_raw_trace(ctrace_frame_ptr* buffer, size_t size, size_t skip, size_t max_depth); CPPTRACE_EXPORT size_t ctrace_safe_generate_raw_trace(ctrace_frame_ptr* buffer, size_t size, size_t skip, size_t max_depth);
CPPTRACE_EXPORT void ctrace_get_safe_object_frame(ctrace_frame_ptr address, ctrace_safe_object_frame* out); CPPTRACE_EXPORT void ctrace_get_safe_object_frame(ctrace_frame_ptr address, ctrace_safe_object_frame* out);
CPPTRACE_EXPORT ctrace_bool can_signal_safe_unwind(void); CPPTRACE_EXPORT ctrace_bool ctrace_can_signal_safe_unwind(void);
CPPTRACE_EXPORT ctrace_bool ctrace_can_get_safe_object_frame(void);
/* ctrace::io: */ /* ctrace::io: */
CPPTRACE_EXPORT ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color); CPPTRACE_EXPORT ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color);

View File

@ -53,6 +53,10 @@ namespace detail {
// may return the object that defines the function descriptor (and not the object that contains the code // may return the object that defines the function descriptor (and not the object that contains the code
// implementing the function), or fail to find any object at all. // implementing the function), or fail to find any object at all.
} }
bool has_get_safe_object_frame() {
return true;
}
} }
} }
#else #else
@ -63,6 +67,10 @@ namespace detail {
out->address_relative_to_object_start = 0; out->address_relative_to_object_start = 0;
out->object_path[0] = 0; out->object_path[0] = 0;
} }
bool has_get_safe_object_frame() {
return false;
}
} }
} }
#endif #endif

View File

@ -6,6 +6,8 @@
namespace cpptrace { namespace cpptrace {
namespace detail { namespace detail {
void get_safe_object_frame(frame_ptr address, safe_object_frame* out); void get_safe_object_frame(frame_ptr address, safe_object_frame* out);
bool has_get_safe_object_frame();
} }
} }

View File

@ -333,4 +333,8 @@ namespace cpptrace {
bool can_signal_safe_unwind() { bool can_signal_safe_unwind() {
return detail::has_safe_unwind(); return detail::has_safe_unwind();
} }
bool can_get_safe_object_frame() {
return detail::has_get_safe_object_frame();
}
} }

View File

@ -310,10 +310,14 @@ extern "C" {
cpptrace::get_safe_object_frame(address, reinterpret_cast<cpptrace::safe_object_frame*>(out)); cpptrace::get_safe_object_frame(address, reinterpret_cast<cpptrace::safe_object_frame*>(out));
} }
ctrace_bool can_signal_safe_unwind() { ctrace_bool ctrace_can_signal_safe_unwind() {
return cpptrace::can_signal_safe_unwind(); return cpptrace::can_signal_safe_unwind();
} }
ctrace_bool ctrace_can_get_safe_object_frame(void) {
return cpptrace::can_get_safe_object_frame();
}
// ctrace::io: // ctrace::io:
ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color) { ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color) {
if(!trace || !trace->frames) { if(!trace || !trace->frames) {