Skip to content

Commit dcf0eb9

Browse files
authored
Feature/ndk16bsupport and feature/IncreaseClientSideUnwidingRobustness (#30)
Add support for NDK 16b and bug fixes for client side unwinding so it works on all supported API/NDK levels when the Crashpad backend is used
1 parent ee8b7d3 commit dcf0eb9

26 files changed

+4986
-696
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "backtrace-library/src/main/cpp/libbun"]
55
path = backtrace-library/src/main/cpp/libbun
66
url = git@github.com:backtrace-labs/libbun.git
7+
[submodule "backtrace-library/src/main/cpp/breakpad-builds"]
8+
path = backtrace-library/src/main/cpp/breakpad-builds
9+
url = git@github.com:backtrace-labs/breakpad-builds.git

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Backtrace Android Release Notes
22

3+
## Version 3.5.0 - 14.09.2021
4+
- Added support for native crash reporting in NDK 16b
5+
- Bug fixes and expanded supported NDK versions for client side unwinding
6+
37
## Version 3.4.0 - 07.09.2021
48
- Added support for NDK 22
59

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ catch (e: Exception) {
7272

7373
# Supported SDKs <a name="supported-sdks"></a>
7474
* Minimum SDK version 21 (Android 5.0)
75-
* Target SDK version 28 (Android 9.0)
76-
* Minimum NDK version 17c
75+
* Target SDK version 30 (Android 11.0)
76+
* Minimum NDK version 16b
7777
* Maximum NDK version 22
7878

7979
# Supported platforms
@@ -516,6 +516,10 @@ In addition, you may need to add the [extractNativeLibs](https://developer.andro
516516
```
517517
More details about [extractNativeLibs](https://developer.android.com/guide/topics/manifest/application-element#extractNativeLibs) are available from the Android documentation
518518

519+
**NOTE:** If your native app is built with NDK 16b, the Breakpad native crash client will be used instead of our recommended Crashpad crash client. To avoid this please use NDK 17c+ to build your native app.
520+
521+
**NOTE:** Breakpad crash reports are submitted on the next app startup, instead of at crash time like Crashpad crash reports
522+
519523
## Uploading symbols to Backtrace
520524
For an NDK application, debugging symbols are not available to Backtrace by default. You will need to upload the application symbols for your native code to Backtrace. You can do this by uploading the native libraries themselves, which are usually found in the .apk bundle. [Click here to learn more about symbolification](https://support.backtrace.io/hc/en-us/articles/360040517071-Symbolication-Overview)
521525

@@ -527,12 +531,12 @@ To enable client side unwinding, you can call the `setupNativeIntegration` metho
527531
database.setupNativeIntegration(backtraceClient, credentials, true);
528532
```
529533

530-
**NOTE:** Client side unwinding is only available in API level 23+ (Android 6.0)+
531-
532534
**NOTE:** When viewing a crash in the Backtrace Debugger, it may still show warning messages that symbols are missing from certain frames after client-side unwinding is performed. This warning is expected if these symbols are not available on the Backtrace server, and should have no impact to the end-user's ability to read the call stack.
533535

534536
**NOTE:** Client side unwinding is only available for fatal crashes. Non-fatal Crashpad dumps you generate via `DumpWithoutCrash` for instance will not use client side unwinding.
535537

538+
**NOTE:** Client side unwinding is only available in NDK level 17+ (i.e: Only with the Crashpad crash reporting backend)
539+
536540
### Unwinding Modes and Options
537541

538542
You can optionally specify the unwinding mode (`REMOTE_DUMPWITHOUTCRASH` is the default)

backtrace-library/build.gradle

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ apply plugin: 'com.android.library'
22
apply from: 'publish.gradle'
33

44
android {
5-
compileSdkVersion 28
5+
compileSdkVersion 30
66

77
defaultConfig {
88
minSdkVersion 21
9-
targetSdkVersion 28
10-
versionCode 340
11-
versionName "3.4.0"
9+
targetSdkVersion 30
10+
versionCode 350
11+
versionName "3.5.0"
1212

1313
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1414

@@ -17,6 +17,9 @@ android {
1717
cppFlags ""
1818
}
1919
}
20+
ndk {
21+
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
22+
}
2023
}
2124

2225
buildTypes {

backtrace-library/src/main/cpp/CMakeLists.txt

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,87 @@
55

66
cmake_minimum_required(VERSION 3.4.1)
77

8-
# Creates and names a library, sets it as either STATIC
9-
# or SHARED, and provides the relative paths to its source code.
10-
# You can define multiple libraries, and CMake builds them for you.
11-
# Gradle automatically packages shared libraries with your APK.
12-
13-
add_library( # Sets the name of the library.
14-
backtrace-native
15-
16-
# Sets the library as a shared library.
17-
SHARED
18-
19-
# Provides a relative path to your source file(s).
20-
backtrace-native.cpp)
21-
22-
# Crashpad Libraries
23-
add_library(crashpad_client STATIC IMPORTED)
24-
set_property(TARGET crashpad_client PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/client/libcrashpad_client.a)
25-
26-
add_library(crashpad_util STATIC IMPORTED)
27-
set_property(TARGET crashpad_util PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/util/libcrashpad_util.a)
28-
29-
add_library(base STATIC IMPORTED)
30-
set_property(TARGET base PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/third_party/mini_chromium/mini_chromium/base/libbase.a)
31-
32-
# Crashpad Headers
33-
include_directories(${PROJECT_SOURCE_DIR}/crashpad-builds/headers/ ${PROJECT_SOURCE_DIR}/crashpad-builds/headers/third_party/mini_chromium/mini_chromium/)
34-
35-
# Bun Libraries
36-
set(LIBUNWINDSTACK_ENABLED TRUE)
37-
add_subdirectory(libbun)
8+
# Determine native crash backend
9+
# ANDROID_NDK_MAJOR not defined until ndk 17+
10+
# https://github.com/android/ndk/issues/596
11+
if (ANDROID_ABI STREQUAL "x86")
12+
message("Native crash reporting not supported for x86 emulator")
13+
elseif(ANDROID_ABI STREQUAL "x86_64" AND (NOT ANDROID_NDK_MAJOR OR ANDROID_NDK_MAJOR LESS 17))
14+
message("Breakpad not supported for x86_64 emulator")
15+
elseif (NOT ANDROID_NDK_MAJOR)
16+
set(BACKEND "BREAKPAD_BACKEND")
17+
elseif(ANDROID_NDK_MAJOR LESS 17)
18+
set(BACKEND "BREAKPAD_BACKEND")
19+
else()
20+
set(BACKEND "CRASHPAD_BACKEND")
21+
set(CLIENT_SIDE_UNWINDING TRUE)
22+
endif()
23+
24+
# Sources
25+
list(APPEND SOURCES backtrace-native.cpp)
26+
list(APPEND SOURCES backends/backend.cpp)
27+
list(APPEND SOURCES client-side-unwinding.cpp)
28+
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
29+
list(APPEND SOURCES backends/crashpad-backend.cpp)
30+
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
31+
list(APPEND SOURCES backends/breakpad-backend.cpp)
32+
else()
33+
message("No native debugging backend selected")
34+
endif()
35+
36+
add_library(# Sets the name of the library.
37+
backtrace-native
38+
39+
# Sets the library as a shared library.
40+
SHARED
41+
42+
# Provides a relative path to your source file(s).
43+
${SOURCES})
44+
45+
target_compile_features(backtrace-native PRIVATE cxx_std_17)
46+
47+
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
48+
target_compile_definitions(backtrace-native PRIVATE -DCRASHPAD_BACKEND)
49+
50+
# Crashpad Libraries
51+
add_library(crashpad_client STATIC IMPORTED)
52+
set_property(TARGET crashpad_client PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/client/libcrashpad_client.a)
53+
54+
add_library(crashpad_util STATIC IMPORTED)
55+
set_property(TARGET crashpad_util PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/util/libcrashpad_util.a)
56+
57+
add_library(base STATIC IMPORTED)
58+
set_property(TARGET base PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/third_party/mini_chromium/mini_chromium/base/libbase.a)
59+
60+
# Crashpad Headers
61+
include_directories(${PROJECT_SOURCE_DIR}/crashpad-builds/headers/ ${PROJECT_SOURCE_DIR}/crashpad-builds/headers/third_party/mini_chromium/mini_chromium/)
62+
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
63+
target_compile_definitions(backtrace-native PRIVATE -DBREAKPAD_BACKEND)
64+
65+
# Breakpad Libraries
66+
add_library(breakpad_client STATIC IMPORTED)
67+
set_property(TARGET breakpad_client PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI}/libbreakpad_client.a)
68+
69+
# Curl Libraries
70+
add_library(curl SHARED IMPORTED)
71+
set_property(TARGET curl PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/curl-builds/${ANDROID_ABI}/libcurl.so)
72+
73+
# Breakpad Headers
74+
include_directories(${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI} ${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI}/src ${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI}/src/common/android/include)
75+
else()
76+
message("No native debugging backend selected")
77+
endif()
78+
79+
# Includes
80+
include_directories(${PROJECT_SOURCE_DIR}/include)
81+
82+
if (CLIENT_SIDE_UNWINDING)
83+
target_compile_definitions(backtrace-native PRIVATE -DCLIENT_SIDE_UNWINDING)
84+
85+
# Bun Libraries
86+
set(LIBUNWINDSTACK_ENABLED TRUE)
87+
add_subdirectory(libbun)
88+
endif()
3889

3990
# Searches for a specified prebuilt library and stores the path as a
4091
# variable. Because CMake includes system libraries in the search path by
@@ -50,19 +101,28 @@ find_library( # Sets the name of the path variable.
50101
log
51102
)
52103

53-
54-
55104
# Specifies libraries CMake should link to your target library. You
56105
# can link multiple libraries, such as libraries you define in this
57106
# build script, prebuilt third-party libraries, or system libraries.
58107

59-
target_link_libraries( # Specifies the target library.
60-
backtrace-native
61-
# Links the target library to the log library
62-
# included in the NDK.
63-
${log-lib}
64-
crashpad_client
65-
crashpad_util
66-
base
67-
bun
68-
)
108+
list(APPEND LIBS backtrace-native)
109+
list(APPEND LIBS ${log-lib})
110+
111+
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
112+
list(APPEND LIBS crashpad_client)
113+
list(APPEND LIBS crashpad_util)
114+
list(APPEND LIBS base)
115+
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
116+
list(APPEND LIBS breakpad_client)
117+
list(APPEND LIBS curl)
118+
else()
119+
message("No native debugging backend selected")
120+
endif()
121+
122+
if (CLIENT_SIDE_UNWINDING)
123+
list(APPEND LIBS bun)
124+
endif()
125+
126+
target_link_libraries(${LIBS})
127+
128+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "backend.h"
2+
#include "client-side-unwinding.h"
3+
#include <android/log.h>
4+
#include <atomic>
5+
#include <mutex>
6+
7+
#ifdef CRASHPAD_BACKEND
8+
#include "crashpad-backend.h"
9+
#elif BREAKPAD_BACKEND
10+
#include "breakpad-backend.h"
11+
#endif
12+
13+
extern std::atomic_bool initialized;
14+
15+
extern "C" {
16+
bool Initialize(jstring url,
17+
jstring database_path,
18+
jstring handler_path,
19+
jobjectArray attributeKeys,
20+
jobjectArray attributeValues,
21+
jobjectArray attachmentPaths,
22+
jboolean enableClientSideUnwinding,
23+
jint unwindingMode) {
24+
static std::once_flag initialize_flag;
25+
26+
std::call_once(initialize_flag, [&] {
27+
#ifdef CRASHPAD_BACKEND
28+
initialized = InitializeCrashpad(url,
29+
database_path, handler_path,
30+
attributeKeys, attributeValues,
31+
attachmentPaths, enableClientSideUnwinding,
32+
unwindingMode);
33+
#elif BREAKPAD_BACKEND
34+
initialized = InitializeBreakpad(url,
35+
database_path, handler_path,
36+
attributeKeys, attributeValues,
37+
attachmentPaths, enableClientSideUnwinding,
38+
unwindingMode);
39+
#else
40+
initialized = false;
41+
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android",
42+
"No native crash reporting backend defined");
43+
#endif
44+
});
45+
return initialized;
46+
}
47+
48+
void DumpWithoutCrash(jstring message, jboolean set_main_thread_as_faulting_thread) {
49+
#ifdef CRASHPAD_BACKEND
50+
DumpWithoutCrashCrashpad(message, set_main_thread_as_faulting_thread);
51+
#elif BREAKPAD_BACKEND
52+
DumpWithoutCrashBreakpad(message, set_main_thread_as_faulting_thread);
53+
#else
54+
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android",
55+
"DumpWithoutCrash not supported on this backend");
56+
#endif
57+
}
58+
59+
void AddAttribute(jstring key, jstring value) {
60+
#ifdef CRASHPAD_BACKEND
61+
AddAttributeCrashpad(key, value);
62+
#elif BREAKPAD_BACKEND
63+
AddAttributeBreakpad(key, value);
64+
#else
65+
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android",
66+
"AddAttribute not supported on this backend");
67+
#endif
68+
}
69+
}

0 commit comments

Comments
 (0)