sourcemap功能简介

现在不管是前端应用还是移动端应用,生产环境一般都会压缩(shrink)混淆 (obfuscation) 代码,混淆处理的目的是通过缩短应用的类、方法和字段的名称来缩减应用的大小。下面是使用Android R8 进行混淆处理的一个示例:

androidx.appcompat.app.ActionBarDrawerToggle$DelegateProvider -> a.a.a.b:
androidx.appcompat.app.AlertController -> androidx.appcompat.app.AlertController:
    android.content.Context mContext -> a
    int mListItemLayout -> O
    int mViewSpacingRight -> l
    android.widget.Button mButtonNeutral -> w
    int mMultiChoiceItemLayout -> M
    boolean mShowTitle -> P
    int mViewSpacingLeft -> j
    int mButtonPanelSideLayout -> K

Java开源压缩技术 ProGuard 声称能够达到90%的压缩率和20%的性能提升
在这里插入图片描述

有些语言的backtrace没有文件名和行号,例如C语言,使用backtrace 方法可以打印调用栈

#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>

int show = 0;
int fibonacci(int n) {
	if (n <= 1) {
		if (!show) {
			void *callStack[32];
			int r = backtrace(callStack, 32);
			printf("collect %d callstack\n", r);
			char** symbols = backtrace_symbols(callStack, r);
			for(int i = 0; i < r; i++) {
				printf("%s\n", symbols[i]);
			}
			free(symbols);
			show = 1;
		}
		return n;
	}

	return fibonacci(n-1) + fibonacci(n-2);
}

int main() {
	fibonacci(5);
	return 0;
}

会输出:

collect 8 callstack
./backtrace(+0x11b6) [0x55dda8ff61b6]
./backtrace(+0x1249) [0x55dda8ff6249]
./backtrace(+0x1249) [0x55dda8ff6249]
./backtrace(+0x1249) [0x55dda8ff6249]
./backtrace(+0x1249) [0x55dda8ff6249]
./backtrace(+0x1275) [0x55dda8ff6275]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xeb) [0x7f514f4e609b]
./backtrace(+0x10ba) [0x55dda8ff60ba]

只有函数名和内存地址,缺少文件名和行号,如果需要定位文件名和行号需要结合类似addr2line工具和包含调试信息的可执行文件来获取

$ gcc -g backtrace.c -o backtrace
$
$ addr2line -e backtrace 0x11b6
/root/backtrace.c:10
$ addr2line -e backtrace 0x1249
/root/backtrace.c:22
$ addr2line -e backtrace 0x1275
/root/backtrace.c:27

什么是符号表?
符号表是内存地址与函数名、文件名、行号的映射表。符号表元素如下所示:

<起始地址> <结束地址> <函数> [<文件名:行号>]

iOS符号还原效果
在这里插入图片描述

iOS平台上的 sourcemap 文件是以 .dSYM 为后缀的带有调试信息的符号表文件,一般情况下,项目编译完和 .app 文件在同一个目录下,如下所示:

$ ls -l Build/Products/Debug-iphonesimulator/
total 0
drwxr-xr-x   6 zy  staff  192  8  9 15:27 Fishing.app
drwxr-xr-x   3 zy  staff   96  8  9 14:02 Fishing.app.dSYM
drwxr-xr-x  15 zy  staff  480  8  9 15:27 Fishing.doccarchive
drwxr-xr-x   6 zy  staff  192  8  9 13:55 Fishing.swiftmodule

需要注意,XCode Release 编译默认会生成 .dSYM 文件,而Debug 编译默认不会生成,需要对 XCode 做如下相应的设置:

Build Settings -> Code Generation -> Generate Debug Symbols -> Yes
Build Settings -> Build Option -> Debug Information Format -> DWARF with dSYM File

在这里插入图片描述
在这里插入图片描述
还原工具可使用macOS自带的 atos

atos(1)                                        General Commands Manual                                       atos(1)

NAME
     atos – convert numeric addresses to symbols of binary images or processes

SYNOPSIS
     atos [-o <binary-image-file> | <dSYM>] [-p <pid> | <partial-executable-name>] [-arch architecture]
          [-l <load-address>] [-s <slide>] [-printHeader] [-fullPath] [-i] [-d <delimiter>]
          [-f <address-input-file>] [<address> ...]

DESCRIPTION
     The atos command converts numeric addresses to their symbolic equivalents.  If full debug symbol information is
     available, for example in a .app.dSYM sitting beside a .app, then the output of atos will include file name and
     source line number information.
...
...

示例:

$ atos -o /BuildProducts/Release/Sketch.app.dSYM -arch x86_64 -l 0x10acde000  0x10acea1d3 0x10ace4bea 0x10ace4b7a
     -[SKTGraphicView drawRect:] (in Sketch) (SKTGraphicView.m:445)
     -[SKTGraphic drawHandlesInView:] (in Sketch) (NSGeometry.h:110)
     -[SKTGraphic drawHandleInView:atPoint:] (in Sketch) (SKTGraphic.m:490)

