Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions src/backends/native/sentry_crash_daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,14 +2119,18 @@ build_stacktrace_from_ctx(const sentry_crash_context_t *ctx)
}

/**
* Build native crash event with exception, mechanism, and debug_meta
* Build a native event and set the level, mechanism, and handled state
*
* @param ctx Crash context
* @param event_file_path Path to event file from parent process
* @param event_file_path Path to base event file from parent process
* @param level Event level (e.g. "fatal")
* @param mechanism_type Exception mechanism type (e.g. "signalhandler")
* @param handled Whether the mechanism was handled
*/
static sentry_value_t
build_native_crash_event(
const sentry_crash_context_t *ctx, const char *event_file_path)
build_native_event(const sentry_crash_context_t *ctx,
const char *event_file_path, const char *level, const char *mechanism_type,
bool handled)
{
// Read base event from parent's file
sentry_value_t event = sentry_value_new_null();
Expand All @@ -2152,8 +2156,7 @@ build_native_crash_event(
sentry_value_set_by_key(
event, "platform", sentry_value_new_string("native"));

// Set level to fatal
sentry_value_set_by_key(event, "level", sentry_value_new_string("fatal"));
sentry_value_set_by_key(event, "level", sentry_value_new_string(level));

// Build exception
const char *signal_name = "UNKNOWN";
Expand All @@ -2175,10 +2178,11 @@ build_native_crash_event(
// Add mechanism
sentry_value_t mechanism = sentry_value_new_object();
sentry_value_set_by_key(
mechanism, "type", sentry_value_new_string("signalhandler"));
Comment thread
bitsandfoxes marked this conversation as resolved.
mechanism, "type", sentry_value_new_string(mechanism_type));
sentry_value_set_by_key(
mechanism, "synthetic", sentry_value_new_bool(true));
sentry_value_set_by_key(mechanism, "handled", sentry_value_new_bool(false));
sentry_value_set_by_key(
mechanism, "handled", sentry_value_new_bool(handled));

// Add signal metadata
sentry_value_t meta = sentry_value_new_object();
Expand Down Expand Up @@ -2477,7 +2481,8 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options,
// Build native crash event (always include threads with names)
SENTRY_DEBUGF("write_envelope_with_native_stacktrace: minidump_path=%s",
minidump_path ? minidump_path : "(null)");
sentry_value_t event = build_native_crash_event(ctx, event_file_path);
sentry_value_t event = build_native_event(
ctx, event_file_path, "fatal", "signalhandler", false);

// Serialize event to JSON
size_t event_size = 0;
Expand Down
115 changes: 39 additions & 76 deletions src/backends/sentry_backend_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,9 +767,42 @@ native_backend_write_attachments(const sentry_path_t *event_path)
}
}

#if defined(SENTRY_PLATFORM_WINDOWS)
// Sentry's symbolicator needs `contexts.device.arch` to process PE modules. If
// the scope already carries a device context with arch (host SDKs like Unity
// provide one), leave it; otherwise synthesize a minimal one so native-only
// consumers still symbolicate.
static void
ensure_device_arch(sentry_value_t event)
{
sentry_value_t contexts = sentry_value_get_by_key(event, "contexts");
if (sentry_value_is_null(contexts)) {
contexts = sentry_value_new_object();
sentry_value_set_by_key(event, "contexts", contexts);
}
sentry_value_t device = sentry_value_get_by_key(contexts, "device");
if (sentry_value_is_null(device)) {
device = sentry_value_new_object();
sentry_value_set_by_key(
device, "type", sentry_value_new_string("device"));
sentry_value_set_by_key(contexts, "device", device);
}
if (!sentry_value_is_null(sentry_value_get_by_key(device, "arch"))) {
return;
}
# if defined(_M_AMD64)
sentry_value_set_by_key(device, "arch", sentry_value_new_string("x86_64"));
# elif defined(_M_IX86)
sentry_value_set_by_key(device, "arch", sentry_value_new_string("x86"));
# elif defined(_M_ARM64)
sentry_value_set_by_key(device, "arch", sentry_value_new_string("arm64"));
# endif
}
#endif

