release模式编译产物,产物位置:{ProjectPath}/{ModuleName}/build/{product}/cache/default/default@CompileArkTS/esmodule/release/sourceMaps.map

带调试信息的so数据,产物位置:{ProjectPath}/{ModuleName}/build/{product}/intermediates/libs
配置方式请参考release编译带调试信息的so。

反混淆映射表,release模式编译产物,产物位置:{ProjectPath}/{ModuleName}/build/{product}/cache/default/default@CompileArkTS/esmodule/release/obfuscation

set_source_files_properties(crash.cpp PROPERTIES COMPILE_FLAGS "-O0 -g -DNDEBUG")
通常release的so中的符号表、调试信息会被移除。

若需要保留so文件中的符号表、调试信息,需要在build-profile.json5的buildOption/externalNativeOptions中配置参数:"arguments": "-DCMAKE_BUILD_TYPE=RelWithDebInfo"。
{
"apiType": "stageMode",
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-DCMAKE_BUILD_TYPE=RelWithDebInfo",
"cppFlags": "",
}
},
} 编译后会生成2份so产物:

llvm-addr2line(在DevEco Studio安装目录的sdk/default/openharmony/native/llvm/bin目录下)是将函数地址解析成文件名或行号的工具。
给出一个可执行文件中的地址或一个可重定位对象中的偏移部分的地址,使用调试信息来找出与之相关的文件名和行号。
常用参数:
参数 | 用途 |
|---|---|
-a | 以十六进制形式显示地址 |
-C | 将符号名解码为用户级别的名字 |
-e | 设置需要转换地址的可执行文件名 |
-f | 显示文件名、行号和函数名信息 |
-F | 显示函数名及文件行号 |
-j | 读取指定部分的偏移量,而不是绝对地址 |
-p | 每个地址信息单独占一行 |
参考示例:
查看文件名、行号和函数名相关信息:
llvm-addr2line -f -e File.so
查找指定的地址所对应的代码位置:
llvm-addr2line 0x00000000004005e7 -e test -f -C -s
例如:
llvm-addr2line -e libapplication.so 00003714 -f -C

ASan堆栈解析:




实际代码行映射关系:
70->29
71->30
72->31
73->32
sourceMap结构:

单个module构建产物sourceMaps.map为merge文件,实际包含该模块的所有文件的映射关系;每个json中key以编译构建产物的唯一路径作为主键,运行程序的abc中保留了对应的key信息,当运行时异常代码归属到该文件时输出信息为该key,sources为实际源码文件信息,用于异常堆栈还原源码;mappings为编码后的行列号映射表,每个文件有独立的映射关系。
下图是sourceMap中每个json的key的结构化处理过程,以“entry|har1|1.0.0|src/main/ets/pages/w.ts”为例,各字段含义如下。
以“|”为分隔符,entry是本模块oh-package.json5中的name,har1|1.0.0是依赖的har1包的oh-package.json5中的name和version(如果没有依赖包,则是本模块oh-package.json5中的name和version),src/main/ets/pages/w.ts是引用的源码文件路径。

