Code Monkey home page Code Monkey logo

xunwind's Introduction

xUnwind

xUnwind is a collection of Android native stack unwinding solutions.

README 中文版

Features

  • Support unwinding by:
    • CFI (Call Frame Info): Provided by Android system library.
    • EH (Exception handling GCC extension): Provided by compiler.
    • FP (Frame Pointer): ARM64 only.
  • Support unwinding from:
    • Current execution position.
    • A specified context (which may be obtained from a signal handler).
  • Support unwinding for process:
    • Local process.
    • Remote process: CFI only.
  • Support unwinding for thread(s):
    • Current thread.
    • Specified thread: CFI only.
    • All threads: CFI only.
  • Provide java method to get native backtrace directly in java code.
  • Support Android 4.1 - 13 (API level 16 - 33).
  • Support armeabi-v7a, arm64-v8a, x86 and x86_64.
  • MIT licensed.

Usage

1. Add dependency in build.gradle

xUnwind is published on Maven Central, and uses Prefab package format for native dependencies, which is supported by Android Gradle Plugin 4.0+.

android {
    buildFeatures {
        prefab true
    }
}

dependencies {
    implementation 'io.github.hexhacking:xunwind:2.0.0'
}

NOTE:

  1. Starting from version 2.0.0 of xUnwind, group ID changed from io.hexhacking to io.github.hexhacking.
version range group ID artifact ID Repository URL
[1.0.1, 1.1.1] io.hexhacking xunwind repo
[2.0.0, ) io.github.hexhacking xunwind repo
  1. xUnwind uses the prefab package schema v2, which is configured by default since Android Gradle Plugin 7.1.0. If you are using Android Gradle Plugin earlier than 7.1.0, please add the following configuration to gradle.properties:
android.prefabVersion=2.0.0

2. Add dependency in CMakeLists.txt or Android.mk

If you only use the java interface of xUnwind, please skip this step.

CMakeLists.txt

find_package(xunwind REQUIRED CONFIG)

add_library(mylib SHARED mylib.c)
target_link_libraries(mylib xunwind::xunwind)

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE           := mylib
LOCAL_SRC_FILES        := mylib.c
LOCAL_SHARED_LIBRARIES += xunwind
include $(BUILD_SHARED_LIBRARY)

$(call import-module,prefab/xunwind)

3. Specify one or more ABI(s) you need

android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
}

4. Add packaging options

If you are using xUnwind in an SDK project, you may need to avoid packaging libxunwind.so into your AAR, so as not to encounter duplicate libxunwind.so file when packaging the app project.

android {
    packagingOptions {
        exclude '**/libxunwind.so'
    }
}

On the other hand, if you are using xUnwind in an APP project, you may need to add some options to deal with conflicts caused by duplicate libxunwind.so file.

android {
    packagingOptions {
        pickFirst '**/libxunwind.so'
    }
}

There is a sample app in the xunwind-sample folder you can refer to.

Native API

#include "xunwind.h"

1. CFI unwinding

#define XUNWIND_CURRENT_PROCESS (-1)
#define XUNWIND_CURRENT_THREAD (-1)
#define XUNWIND_ALL_THREADS (-2)

void xunwind_cfi_log(pid_t pid, pid_t tid, void *context, const char *logtag, android_LogPriority priority, const char *prefix);
void xunwind_cfi_dump(pid_t pid, pid_t tid, void *context, int fd, const char *prefix);
char *xunwind_cfi_get(pid_t pid, pid_t tid, void *context, const char *prefix);

These three functions correspond to three ways of obtaining backtrace. They are:

  • log to Android logcat.
  • dump to a place associated with FD (such as file, pipe, socket, etc.).
  • get and return a string (which is allocated on the heap with malloc(), you need to free() it yourself).

The pid parameter is used to specify the backtrace of which process needs to be obtained, which can be the current process (XUNWIND_CURRENT_PROCESS / getpid()) or another process.

The tid parameter is used to specify the backtrace of which thread or threads need to be obtained, which can be the current thread (XUNWIND_CURRENT_THREAD / gettid()), a specified thread, or all threads (XUNWIND_ALL_THREADS).