static void
native_backend_flush_scope(
sentry_backend_t *backend, const sentry_options_t *UNUSED(options))
sentry_backend_t *backend, const sentry_options_t *options)
{
native_backend_state_t *state = (native_backend_state_t *)backend->data;
if (!state || !state->event_path) {
Expand All @@ -789,60 +822,14 @@ native_backend_flush_scope(
sentry_value_set_by_key(
event, "level", sentry__value_new_level(SENTRY_LEVEL_FATAL));

// Apply scope with contexts (includes OS, device info from Sentry)
// Apply scope with contexts
SENTRY_WITH_SCOPE (scope) {
// Get contexts from scope (includes OS info)
sentry_value_t os_context
= sentry_value_get_by_key(scope->contexts, "os");
if (!sentry_value_is_null(os_context)) {
sentry_value_t event_contexts = sentry_value_new_object();
sentry_value_set_by_key(event_contexts, "os", os_context);
sentry_value_incref(os_context);

sentry__scope_apply_to_event(scope, options, event, SENTRY_SCOPE_NONE);
}
#if defined(SENTRY_PLATFORM_WINDOWS)
// Add device context with arch for Windows native events
// This is required for Sentry's symbolicator to process PE modules
sentry_value_t device_context = sentry_value_new_object();
sentry_value_set_by_key(
device_context, "type", sentry_value_new_string("device"));
# if defined(_M_AMD64)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("x86_64"));
# elif defined(_M_IX86)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("x86"));
# elif defined(_M_ARM64)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("arm64"));
# endif
sentry_value_set_by_key(event_contexts, "device", device_context);
ensure_device_arch(event);
#endif

sentry_value_set_by_key(event, "contexts", event_contexts);
}

// Also copy other scope data (user, tags, extra, etc.)
sentry_value_t user = scope->user;
if (sentry_value_get_type(user) == SENTRY_VALUE_TYPE_OBJECT
&& sentry_value_get_length(user) > 0) {
sentry_value_set_by_key(event, "user", user);
sentry_value_incref(user);
}

sentry_value_t tags = scope->tags;
if (!sentry_value_is_null(tags)) {
sentry_value_set_by_key(event, "tags", tags);
sentry_value_incref(tags);
}

sentry_value_t extra = scope->extra;
if (!sentry_value_is_null(extra)) {
sentry_value_set_by_key(event, "extra", extra);
sentry_value_incref(extra);
}
}

// Serialize to JSON (so it can be deserialized on next start)
size_t json_len = 0;
char *json_str = sentry__value_to_json(event, &json_len);
sentry_value_decref(event);
Expand Down Expand Up @@ -1029,32 +1016,8 @@ native_backend_except(sentry_backend_t *backend, const sentry_ucontext_t *uctx)
sentry__scope_apply_to_event(
scope, options, event, SENTRY_SCOPE_BREADCRUMBS);
}

#if defined(SENTRY_PLATFORM_WINDOWS)
// Add device context with arch for Windows native events
// This is required for Sentry's symbolicator to process PE
// modules
sentry_value_t contexts
= sentry_value_get_by_key(event, "contexts");
if (sentry_value_is_null(contexts)) {
contexts = sentry_value_new_object();
sentry_value_set_by_key(event, "contexts", contexts);
}
sentry_value_t device_context = sentry_value_new_object();
sentry_value_set_by_key(
device_context, "type", sentry_value_new_string("device"));
# if defined(_M_AMD64)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("x86_64"));
# elif defined(_M_IX86)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("x86"));
# elif defined(_M_ARM64)
sentry_value_set_by_key(
device_context, "arch", sentry_value_new_string("arm64"));
# endif
sentry_value_set_by_key(contexts, "device", device_context);

ensure_device_arch(event);
#endif

#ifndef SENTRY_SCREENSHOT_NONE
Expand Down
Loading