混淆映射表:$ProjectPath\$ModuleName\build\$product\cache\default\default@CompileArkTS\esmodule\release\obfuscation\nameCache.json
{
"home/src/main/ets/homeability/HomeAbility.ets": {
"IdentifierCache": {
"#AbilityConstant": "AbilityConstant",
"#hilog": "hilog",
"#UIAbility": "UIAbility",
"#Want": "Want",
"#window": "window",
"HomeAbility#onWindowStageCreate#__function": "i"
},
"MemberMethodCache": {
"onCreate:10:16": "onCreate",
"onDestroy:18:20": "onDestroy",
"onWindowStageCreate:22:33": "onWindowStageCreate",
"onWindowStageDestroy:35:38": "onWindowStageDestroy",
"onForeground:40:43": "onForeground",
"onBackground:45:48": "onBackground"
},
"obfName": "home/src/main/ets/homeability/HomeAbility.ets"
},
"compileSdkVersion": "5.0.0.25",
"entryPackageInfo": "home|1.0.0",
"PropertyCache": {
"integratedHsp": "i",
"asanClick": "j",
"Index_Params": "m",
"testNapi": "o",
"Index": "t",
"testObfuscation": "g2"
}
} "obfName": "home/src/main/ets/pages/a.ts"
变量名分为两类:普通变量、类方法变量。
普通变量映射关系的格式如下:
originalvariablename : obfuscatedvariablename
类方法变量映射关系的格式如下:
/*--------------------------key---------------------------------- : -----------value----------*/ originalmethodname: originalmethodstartline: originalmethodendline : obfuscatedmethodname
开启属性混淆时,成员方法映射关系的格式如下:
/*--------------------------key--------------------------------- : -----------value----------*/ originalmethodname:originalmethodstartline:originalmethodendline : obfuscatedmethodname
未开启属性混淆时,成员方法映射关系的格式如下:
/*--------------------------key------------------------------------- : -----------value----------*/ originalmethodname : originalmethodstartline : originalmethodendline : originalmethodname
属性名映射关系格式如下:
/*--------key------- : -----------value----------*/ originalpropertyname : obfuscatedmethodname
异常堆栈如下:
Pid:58348
Uid:20020156
Reason:RangeError
Error name:RangeError
Error message:The number cannot be converted to a BigInt because it is not an integer
Stacktrace:
Cannot get SourceMap info, dump raw stack:
at g2 (home|home|1.0.0|src/main/ets/pages/a.ts:6:6)
at getVersion (home|home|1.0.0|src/main/ets/pages/a.ts:2:2)
at anonymous (home|home|1.0.0|src/main/ets/pages/Index.ts:61:61) at g2 (home/src/main/ets/pages/tool.ts:7:27) at getVersion (home/src/main/ets/pages/tool.ts:2:30) at anonymous (home/src/main/ets/pages/Index.ets:23:40)
a.ts通过sourceMap还原为tool.ts。
"home|home|1.0.0|src/main/ets/pages/a.ts": {
"version": 3,
"file": "tool.ts",
"sources": [
"home/src/main/ets/pages/tool.ts"
],
"names": [],
"mappings": "AAAA,MAAM,CAAC,OAAO,UAAU,UAAU,IAAI,MAAM;IAC1C,IAAI,KAAM,IAAiB,CAAA;IAC3B,UAAW;AACb,CAAC;AAED,eAA2B,MAAM;IAC/B,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IACxB,OAAO,GAAG,CAAC;AACb,CAAC",
"sourceRoot": "",
"entry-package-info": "home|1.0.0"
} 查看混淆映射表:$ProjectPath\$ModuleName\build\$product\cache\default\default@CompileArkTS\esmodule\release\obfuscation\nameCache.json
"home/src/main/ets/pages/tool.ts": {
"IdentifierCache": {
"getVersion#res": "h2",
"#testObfuscation:6:9": "g2"
},
"MemberMethodCache": {},
"obfName": "home/src/main/ets/pages/a.ts"
} 该字段的IdentifierCache与MemberMethodCache中保存了方法名混淆前后的映射关系,对应格式为:"源码方法名:该方法起始行号:该方法结束行号":"混淆后方法名"。
源码方法名中的"源码方法名"代表上下级关系,故匹配后可以通过"#"保留最后名称。
第一条堆栈混淆后的方法名为"g2",若存在多个"g2"则需要通过行号范围过滤,故利用上述字段对该方法名进行还原:
"#testObfuscation:6:9": "g2"
at testObfuscation (home/src/main/ets/pages/tool.ts:7:27) at getVersion (home/src/main/ets/pages/tool.ts:2:30) at anonymous (home/src/main/ets/pages/Index.ets:23:40)