Skip to content

Commit cd366f5

Browse files
authored
Merge pull request #176 from backtrace-labs/feature/16kb_alignment
16 KB page-size support, compileSdk 35, AGP 8.5 #176 GSON fix - implement ThrowableTypeAdapterFactory #178
2 parents d07ecbf + 8e67c39 commit cd366f5

26 files changed

+1047
-17
lines changed

.github/workflows/test.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,20 @@ jobs:
3333
echo BACKTRACE_CORONER_URL=\"${{ secrets.BACKTRACE_CORONER_URL }}\" >> ./local.properties
3434
echo BACKTRACE_CORONER_TOKEN=\"${{ secrets.BACKTRACE_CORONER_TOKEN }}\" >> ./local.properties
3535
36+
- name: Accept Android SDK licences
37+
run: yes | "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --licenses
38+
3639
- name: Build and check
3740
run: ./gradlew assembleDebug assembleDebugAndroidTest build check
3841

42+
- name: Alignment script executable
43+
run: chmod +x scripts/check_elf_alignment.sh
44+
45+
- name: Verify 16-KB alignment (arm64-v8a & x86_64)
46+
run: |
47+
scripts/check_elf_alignment.sh \
48+
example-app/build/outputs/apk/debug/example-app-debug.apk
49+
3950
- name: Upload symbols.zip
4051
uses: actions/upload-artifact@v4
4152
with:

backtrace-library/build.gradle

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
plugins {
2+
id 'com.android.library'
23
id 'com.gladed.androidgitversion' version '0.4.14'
34
id "com.vanniktech.maven.publish" version "0.29.0" apply true
45
}
5-
apply plugin: 'com.android.library'
66

77
import com.vanniktech.maven.publish.SonatypeHost
88