Android有两种符号表

第一种:原生C/C++代码的 .so符号表

在这里插入图片描述
可以使用 Android NDK 中集成的工具 ndk-stack 来还原

$ ndk-stack --help
usage: ndk-stack.py [-h] -sym SYMBOL_DIR [-i INPUT]

Symbolizes Android crashes.

optional arguments:
  -h, --help            show this help message and exit
  -sym SYMBOL_DIR, --sym SYMBOL_DIR
                        directory containing unstripped .so files
  -i INPUT, -dump INPUT, --dump INPUT
                        input filename

See <https://developer.android.com/ndk/guides/ndk-stack>.

使用示例:

$ ndk-stack --sym ~/software/source_map/Android/C_C++/obj/arm64-v8a/ -i ~/software/source_map/Android/C_C++/crash.txt
********** Crash dump: **********
Build fingerprint: 'Android/sdk_phone64_arm64/emulator64_arm64:12/SE1A.220203.002.A1/8151367:userdebug/test-keys'
Abort message: 'abort message for ftNative internal testing'
#00 0x00000000000057fc /data/app/~~Taci3mQyw7W7iWT7Jxo-ag==/com.ft-Q8m2flQFG1MbGImPiuAZmQ==/lib/arm64/libft_native_exp_lib.so (xc_test_call_4+12)
                                                                                                                               xc_test_call_4
                                                                                                                               /Users/Brandon/Documents/workplace/working/StudioPlace/xCrash/xcrash_lib/src/main/cpp/xcrash/xc_test.c:65:9
#01 0x00000000000058a4 /data/app/~~Taci3mQyw7W7iWT7Jxo-ag==/com.ft-Q8m2flQFG1MbGImPiuAZmQ==/lib/arm64/libft_native_exp_lib.so (xc_test_call_3+8)
                                                                                                                               xc_test_call_3
                                                                                                                               /Users/Brandon/Documents/workplace/working/StudioPlace/xCrash/xcrash_lib/src/main/cpp/xcrash/xc_test.c:73:13
#02 0x00000000000058b4 /data/app/~~Taci3mQyw7W7iWT7Jxo-ag==/com.ft-Q8m2flQFG1MbGImPiuAZmQ==/lib/arm64/libft_native_exp_lib.so (xc_test_call_2+12)

第二种:Java/Kotlin 语言 shrink后生成的mapping文件

Java 目前主要有两种压缩混淆技术,ProGuardAndroid R8

还原调用栈 两者都提供了 retrace (retrace.sh) 脚本

ProGuard

$ /usr/local/proguard-7.2.2/bin/retrace.sh
Usage: java proguard.retrace.ReTrace [-regex <regex>] [-allclassnames] [-verbose] <mapping_file> [<stacktrace_file>]

Default regex: (?:.*?\bat\s+%c\.%m\s*(?:\+\s+[0-9]+)?(?:\(\))?(?:\((?:%s)?(?::?%l)?(?::\d+)?\))?\s*(?:~\[.*\])?)|(?:.*?\bjava\.lang\.ClassCastException: %c cannot be cast to .{5,})|(?:.*?\bjava\.lang\.ClassCastException: .* cannot be cast to %c)|(?:.*?\bjava\.lang\.NullPointerException: Attempt to read from field '%t %c\.%f' on a null object reference)|(?:.*?\bjava\.lang\.NullPointerException: Attempt to write to field '%t %c\.%f' on a null object reference)|(?:.*?\bjava\.lang\.NullPointerException: Attempt to invoke (?:virtual|interface) method '%t %c\.%m\(%a\)' on a null object reference)|(?:.*?\bjava\.lang\.NullPointerException: Cannot invoke \".*\" because the return value of \"%c\.%m\(%a\)\" is null)|(?:.*?\bbecause \"%c\.%f\" is null)|(?:(?:.*?[:"]\s+)?%c(?::.*)?)

Android R8可以使用 Android command line tools

$ /usr/local/cmdline-tools/bin/retrace --help
Retrace 3.2.47 (build 00d5d321bbff9d427a16574fe6e1fdd95bcf9378 from go/r8bot (luci-r8-custom-ci-xenial-36-mfdm))
Usage: retrace <proguard-map> [stack-trace-file] [--regex <regexp>, --verbose, --info, --quiet, --verify-mapping-file-hash]
  where <proguard-map> is an r8 generated mapping file.

使用示例:

$ /usr/local/cmdline-tools/bin/retrace ~/software/source_map/Android/Java_Kotlin/mapping.txt ~/software/source_map/Android/Java_Kotlin/java_crash.txt
java.lang.ArithmeticException: divide by zero
	at prof.wang.activity.TeamInvitationActivity.onClick$lambda-0(TeamInvitationActivity.java:1)
	at java.lang.Thread.run(Thread.java:1012)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值