{"id":13480390,"url":"https://github.com/hexhacking/xUnwind","last_synced_at":"2025-03-27T10:32:42.511Z","repository":{"id":41418813,"uuid":"313028060","full_name":"hexhacking/xUnwind","owner":"hexhacking","description":":fire: xUnwind is a collection of Android native stack unwinding solutions.","archived":false,"fork":false,"pushed_at":"2023-05-16T06:52:48.000Z","size":368,"stargazers_count":189,"open_issues_count":5,"forks_count":37,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-08-01T17:21:55.488Z","etag":null,"topics":["android","arm64","backtrace","cfi","fp","native","stacktrace","unwind"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hexhacking.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-11-15T12:39:03.000Z","updated_at":"2024-07-07T04:49:26.000Z","dependencies_parsed_at":"2024-01-13T18:13:48.965Z","dependency_job_id":"6259d956-38ad-408d-881d-f1a7ab062af5","html_url":"https://github.com/hexhacking/xUnwind","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexhacking%2FxUnwind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexhacking%2FxUnwind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexhacking%2FxUnwind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexhacking%2FxUnwind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hexhacking","download_url":"https://codeload.github.com/hexhacking/xUnwind/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222239310,"owners_count":16953914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","arm64","backtrace","cfi","fp","native","stacktrace","unwind"],"created_at":"2024-07-31T17:00:38.451Z","updated_at":"2024-10-30T14:30:26.571Z","avatar_url":"https://github.com/hexhacking.png","language":"C","readme":"# xUnwind\n\n![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)\n![](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)\n![](https://img.shields.io/badge/release-2.0.0-red.svg?style=flat)\n![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)\n![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a%20%7C%20x86%20%7C%20x86__64-blue.svg?style=flat)\n\nxUnwind is a collection of Android native stack unwinding solutions.\n\n[README 中文版](README.zh-CN.md)\n\n\n## Features\n\n* Support unwinding by:\n    * CFI (Call Frame Info): Provided by Android system library.\n    * EH (Exception handling GCC extension): Provided by compiler.\n    * FP (Frame Pointer): ARM64 only.\n* Support unwinding from:\n    * Current execution position.\n    * A specified context (which may be obtained from a signal handler).\n* Support unwinding for process:\n    * Local process.\n    * Remote process: CFI only.\n* Support unwinding for thread(s):\n    * Current thread.\n    * Specified thread: CFI only.\n    * All threads: CFI only.\n* Provide java method to get native backtrace directly in java code.\n* Support Android 4.1 - 13 (API level 16 - 33).\n* Support armeabi-v7a, arm64-v8a, x86 and x86_64.\n* MIT licensed.\n\n\n## Usage\n\n### 1. Add dependency in build.gradle\n\nxUnwind is published on [Maven Central](https://search.maven.org/), and uses [Prefab](https://google.github.io/prefab/) package format for [native dependencies](https://developer.android.com/studio/build/native-dependencies), which is supported by [Android Gradle Plugin 4.0+](https://developer.android.com/studio/releases/gradle-plugin?buildsystem=cmake#native-dependencies).\n\n```Gradle\nandroid {\n    buildFeatures {\n        prefab true\n    }\n}\n\ndependencies {\n    implementation 'io.github.hexhacking:xunwind:2.0.0'\n}\n```\n\n**NOTE**:\n\n1. Starting from version `2.0.0` of xUnwind, group ID changed from `io.hexhacking` to `io.github.hexhacking`.\n\n| version range  | group ID                 | artifact ID | Repository URL |\n|:---------------|:-------------------------|:------------| :--------------|\n| [1.0.1, 1.1.1] | io.hexhacking            | xunwind     | [repo](https://repo1.maven.org/maven2/io/hexhacking/xunwind/) |\n| [2.0.0, )      | **io.github.hexhacking** | xunwind     | [repo](https://repo1.maven.org/maven2/io/github/hexhacking/xunwind/) |\n\n2. xUnwind uses the [prefab package schema v2](https://github.com/google/prefab/releases/tag/v2.0.0), which is configured by default since [Android Gradle Plugin 7.1.0](https://developer.android.com/studio/releases/gradle-plugin?buildsystem=cmake#7-1-0). If you are using Android Gradle Plugin earlier than 7.1.0, please add the following configuration to `gradle.properties`:\n\n```\nandroid.prefabVersion=2.0.0\n```\n\n### 2. Add dependency in CMakeLists.txt or Android.mk\n\nIf you only use the java interface of xUnwind, please skip this step.\n\n\u003e CMakeLists.txt\n\n```CMake\nfind_package(xunwind REQUIRED CONFIG)\n\nadd_library(mylib SHARED mylib.c)\ntarget_link_libraries(mylib xunwind::xunwind)\n```\n\n\u003e Android.mk\n\n```\ninclude $(CLEAR_VARS)\nLOCAL_MODULE           := mylib\nLOCAL_SRC_FILES        := mylib.c\nLOCAL_SHARED_LIBRARIES += xunwind\ninclude $(BUILD_SHARED_LIBRARY)\n\n$(call import-module,prefab/xunwind)\n```\n\n### 3. Specify one or more ABI(s) you need\n\n```Gradle\nandroid {\n    defaultConfig {\n        ndk {\n            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'\n        }\n    }\n}\n```\n\n### 4. Add packaging options\n\nIf 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.\n\n```Gradle\nandroid {\n    packagingOptions {\n        exclude '**/libxunwind.so'\n    }\n}\n```\n\nOn 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.\n\n```Gradle\nandroid {\n    packagingOptions {\n        pickFirst '**/libxunwind.so'\n    }\n}\n```\n\nThere is a sample app in the [xunwind-sample](xunwind_sample) folder you can refer to.\n\n\n## Native API\n\n```C\n#include \"xunwind.h\"\n```\n\n### 1. CFI unwinding\n\n```C\n#define XUNWIND_CURRENT_PROCESS (-1)\n#define XUNWIND_CURRENT_THREAD (-1)\n#define XUNWIND_ALL_THREADS (-2)\n\nvoid xunwind_cfi_log(pid_t pid, pid_t tid, void *context, const char *logtag, android_LogPriority priority, const char *prefix);\nvoid xunwind_cfi_dump(pid_t pid, pid_t tid, void *context, int fd, const char *prefix);\nchar *xunwind_cfi_get(pid_t pid, pid_t tid, void *context, const char *prefix);\n```\n\nThese three functions correspond to three ways of obtaining backtrace. They are:\n\n* `log` to Android logcat.\n* `dump` to a place associated with FD (such as file, pipe, socket, etc.).\n* `get` and return a string (which is allocated on the heap with `malloc()`, you need to `free()` it yourself).\n\nThe `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.\n\nThe `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`).\n\nThe 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.\n\nThe optional `prefix` parameter is used to specify a prefix string for each line of backtrace.\n\n### 2. FP and EH unwinding\n\n```C\nsize_t xunwind_fp_unwind(uintptr_t* frames, size_t frames_cap, void *context);\nsize_t xunwind_eh_unwind(uintptr_t* frames, size_t frames_cap, void *context);\n\nvoid xunwind_frames_log(uintptr_t* frames, size_t frames_sz, const char *logtag, android_LogPriority priority, const char *prefix);\nvoid xunwind_frames_dump(uintptr_t* frames, size_t frames_sz, int fd, const char *prefix);\nchar *xunwind_frames_get(uintptr_t* frames, size_t frames_sz, const char *prefix);\n```\n\nCurrently, FP unwinding is ARM64 only.\n\n`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.\n\nThe meaning of the optional `context` parameter is the same as that of CFI unwinding.\n\nThe 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.\n\n\n## Java API\n\n```Java\nimport io.github.hexhacking.xunwind.XUnwind;\n```\n\n### 1. Initialize\n\n```Java\npublic static void init();\n```\n\nThe only thing `init()` does is `System.loadLibrary(\"xunwind\")`. If you only use xUnwind in native code, no initialization is required.\n\n### 2. CFI unwinding\n\n```Java\npublic static void logLocalCurrentThread(String logtag, int priority, String prefix);\npublic static void logLocalThread(int tid, String logtag, int priority, String prefix);\npublic static void logLocalAllThread(String logtag, int priority, String prefix);\npublic static void logRemoteThread(int pid, int tid, String logtag, int priority, String prefix);\npublic static void logRemoteAllThread(int pid, String logtag, int priority, String prefix);\n\npublic static void dumpLocalCurrentThread(int fd, String prefix);\npublic static void dumpLocalThread(int tid, int fd, String prefix);\npublic static void dumpLocalAllThread(int fd, String prefix);\npublic static void dumpRemoteThread(int pid, int tid, int fd, String prefix);\npublic static void dumpRemoteAllThread(int pid, int fd, String prefix);\n\npublic static String getLocalCurrentThread(String prefix);\npublic static String getLocalThread(int tid, String prefix);\npublic static String getLocalAllThread(String prefix);\npublic static String getRemoteThread(int pid, int tid, String prefix);\npublic static String getRemoteAllThread(int pid, String prefix);\n```\n\nAll native CFI unwinding capabilities have corresponding java functions. They call the native CFI unwinding functions through JNI.\n\nFP 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.\n\n\n## Support\n\n* [GitHub Issues](https://github.com/hexhacking/xUnwind/issues)\n* [GitHub Discussions](https://github.com/hexhacking/xUnwind/discussions)\n* [Telegram Public Group](https://t.me/android_native_geeks)\n\n\n## Contributing\n\n* [Code of Conduct](CODE_OF_CONDUCT.md)\n* [Contributing Guide](CONTRIBUTING.md)\n* [Reporting Security vulnerabilities](SECURITY.md)\n\n\n## License\n\nxUnwind is MIT licensed, as found in the [LICENSE](LICENSE) file.\n\n\n## History\n\n[xCrash 2.x](https://github.com/hexhacking/xCrash/tree/4748d183c1395c54bfb760ec6c454966d52ab73f) contains a set of methods [xcc\\_unwind\\_*](https://github.com/hexhacking/xCrash/tree/4748d183c1395c54bfb760ec6c454966d52ab73f/src/native/common) 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.\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexhacking%2FxUnwind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhexhacking%2FxUnwind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexhacking%2FxUnwind/lists"}