The optional context parameter is used to pass a register context information. For example, in signal handler, you may need to start unwinding from a specific context.

The optional prefix parameter is used to specify a prefix string for each line of backtrace.

2. FP and EH unwinding

size_t xunwind_fp_unwind(uintptr_t* frames, size_t frames_cap, void *context);
size_t xunwind_eh_unwind(uintptr_t* frames, size_t frames_cap, void *context);

void xunwind_frames_log(uintptr_t* frames, size_t frames_sz, const char *logtag, android_LogPriority priority, const char *prefix);
void xunwind_frames_dump(uintptr_t* frames, size_t frames_sz, int fd, const char *prefix);
char *xunwind_frames_get(uintptr_t* frames, size_t frames_sz, const char *prefix);

Currently, FP unwinding is ARM64 only.

xunwind_fp_unwind and xunwind_eh_unwind saves the absolute-PCs of the unwinding result in the array pointed to by frames (frames_cap is the size of the array), and returns the number of absolute-PCs actually obtained.

The meaning of the optional context parameter is the same as that of CFI unwinding.

The remaining three functions are used to convert the absolute-PCs in the frames array into backtrace (the size of the array is specified by frames_sz). Same as CFI unwinding, respectively output to Android logcat, FD, and return as a string.

Java API

import io.github.hexhacking.xunwind.XUnwind;

1. Initialize

public static void init();

The only thing init() does is System.loadLibrary("xunwind"). If you only use xUnwind in native code, no initialization is required.

2. CFI unwinding

public static void logLocalCurrentThread(String logtag, int priority, String prefix);
public static void logLocalThread(int tid, String logtag, int priority, String prefix);
public static void logLocalAllThread(String logtag, int priority, String prefix);
public static void logRemoteThread(int pid, int tid, String logtag, int priority, String prefix);
public static void logRemoteAllThread(int pid, String logtag, int priority, String prefix);

public static void dumpLocalCurrentThread(int fd, String prefix);
public static void dumpLocalThread(int tid, int fd, String prefix);
public static void dumpLocalAllThread(int fd, String prefix);
public static void dumpRemoteThread(int pid, int tid, int fd, String prefix);
public static void dumpRemoteAllThread(int pid, int fd, String prefix);

public static String getLocalCurrentThread(String prefix);
public static String getLocalThread(int tid, String prefix);
public static String getLocalAllThread(String prefix);
public static String getRemoteThread(int pid, int tid, String prefix);
public static String getRemoteAllThread(int pid, String prefix);

All native CFI unwinding capabilities have corresponding java functions. They call the native CFI unwinding functions through JNI.

FP and EH unwinding do not have corresponding java functions. Because compared to CFI unwinding, their main advantage is faster execution speed (but the backtrace is not as complete as CFI unwinding), so they are always only used in native code. If you are a java programmer, just use the CFI unwinding functions here.

Support

Contributing

License

xUnwind is MIT licensed, as found in the LICENSE file.

History

xCrash 2.x contains a set of methods xcc_unwind_* to get backtrace, which is used to try to get backtrace directly from the signal handler when the dumper child process fails. Now we have improved and expanded this set of functions so that they can be used in more scenarios.

xunwind's People

Contributors

caikelun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xunwind's Issues

问题:arm架构下用EH获取堆栈崩溃

崩溃信息如下:

04-25 15:14:46.141 17359-17359/io.hexhacking.xunwind.sample A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x104 in tid 17359 (.xunwind.sample)
04-25 15:14:46.249 331-331/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
04-25 15:14:46.250 331-331/? A/DEBUG: Build fingerprint: 'Xiaomi/virgo/virgo:6.0.1/MMB29M/V8.2.1.0.MXECNDL:user/release-keys'
04-25 15:14:46.251 331-331/? A/DEBUG: Revision: '0'
04-25 15:14:46.253 331-331/? A/DEBUG: ABI: 'arm'
04-25 15:14:46.253 331-331/? A/DEBUG: pid: 17359, tid: 17359, name: .xunwind.sample  >>> io.hexhacking.xunwind.sample <<<
04-25 15:14:46.255 331-331/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x104
04-25 15:14:46.287 331-331/? A/DEBUG:     r0 00000104  r1 00000108  r2 00000004  r3 00000000
04-25 15:14:46.288 331-331/? A/DEBUG:     r4 b6ee0224  r5 00000000  r6 00000004  r7 b6ee0248
04-25 15:14:46.288 331-331/? A/DEBUG:     r8 000040d0  r9 b6c9dec0  sl b6ee0748  fp 00000001
04-25 15:14:46.289 331-331/? A/DEBUG:     ip b6c995dc  sp b6ee0210  lr b37b8823  pc b37b8538  cpsr 000d0030
04-25 15:14:46.298 331-331/? A/DEBUG: backtrace:
04-25 15:14:46.299 331-331/? A/DEBUG:     #00 pc 00002538  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.299 331-331/? A/DEBUG:     #01 pc 000021bd  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.300 331-331/? A/DEBUG:     #02 pc 00002ceb  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.300 331-331/? A/DEBUG:     #03 pc 00002969  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.300 331-331/? A/DEBUG:     #04 pc 00002659  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.301 331-331/? A/DEBUG:     #05 pc 0000271d  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so
04-25 15:14:46.301 331-331/? A/DEBUG:     #06 pc 0000201d  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so (xunwind_eh_unwind+44)
04-25 15:14:46.302 331-331/? A/DEBUG:     #07 pc 00001017  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libsample.so
04-25 15:14:46.302 331-331/? A/DEBUG:     #08 pc 0001756c  /system/lib/libc.so
04-25 15:14:46.302 331-331/? A/DEBUG:     #09 pc 00042044  /system/lib/libc.so (tgkill+8)
04-25 15:14:46.303 331-331/? A/DEBUG:     #10 pc 00000e67  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libsample.so
04-25 15:14:46.303 331-331/? A/DEBUG:     #11 pc fffffffd  <unknown>

符号化:

********** Crash dump: **********
Build fingerprint: 'Xiaomi/virgo/virgo:6.0.1/MMB29M/V8.2.1.0.MXECNDL:user/release-keys'
pid: 17359, tid: 17359, name: .xunwind.sample  >>> io.hexhacking.xunwind.sample <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x104
Stack frame #00 pc 00002538  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #01 pc 000021bd  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #02 pc 00002ceb  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #03 pc 00002969  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #04 pc 00002659  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #05 pc 0000271d  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so: Routine ??
??:0
Stack frame #06 pc 0000201d  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libxunwind.so (xunwind_eh_unwind+44): Routine ??
??:0
Stack frame #07 pc 00001017  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libsample.so: Routine sample_sigabrt_handler at /Users/lwy/code_workspace/android/xUnwind-master/xunwind_sample/src/main/cpp/sample.c:83
Stack frame #08 pc 0001756c  /system/lib/libc.so
Stack frame #09 pc 00042044  /system/lib/libc.so (tgkill+8)
Stack frame #10 pc 00000e67  /data/app/io.hexhacking.xunwind.sample-1/lib/arm/libsample.so: Routine sample_test at /Users/lwy/code_workspace/android/xUnwind-master/xunwind_sample/src/main/cpp/sample.c:208

help! sample can't run

I downloaded the examples on github and can’t run.
The error message is as follows:

Task :prepareKotlinBuildScriptModel UP-TO-DATE
prefabUsage: prefab [OPTIONS] [PACKAGE_PATH]...
prefabError: Invalid value for "PACKAGE_PATH": Directory "/Users/lwy/code_workspace/java/xUnwind-master/xunwind/build/intermediates/prefab_package/debug/prefab" is not readable.
executing external native build for cmake /Users/lwy/code_workspace/java/xUnwind-master/xunwind_sample/src/main/cpp/CMakeLists.txt

BUILD SUCCESSFUL in 2s

Crash on some Android phones

xUnwind Version

2.0.0

Android OS Version

Unknown yet

Android ABIs

armeabi-v7a

Device Manufacturers and Models

Unknown yet

Describe the Bug

Sometimes calling xunwind_cfi_get(XUNWIND_CURRENT_PROCESS, XUNWIND_CURRENT_THREAD, ucontext, ""); resulting in a crash on some phones.

