Skip to content
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

NDK metadata iterator #2035

Merged
merged 3 commits into from
Jun 4, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -1,79 +1 @@
{
"context": "Foo",
"metaData": {},
"severity": "info",
"unhandled": true,
"severityReason": {
"unhandledOverridden": false,
"type": "signal",
"attributes": {
"signalType": "SIGSEGV"
}
},
"exceptions": [
{
"errorClass": "SIGSEGV",
"message": "Whoops!",
"type": "c",
"stacktrace": [
{
"frameAddress": "0x0",
"symbolAddress": "0x0",
"loadAddress": "0x0",
"lineNumber": 58,
"isPC": true,
"file": "Something.c",
"method": "foo()"
}
]
}
],
"user": {
"id": "123",
"name": "Bob Bobbiton",
"email": "[email protected]"
},
"app": {
"version": "1.0",
"id": "fa02",
"type": "C",
"releaseStage": "dev",
"versionCode": 55,
"buildUUID": "123",
"binaryArch": "x86",
"duration": 9019,
"durationInForeground": 7017,
"inForeground": true,
"isLaunching": true
},
"device": {
"osName": "android",
"id": "my-id-123",
"locale": "en",
"osVersion": "9.1",
"manufacturer": "Google",
"model": "Nexus",
"orientation": "portrait",
"runtimeVersions": {
"androidApiLevel": 0,
"osBuild": ""
},
"cpuAbi": [],
"totalMemory": 1095092340,
"jailbroken": true,
"time": "1970-01-01T02:06:49Z"
},
"breadcrumbs": [],
"groupingHash": "Bar",
"usage": {
"callbacks": {}
},
"session": {
"id": "",
"startedAt": "",
"events": {
"handled": 0,
"unhandled": 0
}
}
}
{"context":"Foo","metaData":{},"severity":"info","unhandled":true,"severityReason":{"unhandledOverridden":false,"type":"signal","attributes":{"signalType":"SIGSEGV"}},"exceptions":[{"errorClass":"SIGSEGV","message":"Whoops!","type":"c","stacktrace":[{"frameAddress":"0x0","symbolAddress":"0x0","loadAddress":"0x0","lineNumber":58,"isPC":true,"file":"Something.c","method":"foo()"}]}],"user":{"id":"123","name":"Bob Bobbiton","email":"[email protected]"},"app":{"version":"1.0","id":"fa02","type":"C","releaseStage":"dev","versionCode":55,"buildUUID":"123","binaryArch":"x86","duration":9019,"durationInForeground":7017,"inForeground":true,"isLaunching":true},"device":{"osName":"android","id":"my-id-123","locale":"en","osVersion":"9.1","manufacturer":"Google","model":"Nexus","orientation":"portrait","runtimeVersions":{"androidApiLevel":0,"osBuild":""},"cpuAbi":[],"totalMemory":1095092340,"jailbroken":true,"time":"1970-01-01T02:06:49Z"},"breadcrumbs":[],"groupingHash":"Bar","usage":{"callbacks":{}},"threads":[]}
210 changes: 77 additions & 133 deletions bugsnag-plugin-android-ndk/src/main/jni/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,101 +376,71 @@ static void populate_metadata_value(JNIEnv *env, bugsnag_metadata *dst,
}

