-
-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
minimal implementation of sdk-version dependent... #752
Conversation
...dynamic loader but mostly to show that using the generic unwinder is probably a dead end.
Instructions and example for changelogPlease add an entry to Example: ## Unreleased
- minimal implementation of sdk-version dependent ([#752](https://github.com/getsentry/sentry-native/pull/752)) If none of the above apply, you can opt out of this check by adding |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, although it is a bit complex admittedly.
No matter what we decide specifically, we should update our fork regardless, maybe independently from this PR.
void | ||
sentry__unload_unwinder() | ||
{ | ||
int result = dlclose(handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
manpage doesn’t really say if you can safely pass NULL
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should surely check this either way.
static android_unwind_stack_t android_unwind_stack; | ||
static void *handle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should explicitly initialize these to NULL
@@ -1,6 +1,5 @@ | |||
extern "C" { | |||
#include "sentry_boot.h" | |||
#include "sentry_core.h" | |||
#include <sentry.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this whole file isn’t used anymore, is it?
(void)addr; | ||
(void)uctx; | ||
trace_state state = { ptrs, ptrs + max_frames }; | ||
_Unwind_Backtrace(unwind_callback, &state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always confuse the _Unwind_*
and the unw_*
APIs. So unfortunate that the first one does not allow unwinding from uctx.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unw_
prefix is the "namespace" of libunwind
which would be very convenient library and I would love to use, but AOSP dropped it and upstream doesn't really support Android.
But even if it would provide a uctx
interface, I am not sure if the added complexity justifies the changes, as long as it doesn't offer any expected/significant improvements in the stack trace (for instance by mapping to libunwindstack
).
This is especially true since most users use a pre-built package, which doesn't gain anything from the size improvements when using only a slimmapper.so
, without ("manually") removing the legacy.so
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
libunwind
is still deployed with NDK as the unwinder for C++ exception-handling and C scope-cleanups but it is not exposed as an app-developer library.
The hint that NDK versions below r23 re-export the symbols of the previous libgcc unwinder, potentially screwing with client code that uses exception-handling, shows that stability of that "interface" is not a driver for decisions). Nonetheless, i can also try to access this implementation.
This is probably the most valuable outcome of this investigation. |
Closing since there is no conclusive net improvement visible for the changes required:
what we can extract from this:
|
...dynamic loader, but mostly to show that using the generic unwinder is probably a dead end. There was a lot more time invested than is visible, but I wanted to break this down to a minimal implementation to be able to discuss its issues. This contains an approach to tackle #743, but it has many problems:
libunwindstack
, in SDK 28+, is still not exposed via any recent NDK and is thus not accessible to App developers or their dependencies but only to platform developers.libunwindstack
to make it available to app developers indirectly, so while this PR uses it for SDKs >= 28, the unwinder doesn't provide a better stack-trace than our stripped-down version of libunwindstack.ucontext_t
or a passed-in address, which leads to stack traces that start fromsentry-native
frames.So, at this point, it is relatively obvious that we cannot release this simply because it provides no visible improvements to the users (or rather regressions if you are deploying on targets with SDK >= 28).
It is not all bad, though:
libunwindstack
in a shared library, which we dynamically load duringsentry_init
, I could get down to 1.5MiB (for the.so
) from 2MiB (for the.a
) onaarch64
..so
of only 26KiB, which would allow users who target only SDK >= 28 to drop the heavy legacy.so
from their deployment packages.So the question is how we should proceed with this (if at all):
sentry_init
, cash in the package-size reduction, but not provide any improvements for SDK >= 28.libunwindstack
dynamically, but it is very unclear how successful this will be. For one, it requires us to provide a minimal header environment to build the unwinder code insentry-native
and it requires the platform's builders to provide symbol-name stability for us to find even the small subset of the interface across deployed androids in the wild.backtrace()
implementation in API 33 wrapslibunwindstack
and then replace the generic unwinder implementation we have now withbacktrace()
. In the worst case, it would at least provide us with an interface for a relative start into the stack.Please chime in with further suggestions.