├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── encodings.xml ├── gradle.xml ├── misc.xml └── runConfigurations.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── info │ │ └── lofei │ │ └── app │ │ └── testjni │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ ├── fake_dlfcn.cpp │ │ ├── fake_dlfcn.h │ │ ├── fake_jdwp.cpp │ │ ├── fake_jdwp.h │ │ └── native-lib.cpp │ ├── java │ │ └── info │ │ │ └── lofei │ │ │ └── app │ │ │ └── testjni │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── info │ └── lofei │ └── app │ └── testjni │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidRemoteDebug 2 | Enable jdwp for android release apk to support remote debug. 3 | 4 | # See Also 5 | * [https://tech.meituan.com/2017/07/20/android-remote-debug.html](https://tech.meituan.com/2017/07/20/android-remote-debug.html "Android remote debug, Meituan Tech") 6 | * [https://github.com/avs333/Nougat_dlfunctions](https://github.com/avs333/Nougat_dlfunctions "Nougat dlfunctions") 7 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | signingConfigs { 5 | config { 6 | keyAlias 'test' 7 | keyPassword 'testtest' 8 | storeFile file('/Users/lofei/Documents/tmp1/test.jks') 9 | storePassword 'testtest' 10 | } 11 | } 12 | compileSdkVersion 28 13 | defaultConfig { 14 | applicationId "info.lofei.app.testjni" 15 | minSdkVersion 21 16 | targetSdkVersion 28 17 | versionCode 1 18 | versionName "1.0" 19 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 20 | externalNativeBuild { 21 | cmake { 22 | cppFlags "" 23 | // abiFilters 'armeabi-v7a' 24 | // arguments "-DANDROID_ABI=armeabi-v7a" 25 | } 26 | } 27 | } 28 | lintOptions { 29 | checkReleaseBuilds false // Add this 30 | abortOnError false 31 | } 32 | buildTypes { 33 | release { 34 | minifyEnabled false 35 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 36 | signingConfig signingConfigs.config 37 | } 38 | } 39 | externalNativeBuild { 40 | cmake { 41 | path "src/main/cpp/CMakeLists.txt" 42 | } 43 | } 44 | } 45 | 46 | dependencies { 47 | implementation fileTree(include: ['*.jar'], dir: 'libs') 48 | implementation 'com.android.support:appcompat-v7:28.0.0' 49 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 50 | testImplementation 'junit:junit:4.12' 51 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 52 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 53 | } 54 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/info/lofei/app/testjni/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package info.lofei.app.testjni; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("info.lofei.app.testjni", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 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 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | native-lib.cpp 21 | 22 | # fake library 23 | fake_dlfcn.h 24 | fake_dlfcn.cpp) 25 | 26 | # Searches for a specified prebuilt library and stores the path as a 27 | # variable. Because CMake includes system libraries in the search path by 28 | # default, you only need to specify the name of the public NDK library 29 | # you want to add. CMake verifies that the library exists before 30 | # completing its build. 31 | 32 | find_library( # Sets the name of the path variable. 33 | log-lib 34 | 35 | # Specifies the name of the NDK library that 36 | # you want CMake to locate. 37 | log ) 38 | 39 | # Specifies libraries CMake should link to your target library. You 40 | # can link multiple libraries, such as libraries you define in this 41 | # build script, prebuilt third-party libraries, or system libraries. 42 | 43 | target_link_libraries( # Specifies the target library. 44 | native-lib 45 | 46 | # Links the target library to the log library 47 | # included in the NDK. 48 | ${log-lib} ) -------------------------------------------------------------------------------- /app/src/main/cpp/fake_dlfcn.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by lofei on 2019/1/24. 3 | // 4 | 5 | #include "fake_dlfcn.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | #define TAG_NAME "fake_dlfcn" 18 | 19 | #define log_info(fmt,args...) __android_log_print(ANDROID_LOG_INFO, TAG_NAME, (const char *) fmt, ##args) 20 | #define log_err(fmt,args...) __android_log_print(ANDROID_LOG_ERROR, TAG_NAME, (const char *) fmt, ##args) 21 | 22 | #ifdef LOG_DBG 23 | #define log_dbg log_info 24 | #else 25 | #define log_dbg(...) 26 | #endif 27 | 28 | #ifdef __arm__ 29 | #define Elf_Ehdr Elf32_Ehdr 30 | #define Elf_Shdr Elf32_Shdr 31 | #define Elf_Sym Elf32_Sym 32 | #elif defined(__aarch64__) 33 | #define Elf_Ehdr Elf64_Ehdr 34 | #define Elf_Shdr Elf64_Shdr 35 | #define Elf_Sym Elf64_Sym 36 | #elif defined(__i386__) 37 | #define Elf_Ehdr Elf32_Ehdr 38 | #define Elf_Shdr Elf32_Shdr 39 | #define Elf_Sym Elf32_Sym 40 | #elif defined(__x86_64) 41 | #define Elf_Ehdr Elf64_Ehdr 42 | #define Elf_Shdr Elf64_Shdr 43 | #define Elf_Sym Elf64_Sym 44 | #else 45 | #error "Arch unknown, please port me" 46 | #endif 47 | 48 | struct ctx { 49 | void *load_addr; 50 | void *dynstr; 51 | void *dynsym; 52 | int nsyms; 53 | off_t bias; 54 | }; 55 | 56 | int v_dlclose(void *handle) { 57 | if (handle) { 58 | struct ctx *ctx = (struct ctx *) handle; 59 | if (ctx->dynsym) free(ctx->dynsym); /* we're saving dynsym and dynstr */ 60 | if (ctx->dynstr) free(ctx->dynstr); /* from library file just in case */ 61 | free(ctx); 62 | } 63 | return 0; 64 | } 65 | 66 | /* flags are ignored */ 67 | 68 | void *v_dlopen(const char *libpath, int flags) { 69 | FILE *maps; 70 | char buff[256]; 71 | struct ctx *ctx = 0; 72 | off_t load_addr, size; 73 | int k, fd = -1, found = 0; 74 | char *shoff; 75 | Elf_Ehdr *elf = static_cast(MAP_FAILED); 76 | 77 | #define fatal(fmt, args...) do { log_err(fmt,##args); goto err_exit; } while(0) 78 | 79 | maps = fopen("/proc/self/maps", "r"); 80 | if (!maps) fatal("failed to open maps"); 81 | 82 | while (!found && fgets(buff, sizeof(buff), maps)) 83 | if (strstr(buff, "r-xp") && strstr(buff, libpath)) found = 1; 84 | 85 | fclose(maps); 86 | 87 | if (!found) fatal("%s not found in my userspace", libpath); 88 | 89 | if (sscanf(buff, "%lx", &load_addr) != 1) 90 | fatal("failed to read load address for %s", libpath); 91 | 92 | log_info("%s loaded in Android at 0x%08lx", libpath, load_addr); 93 | 94 | /* Now, mmap the same library once again */ 95 | 96 | fd = open(libpath, O_RDONLY); 97 | if (fd < 0) fatal("failed to open %s", libpath); 98 | 99 | size = lseek(fd, 0, SEEK_END); 100 | if (size <= 0) fatal("lseek() failed for %s", libpath); 101 | 102 | elf = (Elf_Ehdr *) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); 103 | close(fd); 104 | fd = -1; 105 | 106 | if (elf == MAP_FAILED) fatal("mmap() failed for %s", libpath); 107 | 108 | ctx = (struct ctx *) calloc(1, sizeof(struct ctx)); 109 | if (!ctx) fatal("no memory for %s", libpath); 110 | 111 | ctx->load_addr = (void *) load_addr; 112 | shoff = ((char *) elf) + elf->e_shoff; 113 | 114 | for (k = 0; k < elf->e_shnum; k++, shoff += elf->e_shentsize) { 115 | 116 | Elf_Shdr *sh = (Elf_Shdr *) shoff; 117 | log_dbg("%s: k=%d shdr=%p type=%x", __func__, k, sh, sh->sh_type); 118 | 119 | switch (sh->sh_type) { 120 | 121 | case SHT_DYNSYM: 122 | if (ctx->dynsym) fatal("%s: duplicate DYNSYM sections", libpath); /* .dynsym */ 123 | ctx->dynsym = malloc(sh->sh_size); 124 | if (!ctx->dynsym) fatal("%s: no memory for .dynsym", libpath); 125 | memcpy(ctx->dynsym, ((char *) elf) + sh->sh_offset, sh->sh_size); 126 | ctx->nsyms = (sh->sh_size / sizeof(Elf_Sym)); 127 | break; 128 | 129 | case SHT_STRTAB: 130 | if (ctx->dynstr) break; /* .dynstr is guaranteed to be the first STRTAB */ 131 | ctx->dynstr = malloc(sh->sh_size); 132 | if (!ctx->dynstr) fatal("%s: no memory for .dynstr", libpath); 133 | memcpy(ctx->dynstr, ((char *) elf) + sh->sh_offset, sh->sh_size); 134 | break; 135 | 136 | case SHT_PROGBITS: 137 | if (!ctx->dynstr || !ctx->dynsym) break; 138 | /* won't even bother checking against the section name */ 139 | ctx->bias = (off_t) sh->sh_addr - (off_t) sh->sh_offset; 140 | k = elf->e_shnum; /* exit for */ 141 | break; 142 | } 143 | } 144 | 145 | munmap(elf, size); 146 | elf = 0; 147 | 148 | if (!ctx->dynstr || !ctx->dynsym) fatal("dynamic sections not found in %s", libpath); 149 | 150 | #undef fatal 151 | 152 | log_dbg("%s: ok, dynsym = %p, dynstr = %p", libpath, ctx->dynsym, ctx->dynstr); 153 | 154 | return ctx; 155 | 156 | err_exit: 157 | if (fd >= 0) close(fd); 158 | if (elf != MAP_FAILED) munmap(elf, size); 159 | v_dlclose(ctx); 160 | return 0; 161 | } 162 | 163 | void *v_dlsym(void *handle, const char *name) { 164 | int k; 165 | auto *ctx = (struct ctx *) handle; 166 | auto *sym = (Elf_Sym *) ctx->dynsym; 167 | char *strings = (char *) ctx->dynstr; 168 | 169 | for (k = 0; k < ctx->nsyms; k++, sym++) 170 | if (strcmp(strings + sym->st_name, name) == 0) { 171 | /* NB: sym->st_value is an offset into the section for relocatables, 172 | but a VMA for shared libs or exe files, so we have to subtract the bias */ 173 | void *ret = (char *)ctx->load_addr + sym->st_value - ctx->bias; 174 | log_info("%s found at %p", name, ret); 175 | return ret; 176 | } 177 | return 0; 178 | } 179 | 180 | -------------------------------------------------------------------------------- /app/src/main/cpp/fake_dlfcn.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by lofei on 2019/1/24. 3 | // 4 | 5 | #ifndef __FAKE_DLFCN 6 | #define __FAKE_DLFCN 7 | 8 | #include 9 | 10 | struct ctx; 11 | 12 | 13 | void *v_dlopen(const char *filename, int flags); 14 | int v_dlclose(void *handle); 15 | void *v_dlsym(void *handle, const char *symbol); 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /app/src/main/cpp/fake_jdwp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by lofei on 2019/1/24. 3 | // 4 | 5 | #include "fake_jdwp.h" 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/cpp/fake_jdwp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by lofei on 2019/1/24. 3 | // 4 | 5 | #ifndef TESTJNI_FAKE_JDWP_H 6 | #define TESTJNI_FAKE_JDWP_H 7 | 8 | #endif //TESTJNI_FAKE_JDWP_H 9 | 10 | 11 | enum JdwpTransportType { 12 | kJdwpTransportUnknown = 0, 13 | kJdwpTransportSocket, // transport=dt_socket 14 | kJdwpTransportAndroidAdb, // transport=dt_android_adb 15 | }; 16 | 17 | struct JdwpOptions { 18 | JdwpTransportType transport = kJdwpTransportUnknown; 19 | bool server = false; 20 | bool suspend = false; 21 | std::string host = ""; 22 | uint16_t port = static_cast(-1); 23 | }; 24 | -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fake_jdwp.h" 9 | 10 | #include "fake_dlfcn.h" 11 | 12 | #define TAG "native-lib" // 这个是自定义的LOG的标识 13 | #define DEBUG 1 14 | 15 | #if DEBUG 16 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 17 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 18 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 19 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 20 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 21 | #else 22 | #define LOGD(...) 23 | #define LOGI(...) 24 | #define LOGW(...) 25 | #define LOGE(...) 26 | #define LOGF(...) 27 | #endif 28 | 29 | void reloadJdwpPreNougat(jboolean); 30 | void reloadJdwpNougat(jboolean); 31 | 32 | extern "C" JNIEXPORT jstring JNICALL 33 | Java_info_lofei_app_testjni_MainActivity_stringFromJNI( 34 | JNIEnv* env, 35 | jobject /* this */) { 36 | std::string hello = "Hello from C++"; 37 | return env->NewStringUTF(hello.c_str()); 38 | } 39 | 40 | extern "C" JNIEXPORT void JNICALL 41 | Java_info_lofei_app_testjni_MainActivity_reloadJdwp(JNIEnv* env, jobject obj, jboolean open){ 42 | LOGD("reload jdwp called to %d.", open); 43 | 44 | char osVersion[PROP_VALUE_MAX]; 45 | __system_property_get("ro.build.version.sdk", osVersion); 46 | int version = atoi(osVersion); 47 | LOGD("os version: %d", version); 48 | 49 | if (version >= __ANDROID_API_N__) { 50 | reloadJdwpNougat(open); 51 | } else { 52 | reloadJdwpPreNougat(open); 53 | } 54 | 55 | } 56 | 57 | /** 58 | * Android 7.0及以上重新装载jdwp 59 | * @param open 60 | */ 61 | void reloadJdwpNougat(jboolean open) { 62 | // TODO 需要考虑不同架构路径,如32位和64位不一样 63 | void *handler = v_dlopen("/system/lib64/libart.so", RTLD_NOW); 64 | if(handler == NULL){ 65 | const char* err = dlerror(); 66 | LOGD("dlerror: %s", err); 67 | } 68 | //对于debuggable false的配置,重新设置为可调试 69 | void (*allowJdwp)(bool); 70 | allowJdwp = (void (*)(bool)) v_dlsym(handler, "_ZN3art3Dbg14SetJdwpAllowedEb"); 71 | allowJdwp(true); 72 | 73 | 74 | void (*pfun)(); 75 | //关闭之前启动的jdwp-thread 76 | pfun = (void (*)()) v_dlsym(handler, "_ZN3art3Dbg8StopJdwpEv"); 77 | pfun(); 78 | 79 | if (open == JNI_TRUE) { 80 | //重新配置gJdwpOptions 81 | // bool (*parseJdwpOptions)(const std::string&); 82 | // parseJdwpOptions = (bool (*)(const std::string&)) v_dlsym(handler, 83 | // "_ZN3art11CmdlineTypeINS_4JDWP11JdwpOptionsEE15ParseJdwpOptionERKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEESC_PS2_"); 84 | // std::string options = "transport=dt_socket,address=8000,server=y,suspend=n"; 85 | // parseJdwpOptions(options); 86 | 87 | JdwpOptions jdwpOptions; 88 | jdwpOptions.server = true; 89 | jdwpOptions.suspend = false; 90 | jdwpOptions.port = 8000; 91 | jdwpOptions.host = "127.0.0.1"; 92 | jdwpOptions.transport = JdwpTransportType::kJdwpTransportSocket; 93 | 94 | void (*configureJdwp)(const void*); 95 | configureJdwp = (void (*)(const void*)) v_dlsym (handler, "_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE"); 96 | 97 | configureJdwp(&jdwpOptions); 98 | 99 | //重新startJdwp 100 | pfun = (void (*)()) v_dlsym(handler, "_ZN3art3Dbg9StartJdwpEv"); 101 | pfun(); 102 | } 103 | v_dlclose(handler); 104 | } 105 | 106 | /** 107 | * Android 7.0以前版本重新装载jdwp 108 | * @param open 109 | */ 110 | void reloadJdwpPreNougat(jboolean open) { 111 | void *handler = dlopen("/system/lib/libart.so", RTLD_NOW); 112 | if(handler == NULL){ 113 | const char* err = dlerror(); 114 | LOGD("dlerror: %s", err); 115 | } 116 | //对于debuggable false的配置,重新设置为可调试 117 | void (*allowJdwp)(bool); 118 | allowJdwp = (void (*)(bool)) dlsym(handler, "_ZN3art3Dbg14SetJdwpAllowedEb"); 119 | allowJdwp(true); 120 | 121 | 122 | void (*pfun)(); 123 | //关闭之前启动的jdwp-thread 124 | pfun = (void (*)()) dlsym(handler, "_ZN3art3Dbg8StopJdwpEv"); 125 | pfun(); 126 | 127 | if (open == JNI_TRUE) { 128 | //重新配置gJdwpOptions 129 | bool (*parseJdwpOptions)(const std::string&); 130 | parseJdwpOptions = (bool (*)(const std::string&)) dlsym(handler, 131 | "_ZN3art3Dbg16ParseJdwpOptionsERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE"); 132 | std::string options = "transport=dt_socket,address=8000,server=y,suspend=n"; 133 | parseJdwpOptions(options); 134 | 135 | //重新startJdwp 136 | pfun = (void (*)()) dlsym(handler, "_ZN3art3Dbg9StartJdwpEv"); 137 | pfun(); 138 | } 139 | dlclose(handler); 140 | } -------------------------------------------------------------------------------- /app/src/main/java/info/lofei/app/testjni/MainActivity.java: -------------------------------------------------------------------------------- 1 | package info.lofei.app.testjni; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.CompoundButton; 8 | import android.widget.Switch; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | 14 | // Used to load the 'native-lib' library on application startup. 15 | static { 16 | System.loadLibrary("native-lib"); 17 | } 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | 24 | // Example of a call to a native method 25 | TextView tv = findViewById(R.id.sample_text); 26 | tv.setText(stringFromJNI()); 27 | 28 | Switch btn = findViewById(R.id.btn_reload_jdwp); 29 | btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 30 | @Override 31 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 32 | Log.d("test", "Java click reloadJdwp"); 33 | reloadJdwp(isChecked); 34 | } 35 | }); 36 | } 37 | 38 | public void reloadJdwp(View v) { 39 | 40 | reloadJdwp(true); 41 | } 42 | 43 | public void test(View v) { 44 | Toast.makeText(this, "test click", Toast.LENGTH_SHORT).show(); 45 | } 46 | 47 | /** 48 | * A native method that is implemented by the 'native-lib' native library, 49 | * which is packaged with this application. 50 | */ 51 | public native String stringFromJNI(); 52 | 53 | public native void reloadJdwp(boolean open); 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 29 | 30 |