Skip to content

Commit

Permalink
Merge pull request #2035 from bugsnag/PLAT-12075/ndk-metadata-iterator
Browse files Browse the repository at this point in the history
NDK metadata iterator
  • Loading branch information
lemnik authored Jun 4, 2024
2 parents 5bc8d99 + af3f5bc commit 2cce055
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 213 deletions.
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

0 comments on commit 2cce055

Please sign in to comment.