My users cant even gather logs so it's most likely a dead end. But maybe can give me some info... Im waiting for that. I hope so.

unwind Crash

xUnwind Version

2.0.0

Android OS Version

13

Android ABIs

arm64-v8a

Device Manufacturers and Models

Xiaomi 2211133c

Describe the Bug

#00 pc 000000000004fe3c /apex/com.android.runtime/lib64/bionic/libc.so (je_free+1200)
#1 pc 00000000000625b8 /system/lib64/libunwindstack.so (unwindstack::MemoryRange::~MemoryRange()+72)
#2 pc 00000000000627f0 /system/lib64/libunwindstack.so (std::__1::__tree<std::__1::__value_type<unsigned long, std::__1::unique_ptr<unwindstack::MemoryRange, std::__1::default_deleteunwindstack::MemoryRange > >, std::__1::__map_value_compare<unsigned long, std::__1::__value_type<unsigned long, std::__1::unique_ptr<unwindstack::MemoryRange, std::__1::default_deleteunwindstack::MemoryRange > >, std::__1::less, true>, std::__1::allocator<std::__1::__value_type<unsigned long, std::__1::unique_ptr<unwindstack::MemoryRange, std::__1::default_deleteunwindstack::MemoryRange > > > >::destroy(std::__1::__tree_node<std::__1::__value_type<unsigned long, std::__1::unique_ptr<unwindstack::MemoryRange, std::__1::default_deleteunwindstack::MemoryRange > >, void*>*)+72)
#3 pc 0000000000062628 /system/lib64/libunwindstack.so (unwindstack::MemoryRanges::~MemoryRanges()+44)
#4 pc 0000000000057050 /system/lib64/libunwindstack.so (unwindstack::Elf::~Elf()+112)
#5 pc 000000000005c5d0 /system/lib64/libunwindstack.so (unwindstack::MapInfo::~MapInfo()+148)
#06 pc 000000000000f228 /system/lib64/libbacktrace.so (unwindstack::LocalMaps::~LocalMaps()+116)
#7 pc 000000000000f0e0 /system/lib64/libbacktrace.so (UnwindStackMap::~UnwindStackMap()+152)
#8 pc 000000000000bbf8 /system/lib64/libbacktrace.so (Backtrace::~Backtrace()+64)
#9 pc 00000000000081ac /data/app/~~2cr1esTtlIxLU8wDwMhDow==/com.lalamove.huolala.driver-67y7H4KbSHRBe2QLjY51-w==/lib/arm64/libxunwind.so
#10 pc 0000000000007e8c /data/app/~~2cr1esTtlIxLU8wDwMhDow==/com.lalamove.huolala.driver-67y7H4KbSHRBe2QLjY51-w==/lib/arm64/libxunwind.so

BuildId printing is required

Hello.

I'm found that the library does not print BuildId like android's crash dumper.

xUnwind example:

: #00 pc 001b5548  /data/app/~~e_GE1lEQefY82roFs1FWDA==/com.example.Tests-a19SzXnXizKY4uhToyS7lA==/lib/x86/libmain.so

android crush dumper example (contains BuildId at end of a line):

12-20 00:03:53.008 11002 11002 F DEBUG   :       #00 pc 001c4af7  /data/app/~~e_GE1lEQefY82roFs1FWDA==/com.example.Tests-a19SzXnXizKY4uhToyS7lA==/lib/x86/libmain.so (BuildId: 1235265346346457347346765467547645865548)

readelf dump of symbols:

D:\android-ndk-r21b\toolchains\llvm\prebuilt\windows-x86_64\bin\i686-linux-android-readelf.exe -n D:\temp\symbols\x86\libmain.so

Displaying notes found at file offset 0x00000134 with length 0x00000098:
  Owner                 Data size       Description
  Android              0x00000084       NT_VERSION (version)

Displaying notes found at file offset 0x000001cc with length 0x00000024:
  Owner                 Data size       Description
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 1235265346346457347346765467547645865548

Displaying notes found at file offset 0x08b4a990 with length 0x0000001c:
  Owner                 Data size       Description
  GNU                  0x00000009       NT_GNU_GOLD_VERSION (gold version)
    Version: gold 1.12

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.