static void populate_metadata_obj(JNIEnv *env, bugsnag_metadata *dst,
jobject section, jobject section_keylist,
int index) {
jstring section_key = NULL;
const char *name = NULL;
jobject _value = NULL;

if (!bsg_jni_cache->initialized) {
goto exit;
}

section_key = bsg_safe_call_object_method(
env, section_keylist, bsg_jni_cache->ArrayList_get, (jint)index);
if (section_key == NULL) {
goto exit;
}
const char *section, jobject section_map) {
jobject entryset = NULL;
jobject entries = NULL;

_value = bsg_safe_call_object_method(env, section, bsg_jni_cache->Map_get,
section_key);
name = bsg_safe_get_string_utf_chars(env, section_key);
if (name == NULL) {
if (section_map == NULL) {
goto exit;
}

populate_metadata_value(env, dst, section, name, _value);

exit:
bsg_safe_release_string_utf_chars(env, section_key, name);
bsg_safe_delete_local_ref(env, section_key);
bsg_safe_delete_local_ref(env, _value);
}

static void populate_metadata_section(JNIEnv *env, bugsnag_metadata *dst,
jobject metadata, jobject keylist,
int i) {
jstring _key = NULL;
const char *section = NULL;
jobject _section = NULL;
jobject section_keyset = NULL;
jobject section_keylist = NULL;

if (!bsg_jni_cache->initialized) {
goto exit;
}

_key = bsg_safe_call_object_method(env, keylist, bsg_jni_cache->ArrayList_get,
(jint)i);
if (_key == NULL) {
goto exit;
}
section = bsg_safe_get_string_utf_chars(env, _key);
if (section == NULL) {
goto exit;
}
_section =
bsg_safe_call_object_method(env, metadata, bsg_jni_cache->Map_get, _key);
if (_section == NULL) {
// get size of metadata map
jint map_size =
bsg_safe_call_int_method(env, section_map, bsg_jni_cache->Map_size);
if (map_size <= 0) {
goto exit;
}
jint section_size =
bsg_safe_call_int_method(env, _section, bsg_jni_cache->Map_size);
if (section_size == -1) {

// create a list of metadata keys
entryset = bsg_safe_call_object_method(env, section_map,
bsg_jni_cache->Map_entrySet);
if (entryset == NULL) {
goto exit;
}
section_keyset =
bsg_safe_call_object_method(env, _section, bsg_jni_cache->Map_keySet);
if (section_keyset == NULL) {
entries =
bsg_safe_call_object_method(env, entryset, bsg_jni_cache->Set_iterator);
if (entries == NULL) {
goto exit;
}

section_keylist = bsg_safe_new_object(
env, bsg_jni_cache->ArrayList,
bsg_jni_cache->ArrayList_constructor_collection, section_keyset);
if (section_keylist == NULL) {
goto exit;
}
for (int j = 0; j < section_size; j++) {
populate_metadata_obj(env, dst, _section, section_keylist, j);
// we iterate against the size of the Map, avoiding calling Iterator.hasNext()
// on each loop (avoiding the small JNI overhead). Any concurrent modification
// will be caught as an exception and handled by bsg_safe_call_object_method
for (int i = 0; i < map_size; i++) {
(*env)->PushLocalFrame(env, 3);
{
jobject entry = bsg_safe_call_object_method(env, entries,
bsg_jni_cache->Iterator_next);
jstring _key = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getKey);
jobject _value = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getValue);

if (_key != NULL && _value != NULL) {
const char *key = bsg_safe_get_string_utf_chars(env, _key);
if (key != NULL) {
populate_metadata_value(env, dst, section, key, _value);
bsg_safe_release_string_utf_chars(env, _key, key);
}
}
}
(*env)->PopLocalFrame(env, NULL);
}
goto exit;

exit:
bsg_safe_release_string_utf_chars(env, _key, section);
bsg_safe_delete_local_ref(env, _key);
bsg_safe_delete_local_ref(env, _section);
bsg_safe_delete_local_ref(env, section_keyset);
bsg_safe_delete_local_ref(env, section_keylist);
bsg_safe_delete_local_ref(env, entries);
bsg_safe_delete_local_ref(env, entryset);
}

// Internal API

void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst,
jobject metadata) {
jobject _metadata = NULL;
jobject keyset = NULL;
jobject keylist = NULL;
jobject entrySet = NULL;
jobject entryIterator = NULL;

if (!bsg_jni_cache->initialized) {
goto exit;
Expand All @@ -489,90 +459,64 @@ void bsg_populate_metadata(JNIEnv *env, bugsnag_metadata *dst,
}

int size = bsg_safe_call_int_method(env, metadata, bsg_jni_cache->Map_size);
if (size == -1) {
if (size <= 0) {
goto exit;
}

// create a list of metadata keys
keyset = bsg_safe_call_static_object_method(env, metadata,
bsg_jni_cache->Map_keySet);
if (keyset == NULL) {
// retrieve the Map.Entry set
entrySet =
bsg_safe_call_object_method(env, metadata, bsg_jni_cache->Map_entrySet);
if (entrySet == NULL) {
goto exit;
}
keylist = bsg_safe_new_object(env, bsg_jni_cache->ArrayList,
bsg_jni_cache->ArrayList_constructor_collection,
keyset);
if (keylist == NULL) {

// retrieve an Iterator<Map.Entry>
entryIterator =
bsg_safe_call_object_method(env, entrySet, bsg_jni_cache->Set_iterator);
if (entryIterator == NULL) {
goto exit;
}

// we iterate against the size of the Map, avoiding calling Iterator.hasNext()
// on each loop (avoiding the small JNI overhead). Any concurrent modification
// will be caught as an exception and handled by bsg_safe_call_object_method
for (int i = 0; i < size; i++) {
populate_metadata_section(env, dst, metadata, keylist, i);
(*env)->PushLocalFrame(env, 3);
{
jobject entry = bsg_safe_call_object_method(env, entryIterator,
bsg_jni_cache->Iterator_next);
jobject _key = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getKey);
jobject _value = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getValue);

const char *section_name = bsg_safe_get_string_utf_chars(env, _key);

if (section_name != NULL && _value != NULL) {
populate_metadata_obj(env, dst, section_name, _value);
bsg_safe_release_string_utf_chars(env, _key, section_name);
}
}
(*env)->PopLocalFrame(env, NULL);
}

exit:
bsg_safe_delete_local_ref(env, _metadata);
bsg_safe_delete_local_ref(env, keyset);
bsg_safe_delete_local_ref(env, keylist);
bsg_safe_delete_local_ref(env, entrySet);
bsg_safe_delete_local_ref(env, entryIterator);
}

void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb,
jobject metadata) {
jobject entryset = NULL;
jobject entries = NULL;

if (metadata == NULL) {
goto exit;
return;
}
if (!bsg_jni_cache->initialized) {
goto exit;
}

// get size of metadata map
jint map_size =
bsg_safe_call_int_method(env, metadata, bsg_jni_cache->Map_size);
if (map_size <= 0) {
goto exit;
}

// create a list of metadata keys
entryset =
bsg_safe_call_object_method(env, metadata, bsg_jni_cache->Map_entrySet);
if (entryset == NULL) {
goto exit;
}
entries =
bsg_safe_call_object_method(env, entryset, bsg_jni_cache->Set_iterator);
if (entries == NULL) {
goto exit;
}

while (bsg_safe_call_boolean_method(env, entries,
bsg_jni_cache->Iterator_hasNext)) {
(*env)->PushLocalFrame(env, 3);
{
jobject entry = bsg_safe_call_object_method(env, entries,
bsg_jni_cache->Iterator_next);
jstring _key = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getKey);
jobject _value = bsg_safe_call_object_method(
env, entry, bsg_jni_cache->MapEntry_getValue);

if (_key != NULL && _value != NULL) {
const char *key = bsg_safe_get_string_utf_chars(env, _key);
if (key != NULL) {
populate_metadata_value(env, &crumb->metadata, "metaData", key,
_value);
bsg_safe_release_string_utf_chars(env, _key, key);
}
}
}
(*env)->PopLocalFrame(env, NULL);
return;
}

exit:
bsg_safe_delete_local_ref(env, entries);
bsg_safe_delete_local_ref(env, entryset);
populate_metadata_obj(env, &crumb->metadata, "metaData", metadata);
}

void bsg_populate_event(JNIEnv *env, bugsnag_event *event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
extern "C" {
int __attribute__((optnone)) __attribute__((noinline)) crash_stack_overflow(int counter, char *input) {
char stack[7];
char *output = stack;

strcpy(stack, input);
while (*input) {
*output = *input;
input++;
output++;
}

return 4 / counter;
}
Expand Down
Loading