Skip to content

Commit 6491b3e

Browse files
authored
Merge pull request #660 from Tencent/feature/dev
Matrix v2.0.2
2 parents dbfea61 + e836bbc commit 6491b3e

File tree

109 files changed

+7605
-942
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+7605
-942
lines changed

README.md

+36-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
![Matrix-icon](assets/img/readme/header.png)
22
[![license](http://img.shields.io/badge/license-BSD3-brightgreen.svg?style=flat)](https://github.com/Tencent/matrix/blob/master/LICENSE)
33
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/matrix/pulls)
4-
[![WeChat Approved](https://img.shields.io/badge/Wechat%20Approved-2.0.1-red.svg)](https://github.com/Tencent/matrix/wiki)
4+
[![WeChat Approved](https://img.shields.io/badge/Wechat%20Approved-2.0.2-red.svg)](https://github.com/Tencent/matrix/wiki)
55
[![CircleCI](https://circleci.com/gh/Tencent/matrix.svg?style=shield)](https://app.circleci.com/pipelines/github/Tencent/matrix)
66

77
(中文版本请参看[这里](#matrix_cn))
@@ -140,6 +140,10 @@ At this point, Matrix has been integrated into the app and is beginning to colle
140140
- **Battery Canary:**
141141

142142
App thread activities monitor (Background watch & foreground loop watch), Sonsor usage monitor (WakeLock/Alarm/Gps/Wifi/Bluetooth), Background network activities (Wifi/Mobile) monitor.
143+
144+
- **MemGuard**
145+
146+
Detect heap memory overlap, use-after-free and double free issues.
143147

144148

145149
## Features
@@ -197,6 +201,14 @@ At this point, Matrix has been integrated into the app and is beginning to colle
197201
+ **Non-invasive.** It is based on PLT-hook([iqiyi/xHook](https://github.com/iqiyi/xHook)), so we do NOT need to recompile the native libraries.
198202
+ WebView still works after using this tool.
199203

204+
#### MemGuard
205+
206+
+ A tool base on GWP-Asan to detect heap memory issues.
207+
+ **Non-invasive.** It is based on PLT-hook([iqiyi/xHook](https://github.com/iqiyi/xHook)), so we do NOT need to recompile the native libraries.
208+
+ It's able to apply on specific libraries that needs to be detected by RegEx.
209+
210+
+ It detects heap memory accessing overlap, use-after-free and double free issues.
211+
200212

201213
#### Backtrace Component
202214

@@ -208,7 +220,7 @@ At this point, Matrix has been integrated into the app and is beginning to colle
208220

209221
1. Configure `MATRIX_VERSION` in gradle.properties.
210222
``` gradle
211-
MATRIX_VERSION=2.0.1
223+
MATRIX_VERSION=2.0.2
212224
```
213225

214226
2. Add `matrix-gradle-plugin` in your build.gradle:
@@ -357,11 +369,11 @@ Then other components in Matrix could use Quikcen Backtrace to unwind stacktrace
357369

358370
#### APK Checker Usage
359371

360-
APK Checker can run independently in Jar ([matrix-apk-canary-2.0.1.jar](https://repo.maven.apache.org/maven2/com/tencent/matrix/matrix-apk-canary/2.0.1/matrix-apk-canary-2.0.1.jar)) mode, usage:
372+
APK Checker can run independently in Jar ([matrix-apk-canary-2.0.2.jar](https://repo.maven.apache.org/maven2/com/tencent/matrix/matrix-apk-canary/2.0.2/matrix-apk-canary-2.0.2.jar)) mode, usage:
361373

362374

363375
```shell
364-
java -jar matrix-apk-canary-2.0.1.jar
376+
java -jar matrix-apk-canary-2.0.2.jar
365377
Usages:
366378
--config CONFIG-FILE-PATH
367379
or
@@ -420,7 +432,7 @@ Matrix is under the BSD license. See the [LICENSE](https://github.com/Tencent/Ma
420432
421433
# <a name="matrix_cn">Matrix</a>
422434
![Matrix-icon](assets/img/readme/header.png)
423-
[![license](http://img.shields.io/badge/license-BSD3-brightgreen.svg?style=flat)](https://github.com/Tencent/matrix/blob/master/LICENSE)[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/matrix/pulls) [![WeChat Approved](https://img.shields.io/badge/Wechat%20Approved-2.0.1-red.svg)](https://github.com/Tencent/matrix/wiki)
435+
[![license](http://img.shields.io/badge/license-BSD3-brightgreen.svg?style=flat)](https://github.com/Tencent/matrix/blob/master/LICENSE)[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/matrix/pulls) [![WeChat Approved](https://img.shields.io/badge/Wechat%20Approved-2.0.2-red.svg)](https://github.com/Tencent/matrix/wiki)
424436
425437
**Matrix** 是一款微信研发并日常使用的应用性能接入框架,支持iOS, macOS和Android。
426438
Matrix 通过接入各种性能监控方案,对性能监控项的异常数据进行采集和分析,输出相应的问题分析、定位与优化建议,从而帮助开发者开发出更高质量的应用。
@@ -529,16 +541,25 @@ curBuilder.pluginListener = <一个遵循 MatrixPluginListenerDelegate 的对象
529541
Matrix-android 当前监控范围包括:应用安装包大小,帧率变化,启动耗时,卡顿,慢方法,SQLite 操作优化,文件读写,内存泄漏等等。
530542
- APK Checker:
531543
针对 APK 安装包的分析检测工具,根据一系列设定好的规则,检测 APK 是否存在特定的问题,并输出较为详细的检测结果报告,用于分析排查问题以及版本追踪
544+
532545
- Resource Canary:
533546
基于 WeakReference 的特性和 [Square Haha](https://github.com/square/haha) 库开发的 Activity 泄漏和 Bitmap 重复创建检测工具
547+
534548
- Trace Canary:
535549
监控ANR、界面流畅性、启动耗时、页面切换耗时、慢函数及卡顿等问题
550+
536551
- SQLite Lint:
537552
按官方最佳实践自动化检测 SQLite 语句的使用质量
553+
538554
- IO Canary:
539555
检测文件 IO 问题,包括:文件 IO 监控和 Closeable Leak 监控
556+
540557
- Battery Canary:
541558
监控 App 活跃线程(待机状态 & 前台 Loop 监控)、ASM 调用 (WakeLock/Alarm/Gps/Wifi/Bluetooth 等传感器)、 后台流量 (Wifi/移动网络)等 Battery Historian 统计 App 耗电的数据
559+
560+
- MemGuard
561+
562+
检测堆内存访问越界、使用释放后的内存、重复释放等问题
542563

543564
## 特性
544565

@@ -599,6 +620,13 @@ Matrix-android 当前监控范围包括:应用安装包大小,帧率变化
599620
+ 无侵入,基于 PLT-hook([iqiyi/xHook](https://github.com/iqiyi/xHook)),无需重编 native 库
600621
+ 使用该工具后 WebView 仍可正常工作
601622

623+
#### MemGuard
624+
625+
+ 一个基于 GWP-Asan 修改的堆内存问题检测工具
626+
+ 无侵入,基于 PLT-hook([iqiyi/xHook](https://github.com/iqiyi/xHook)),无需重编 native 库
627+
+ 可根据正则表达式指定被检测的目标库
628+
+ 可检测堆内存访问越界、使用释放后的内存和双重释放等问题
629+
602630
#### Backtrace Component
603631
- 基于 DWARF 以及 ARM 异常处理数据进行简化并生成全新的 quicken unwind tables 数据,用于实现可快速回溯 native 调用栈的 backtrace 组件。回溯速度约是 libunwindstack 的 15x ~ 30x 左右。
604632

@@ -608,7 +636,7 @@ Matrix-android 当前监控范围包括:应用安装包大小,帧率变化
608636

609637
1. 在你项目根目录下的 gradle.properties 中配置要依赖的 Matrix 版本号,如:
610638
``` gradle
611-
MATRIX_VERSION=2.0.1
639+
MATRIX_VERSION=2.0.2
612640
```
613641

614642
2. 在你项目根目录下的 build.gradle 文件添加 Matrix 依赖,如:
@@ -754,10 +782,10 @@ WeChatBacktrace.instance().configure(getApplicationContext()).commit();
754782
755783
#### APK Checker
756784
757-
APK Check 以独立的 jar 包提供 ([matrix-apk-canary-2.0.1.jar](https://repo.maven.apache.org/maven2/com/tencent/matrix/matrix-apk-canary/2.0.1/matrix-apk-canary-2.0.1.jar)),你可以运行:
785+
APK Check 以独立的 jar 包提供 ([matrix-apk-canary-2.0.2.jar](https://repo.maven.apache.org/maven2/com/tencent/matrix/matrix-apk-canary/2.0.2/matrix-apk-canary-2.0.2.jar)),你可以运行:
758786
759787
```cmd
760-
java -jar matrix-apk-canary-2.0.1.jar
788+
java -jar matrix-apk-canary-2.0.2.jar
761789
```
762790
763791
查看 Usages 来使用它。

matrix/matrix-android/gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro
1414
# org.gradle.parallel=true
1515
#Tue Jun 20 10:24:33 CST 2017
1616

17-
VERSION_NAME_PREFIX=2.0.1
17+
VERSION_NAME_PREFIX=2.0.2
1818
VERSION_NAME_SUFFIX=
1919
## two options: Internal (for wechat), External (for public repo)
2020
PUBLISH_CHANNEL=Internal

matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnzipTask.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,16 @@ private String reverseResguard(String dirName, String filename) {
227227

228228
private String writeEntry(ZipFile zipFile, ZipEntry entry) throws IOException {
229229

230+
String entryName = entry.getName();
231+
if (Util.preventZipSlip(outputFile, entryName)) {
232+
Log.e(TAG, "writeEntry entry %s failed!", entryName);
233+
return null;
234+
}
235+
230236
int readSize;
231237
byte[] readBuffer = new byte[4096];
232238
BufferedOutputStream bufferedOutput = null;
233239
InputStream zipInputStream = null;
234-
String entryName = entry.getName();
235240
String outEntryName = null;
236241
String filename;
237242
File dir;

matrix/matrix-android/matrix-backtrace/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ android {
1919

2020
externalNativeBuild {
2121
cmake {
22+
targets = ['wechatbacktrace', 'unwindstack']
2223
arguments = ['-DANDROID_STL=c++_shared',
2324
"-DEnableLOG=${gradle.enableLog() ? "ON" : "OFF"}" as String,
2425
"-DQUT_STATISTIC_ENABLE=${gradle.enableLog() ? "ON" : "OFF"}" as String]

matrix/matrix-android/matrix-backtrace/src/main/cpp/external/libunwindstack/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ SET(
1717
${CMAKE_CURRENT_SOURCE_DIR}/ElfInterfaceArm.cpp
1818
${CMAKE_CURRENT_SOURCE_DIR}/JitDebug.cpp
1919
${CMAKE_CURRENT_SOURCE_DIR}/Log.cpp
20+
${CMAKE_CURRENT_SOURCE_DIR}/LocalUnwinder.cpp
2021
${CMAKE_CURRENT_SOURCE_DIR}/MapInfo.cpp
2122
${CMAKE_CURRENT_SOURCE_DIR}/Maps.cpp
2223
${CMAKE_CURRENT_SOURCE_DIR}/Memory.cpp

matrix/matrix-android/matrix-backtrace/src/main/cpp/external/libunwindstack/LocalUnwinder.cpp

+103
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131

3232
#include <memory>
3333
#include <string>
34+
#include <sstream>
3435
#include <vector>
36+
#include <iomanip>
3537

3638
#include <unwindstack/Elf.h>
3739
#include <unwindstack/LocalUnwinder.h>
@@ -142,4 +144,105 @@ bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_f
142144
return num_frames != 0;
143145
}
144146

147+
size_t LocalUnwinder::UnwindImpl(std::unique_ptr<unwindstack::Regs>& regs, void** pcs, size_t max_frames) {
148+
ArchEnum arch = regs->Arch();
149+
150+
size_t num_frames = 0;
151+
bool adjust_pc = false;
152+
while (true) {
153+
uint64_t cur_pc = regs->pc();
154+
uint64_t cur_sp = regs->sp();
155+
156+
MapInfo* map_info = GetMapInfo(cur_pc);
157+
if (map_info == nullptr) {
158+
break;
159+
}
160+
161+
Elf* elf = map_info->GetElf(process_memory_, arch);
162+
uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info);
163+
uint64_t step_pc = rel_pc;
164+
uint64_t pc_adjustment;
165+
if (adjust_pc) {
166+
pc_adjustment = GetPcAdjustment(rel_pc, elf, arch);
167+
} else {
168+
pc_adjustment = 0;
169+
}
170+
step_pc -= pc_adjustment;
171+
172+
bool finished = false;
173+
if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) {
174+
step_pc = rel_pc;
175+
} else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished)) {
176+
finished = true;
177+
}
178+
179+
// Skip any locations that are within this library.
180+
if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) {
181+
pcs[num_frames++] = (void*) cur_pc;
182+
if (num_frames >= max_frames) {
183+
break;
184+
}
185+
}
186+
187+
if (finished || num_frames == max_frames ||
188+
(cur_pc == regs->pc() && cur_sp == regs->sp())) {
189+
break;
190+
}
191+
adjust_pc = true;
192+
}
193+
return num_frames;
194+
}
195+
196+
size_t LocalUnwinder::Unwind(void** pcs, size_t max_frames) {
197+
std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
198+
unwindstack::RegsGetLocal(regs.get());
199+
return UnwindImpl(regs, pcs, max_frames);
200+
}
201+
202+
size_t LocalUnwinder::Unwind(void* ucontext, void** pcs, size_t max_frames) {
203+
std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
204+
return UnwindImpl(regs, pcs, max_frames);
205+
}
206+
207+
extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
208+
209+
bool LocalUnwinder::GetStackElementString(uint64_t pc, std::string* string_out) {
210+
MapInfo* map_info = GetMapInfo(pc);
211+
if (map_info == nullptr) {
212+
return false;
213+
}
214+
auto elf = map_info->GetElf(process_memory_, Regs::CurrentArch());
215+
uint64_t rel_pc = elf->GetRelPc(pc, map_info);
216+
217+
std::stringstream ss;
218+
std::ios fmt(nullptr);
219+
fmt.copyfmt(ss);
220+
ss << "pc " << std::hex << std::setw(sizeof(void*) * 2) << std::setfill('0') << rel_pc << std::dec << ' ';
221+
ss.copyfmt(fmt);
222+
223+
std::string funcName;
224+
uint64_t funcOffset = 0;
225+
bool isFuncNameGot = map_info->GetFunctionName(rel_pc, &funcName, &funcOffset);
226+
if (isFuncNameGot) {
227+
char* demangledFuncName = nullptr;
228+
if (!funcName.empty()) {
229+
demangledFuncName = __cxa_demangle(funcName.c_str(), nullptr, nullptr, nullptr);
230+
}
231+
if (demangledFuncName != nullptr) {
232+
ss << map_info->name << " (" << demangledFuncName << ")";
233+
free(demangledFuncName);
234+
} else {
235+
ss << map_info->name << " (" << funcName << ")";
236+
}
237+
} else {
238+
ss << map_info->name << " (?\?\?)";
239+
}
240+
auto buildID = map_info->GetPrintableBuildID();
241+
if (!buildID.empty()) {
242+
ss << " (BuildID: " << map_info->GetPrintableBuildID() << ")";
243+
}
244+
*string_out = ss.str();
245+
return true;
246+
}
247+
145248
} // namespace unwindstack

matrix/matrix-android/matrix-backtrace/src/main/cpp/external/libunwindstack/include/unwindstack/LocalUnwinder.h

+8
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,22 @@ class LocalUnwinder {
6666

6767
bool Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames);
6868

69+
size_t Unwind(void** pcs, size_t max_frames);
70+
71+
size_t Unwind(void* ucontext, void** pcs, size_t max_frames);
72+
6973
bool ShouldSkipLibrary(const std::string& map_name);
7074

7175
MapInfo* GetMapInfo(uint64_t pc);
7276

77+
bool GetStackElementString(uint64_t pc, std::string* string_out);
78+
7379
ErrorCode LastErrorCode() { return last_error_.code; }
7480
uint64_t LastErrorAddress() { return last_error_.address; }
7581

7682
private:
83+
size_t UnwindImpl(std::unique_ptr<unwindstack::Regs>& regs, void** pcs, size_t max_frames);
84+
7785
pthread_rwlock_t maps_rwlock_;
7886
std::unique_ptr<LocalUpdatableMaps> maps_ = nullptr;
7987
std::shared_ptr<Memory> process_memory_;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//
2+
// Created by YinSheng Tang on 2021/9/23.
3+
//
4+

matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WarmUpDelegate.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.os.Message;
2828
import android.os.OperationCanceledException;
2929
import android.os.Process;
30+
import android.system.ErrnoException;
3031
import android.system.Os;
3132
import android.system.StructStat;
3233
import android.util.Pair;
@@ -518,8 +519,13 @@ public void run() {
518519
iterateTargetDirectory(file, cs, new FileFilter() {
519520
@Override
520521
public boolean accept(File pathname) {
521-
count[0] += 1;
522-
count[1] += pathname.isFile() ? pathname.length() : 0;
522+
try {
523+
StructStat stat = Os.lstat(pathname.getAbsolutePath());
524+
count[0] += 1;
525+
count[1] += stat.st_blocks * stat.st_blksize;
526+
} catch (ErrnoException e) {
527+
MatrixLog.printErrStackTrace(TAG, e, "");
528+
}
523529
return false;
524530
}
525531
});

matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WarmUpScheduler.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,10 @@ private final static class IdleReceiver extends BroadcastReceiver {
197197
Handler mIdleHandler;
198198

199199
Context mContext;
200-
private WeChatBacktrace.WarmUpTiming mTiming;
201-
private long mWarmUpDelay;
200+
private final WeChatBacktrace.WarmUpTiming mTiming;
201+
private final long mWarmUpDelay;
202202

203-
private Set<TaskType> mTasks = new HashSet<>();
203+
private final Set<TaskType> mTasks = new HashSet<>();
204204

205205
IdleReceiver(Context context, Handler idleHandler, WeChatBacktrace.WarmUpTiming timing,
206206
long delay) {

matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WarmUpUtility.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ class WarmUpUtility {
4141
private final static String FILE_BLOCKED_LIST = "blocked-list";
4242
private final static String FILE_UNFINISHED = "unfinished";
4343

44-
final static long DURATION_LAST_ACCESS_FAR_FUTURE = 30L * 24 * 3600 * 1000; // milliseconds
45-
final static long DURATION_LAST_ACCESS_EXPIRED = 60L * 24 * 3600 * 1000; // milliseconds
46-
final static long DURATION_CLEAN_UP_EXPIRED = 3L * 24 * 3600 * 1000; // milliseconds
47-
final static long DURATION_CLEAN_UP = 3L * 24 * 3600 * 1000; // milliseconds
44+
final static long DURATION_LAST_ACCESS_FAR_FUTURE = 7L * 24 * 3600 * 1000; // milliseconds
45+
final static long DURATION_LAST_ACCESS_EXPIRED = 3L * 24 * 3600 * 1000; // milliseconds
46+
final static long DURATION_CLEAN_UP_EXPIRED = 2L * 24 * 3600 * 1000; // milliseconds
47+
final static long DURATION_CLEAN_UP = 2L * 24 * 3600 * 1000; // milliseconds
4848
final static long DURATION_DISK_USAGE_COMPUTATION = 3L * 24 * 3600 * 1000; // milliseconds
4949

5050
final static int WARM_UP_FILE_MAX_RETRY = 3;
@@ -61,8 +61,7 @@ private static int retryCount(Context context, String key) {
6161
mUnfinishedWarmUp = WarmUpUtility.readUnfinishedMaps(context);
6262
}
6363
Integer value = mUnfinishedWarmUp.get(key);
64-
int retryCount = value != null ? value : 0;
65-
return retryCount;
64+
return value != null ? value : 0;
6665
}
6766

6867
public static boolean check(Context context, String pathOfElf, int offset) {

matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WeChatBacktrace.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ public static String getBaseODEXPath(Context context) {
7575
private volatile boolean mInitialized;
7676
private volatile boolean mConfigured;
7777
private volatile Configuration mConfiguration;
78-
private WarmUpDelegate mWarmUpDelegate = new WarmUpDelegate();
79-
private Handler mHandler = new Handler(Looper.getMainLooper());
78+
private final WarmUpDelegate mWarmUpDelegate = new WarmUpDelegate();
79+
private final Handler mHandler = new Handler(Looper.getMainLooper());
8080

8181
private static boolean sLibraryLoaded = false;
8282

@@ -345,7 +345,7 @@ public final static class Configuration {
345345
String mPathOfXLogSo = null;
346346

347347
private boolean mCommitted = false;
348-
private WeChatBacktrace mWeChatBacktrace;
348+
private final WeChatBacktrace mWeChatBacktrace;
349349

350350
Configuration(Context context, WeChatBacktrace backtrace) {
351351
mContext = context;

0 commit comments

Comments
 (0)