@@ -16,10 +16,10 @@ android {
1616
namespace "backtraceio.library"
1717
defaultConfig {
1818
minSdkVersion 21
19-
compileSdk 34
20-
targetSdkVersion 34
21-
versionName androidGitVersion.name()
22-
versionCode androidGitVersion.code()
19+
compileSdk 35
20+
// TODO: BT-5924 Android 35 update -> noinspection OldTargetApi,EditedTargetSdkVersion
21+
targetSdkVersion 35
22+
ndkVersion "27.0.11718014-beta1"
2323
buildConfigField("String", "VERSION_NAME", "\"${versionName}\"")
2424

2525
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
@@ -29,6 +29,7 @@ android {
2929
cppFlags ""
3030
arguments "-DCMAKE_BUILD_TYPE=Release"
3131
arguments "-DCRASHPAD_HTTPS_TRANSPORT=OPENSSL"
32+
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
3233
}
3334
}
3435
ndk {
@@ -54,7 +55,7 @@ android {
5455
externalNativeBuild {
5556
cmake {
5657
path file('src/main/cpp/CMakeLists.txt')
57-
version "3.22.1"
58+
version "3.31.6"
5859
}
5960
}
6061
sourceSets {

backtrace-library/src/androidTest/java/backtraceio/library/BacktraceClientSendTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public void sendExceptionWithManyCause() {
112112
final String mainExceptionExpectedMessage = expectedExceptionMessages.pop();
113113
assertEquals(mainExceptionExpectedMessage, mainExceptionMessage);
114114
assertTrue(exceptionProperties.getJSONArray("stack-trace").length() > 0);
115-
assertEquals(mainExceptionExpectedMessage, exceptionProperties.get("detail-message"));
115+
assertEquals(mainExceptionExpectedMessage, exceptionProperties.get("message"));
116116

117117
} catch (JSONException e) {
118118
e.printStackTrace();

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ add_library(# Sets the name of the library.
5454

5555
target_compile_features(backtrace-native PRIVATE cxx_std_17)
5656

57+
# Android 15 & later: make every LOAD segment 16 KB-aligned so the .so files
58+
# can work on kernels that use 16 KB pages. Has zero impact on 4 KB devices.
59+
if (ANDROID_ABI STREQUAL "arm64-v8a" OR ANDROID_ABI STREQUAL "x86_64")
60+
target_link_options(backtrace-native PRIVATE
61+
-Wl,-z,max-page-size=16384
62+
-Wl,-z,common-page-size=16384)
63+
endif()
64+
5765
if (BACKEND STREQUAL "CRASHPAD_BACKEND")
5866
target_compile_definitions(backtrace-native PRIVATE -DCRASHPAD_BACKEND)
5967

@@ -107,6 +115,10 @@ list(APPEND LIBS backtrace-native)
107115
list(APPEND LIBS ${log-lib})
108116

109117
if (BACKEND STREQUAL "CRASHPAD_BACKEND")
118+
# Pass 16 KB linker flags to Crashpad’s handler so libcrashpad_handler.so loads on 16 KB kernels.
119+
set(CRASHPAD_GN_ARGS_FILE
120+
"${CMAKE_CURRENT_SOURCE_DIR}/build_args/args_android.gn")
121+
110122
set(CRASHPAD_HANDLER_GENERATE_STATIC_LIB true)
111123
add_subdirectory(crashpad)
112124
target_link_libraries(backtrace-native client)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ldflags = [
2+
"-Wl,-z,max-page-size=16384",
3+
"-Wl,-z,common-page-size=16384",
4+
]

backtrace-library/src/main/java/backtraceio/library/common/serialization/BacktraceGsonBuilder.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ public class BacktraceGsonBuilder implements CustomGsonBuilder {
88

99
@Override
1010
public Gson buildGson() {
11-
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
11+
return new GsonBuilder()
12+
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
13+
.registerTypeAdapter(StackTraceElement.class, new StackTraceElementTypeAdapter())
14+
.registerTypeAdapterFactory(new ThrowableTypeAdapterFactory())
15+
.create();
1216
}
1317
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package backtraceio.library.common.serialization;
2+
3+
import com.google.gson.TypeAdapter;
4+
import com.google.gson.stream.JsonReader;
5+
import com.google.gson.stream.JsonToken;
6+
import com.google.gson.stream.JsonWriter;
7+
8+
import java.io.IOException;
9+
10+
public class StackTraceElementTypeAdapter extends TypeAdapter<StackTraceElement> {
11+
12+
@Override
13+
public void write(JsonWriter out, StackTraceElement value) throws IOException {
14+
if (value == null) {
15+
out.nullValue();
16+
return;
17+
}
18+
out.beginObject();
19+
out.name("declaring-class").value(value.getClassName());
20+
out.name("method-name").value(value.getMethodName());
21+
out.name("file-name").value(value.getFileName());
22+
out.name("line-number").value(value.getLineNumber());
23+
// Do NOT write classLoaderName (for compatibility)
24+
out.endObject();
25+
}
26+
27+
@Override
28+
public StackTraceElement read(JsonReader in) throws IOException {
29+
if (in.peek() == JsonToken.NULL) {
30+
in.nextNull();
31+
return null;
32+
}
33+
String className = null;
34+
String methodName = null;
35+
String fileName = null;
36+
int lineNumber = -1;
37+
38+
in.beginObject();
39+
while (in.hasNext()) {
40+
String name = in.nextName();
41+
switch (name) {
42+
case "declaring-class":
43+
className = in.nextString();
44+
break;
45+
case "method-name":
46+
methodName = in.nextString();
47+
break;
48+
case "file-name":
49+
if (in.peek() == JsonToken.NULL) {
50+
in.nextNull();
51+
fileName = null;
52+
} else {
53+
fileName = in.nextString();
54+
}
55+
break;
56+
case "line-number":
57+
lineNumber = in.nextInt();
58+
break;
59+
// Ignore any unknown fields (including classLoaderName)
60+
default:
61+
in.skipValue();
62+
}
63+
}
64+
in.endObject();
65+
return new StackTraceElement(className, methodName, fileName, lineNumber);
66+
}
67+
}

0 commit comments

Comments
 (0)