# 背景

为提高版本的稳定性,在app灰度时做asan测试

其中一个技术点是实现asan的无崩溃检测方案。但按文档操作发现不生效。

正常ASAN的配置方法查看 <https://developer.android.com/ndk/guides/asan>

为了实现asan的无崩溃测试方案,跟着文档开启halt_on_error=0,但是测试中发现

halt_on_error=0不生效,故深入调查。可直接看结论

# 文档的错误说明

阅读文档说明

<https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html>

要开启无崩溃方案,需要在so编译时添加sanitize-recover参数,但文档说默认是打开recover的

![](https://tech-proxy.bytedance.net/tos/images/1644921785042_7fa914498481debf54cd98863cee2b49)

<https://github.com/google/sanitizers/wiki/AddressSanitizerFlags>

但是配置这编译参数发现还是有区别

## 不同参数的汇编差异对比

在demo中编译过asan so,看看不同参数的区别

## noasan

没有开启asan工具,测试代码不崩溃,没有插桩,没有主动abort的代码

![](https://tech-proxy.bytedance.net/tos/images/1644921784953_0da4c81f6e7ea8925c9b654570629f05)

## asan-recover

demo加了sanitize-recover,发现也会崩溃

![](https://tech-proxy.bytedance.net/tos/images/1644921784855_5c7b8ead7edb9a791e22e65618fac3ee)

这个崩溃和文档说明不符,明明是跳转到__asan_report_load1_noabort函数了,为什么还崩呢。

![](https://tech-proxy.bytedance.net/tos/images/1644921784848_d562dc8323e35c09d45bc0614af675dd)

跟着崩溃堆栈找到就运行了41行,但是我们不应该跑到41行的,因为halt_on_error已经被设置为0了,检查发现是wrap.sh没有打包到apk里,导致值配置失效。

解决了这个问题后后面还崩,反编译看汇编代码

![](https://tech-proxy.bytedance.net/tos/images/1644921784860_94d2f88c87303fb0d8f9d4478c8cbe25)

原来写文件失败也会崩

配置正确的路径后-fsanitize-recover=address终于能按正确的逻辑继续跑asan而不崩溃了 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer")

![](https://tech-proxy.bytedance.net/tos/images/1644921785070_5a4fc670f512a510502fe273bab8739d)

### 下面是汇编推导找到不崩溃分支的代码过程(可以忽略)

#### 新版本配不配置cover参数都崩溃,从0行开始定位

demo崩溃堆栈,加了cover参数

```
    #00 pc 000000000002237c  /system/lib64/libc.so (abort+116)
    #01 pc 000000000008ce88  /lib/arm64/libclang_rt.asan-aarch64-android.so BL .abort
    #02 pc 0000000000092d40  /lib/arm64/libclang_rt.asan-aarch64-android.so BL _ZN11__sanitizer5AbortEv
    #03 pc 0000000000079b84  /lib/arm64/libclang_rt.asan-aarch64-android.so BL _ZN11__sanitizer3DieEv
    #04 pc 000000000007abb8  /lib/arm64/libclang_rt.asan-aarch64-android.so BL _ZN6__asan19ScopedInErrorReportD2Ev 
    #05 pc 0000000000065f30  /lib/arm64/libclang_rt.asan-aarch64-android.so (__asan_memset+552)
    #06 pc 0000000000013d2c  /lib/arm64/libmodule-lib.so (_Z3usrv+132)
    #07 pc 0000000000013de0  /lib/arm64/libmodule-lib.so (Java_com_example_mylibrary_Module_loadttf+108)
```

手动转了指令

下面就是找到__asan_report_load1_noabort崩和不崩的判断分支

#### _ZN11__sanitizer3DieEv

看堆栈符号就是79b84里出事,有die字眼

编译一路看下来,在跳转 _ZN11__sanitizer5AbortEv 时有个 CBNZ的判断,是不是不跳92d40就可以不崩了呢?为什么要跳呢,往上找逻辑

![](https://tech-proxy.bytedance.net/tos/images/1644921785005_b3485581489a019534501dd5796f76c4)

以防万一,CBNZ翻书看定义

![](https://tech-proxy.bytedance.net/tos/images/1644921784986_537042d307946a967f7cfdc2ae33ffa8)

在这里就是对比W9是不是0,不是0就跳到崩溃代码

那现在是w9不为0了,那w9是啥

![](https://tech-proxy.bytedance.net/tos/images/1644921785257_b405fb9b3606412d8d013a44f24f6451)

地址上看是个栈内存,搜到内存没有打印

x8是去读取common flags配置

![](https://tech-proxy.bytedance.net/tos/images/1644921784949_f3182415965af9773be74d905e1d1f40)

![](https://tech-proxy.bytedance.net/tos/images/1644921785275_4999df1cc2807d7a93090096b5d1aaf1)

这块逻辑太难推,继续努力

![](https://tech-proxy.bytedance.net/tos/images/1644921785452_d728f8e65ad0d5a4ae7573c30c3dc248)

手推

.text:0000000000092D00 ADRP X8, #_ZN11__sanitizer21common_flags_dont_useE_ptr@PAGE

.text:0000000000092D04 LDR X8, [X8,#_ZN11__sanitizer21common_flags_dont_useE_ptr@PAGEOFF]

拿的就是 common_flags_dont_use 的指针

LDRB W9, [X8,#(byte_553CAC - 0x553BE8)] = LDRB W9, [X8,0xC4]

C4=196

就是拿common_flags_dont_use偏移 C4位的变量

这个变量是什么,和版本的类有关

我拿21版本看看

<https://code.woboq.org/llvm/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp.html#__sanitizer::common_flags_dont_use>

![](https://tech-proxy.bytedance.net/tos/images/1644921784896_af57777e0a23807c52e5756996c2da3f)

```
namespace __sanitizer {
19
20enum HandleSignalMode {
21  kHandleSignalNo,
22  kHandleSignalYes,
23  kHandleSignalExclusive,
24};
25
26struct CommonFlags {
27#define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name;
28#include "sanitizer_flags.inc"
29#undef COMMON_FLAG
30
31  void SetDefaults();
32  void CopyFrom(const CommonFlags &other);
33};
34
35 // Functions to get/set global CommonFlags shared by all sanitizer runtimes: 36extern CommonFlags common_flags_dont_use;
37inline const CommonFlags *common_flags() {
38  return &common_flags_dont_use;
39}
40
41inline void SetCommonFlagsDefaults() {
42  common_flags_dont_use.SetDefaults();
43}
44
45 // This function can only be used to setup tool-specific overrides for 46 // CommonFlags defaults. Generally, it should only be used right after 47 // SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and 48 // only during the flags initialization (i.e. before they are used for 49 // the first time). 50inline void OverrideCommonFlags(const CommonFlags &cf) {
51  common_flags_dont_use.CopyFrom(cf);
52}
```

<https://code.woboq.org/llvm/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc.html>

这个就是配置变量,说真手推我是没信心确认是哪个,太大了

![](https://tech-proxy.bytedance.net/tos/images/1644921785320_69980a77401720552175602b46cb32a3)

![](https://tech-proxy.bytedance.net/tos/images/1644921785118_21b0aabb109a1abb17974ce0086b5801)

看分支是abort和exit的分支变量,

我可以确认这里没有halt_on_error变量。到这个_ZN11__sanitizer3DieEv函数里就应该是必崩的了,那往上一个堆栈找

#### __asan::ScopedInErrorReport::~ScopedInErrorReport

79A38

![](https://tech-proxy.bytedance.net/tos/images/1644921784989_d207713c84df215dacb3035b53bbc852)

![](https://tech-proxy.bytedance.net/tos/images/1644921784983_1336f28154ff8db72c18c4759cc841e8)

拿锁成功就会跑到abort代码,另外一条路是做unmap等兼容性操作,一般不跑,这样的话就需要再往上看一层

#### __asan_memset

65f30

![](https://tech-proxy.bytedance.net/tos/images/1644921785159_d014d9679bd51bad70c7c03fb8a381fe)

终于看到能跳出来的分支了,看看什么条件才能跳出来

1 asan还在初始化时不崩

![](https://tech-proxy.bytedance.net/tos/images/1644921784946_ef3290514deb136291879248ab4f1de8)

2

__asan28asan_flags_dont_use_directly

![](https://tech-proxy.bytedance.net/tos/images/1644921784943_e62d5ceef9f0b47d7e7b3e331ca9fa94)

__asan_region_is_poisoned 这里有个跳转,判断有没有破坏asan的区域,破坏了就会崩

也就是说不能跑到

由于手推真辛苦,效率也低,安装了反编译插件提高效率

#### __asan_report_load1_noabort

![](https://tech-proxy.bytedance.net/tos/images/1644921784853_8063c73881d81dc49d6595442c9b1366)

#### ReportGenericError

![](https://tech-proxy.bytedance.net/tos/images/1644921784870_898597f6afd63e26edc7d955560feb5e)

#### __asan::ScopedInErrorReport::~ScopedInErrorReport

![](https://tech-proxy.bytedance.net/tos/images/1644921784801_0debd6b3eb85b880591d5bb245899c8c)

终于找到了,看到这个字眼和文档相关就引起了注意,再看分支判断就是崩和不崩的关键所在

## asan

开启asan工具测试代码崩溃

![](https://tech-proxy.bytedance.net/tos/images/1644921784838_56caf76aa9d912d4e341524927d97e99)

插桩的函数已经不一样了,实现就是会崩掉

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fsanitize=address -fno-omit-frame-pointer")

![](https://tech-proxy.bytedance.net/tos/images/1644921784992_eb75a163d310b036e694f806f8c007ca)

# 结论

官方文档有误,无崩溃方案so编译时需要配置sanitize-recover参数

*SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer")*

配置 wrap.sh脚本增加 halt_on_error=0 参数

其他配置和正常的ASAN一样,就可以实现无崩溃的ASAN测试了

# 参考文档

正常ASAN的配置方法查看 <https://developer.android.com/ndk/guides/asan>

文档中的ida工具使用和基础知识 [运行时修改so汇编代码的方法](https://bytedance.feishu.cn/wiki/wikcnQ6vvLyxfKwtnVfeU4WAbOe)

ASAN中无崩溃测试方案实现相关推荐

  1. 软件测试培训之十个无脚本测试方案

    1.自然语言处理(NLP) 目前,一些最新的无脚本自动化测试工具能够通过采用NLP语法,来创建各种测试用例.就像编写简单的英语语句一样,用户可以轻松地实现测试用例的自动化.此类工具一般会带有AI驱动的 ...

  2. rainmeter皮肤_关于雨滴桌面(rainmeter)中无界大神的仿WMP外星人播放器修改方案...

    关于雨滴桌面(rainmeter)中无界大神的仿WMP外星人播放器修改方案 很多人都在用rainmeter雨滴桌面,因为它炫酷的外表和开源的内核.当然也有很多小白想要入坑尝试一下这款软件.那么本人今天 ...

  3. APP测试中压力和性能的差别以及测试方案攥写

    压力测试:对系统不断施加压力的测试,是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试.例如测试一个应用段时间内大量用户涌入的负荷下,何时系统的响应会退化或失败. 性能 ...

  4. SfxMCP基于onvif协议H5无插件直播方案中onvif设备的接入方法 - sfxlab

    SfxMCP基于onvif协议H5无插件直播方案中onvif设备的接入方法 - sfxlab SFX流媒体解决方案基于安防行业推出了以媒体汇聚平台(SfxMCP)为主,以媒体分发平台(SfxMDP)和 ...

  5. SfxMCP基于rtsp协议H5无插件直播方案中RTSP设备的接入方法 - sfxlab

    SfxMCP基于rtsp协议H5无插件直播方案中RTSP设备的接入方法 - sfxlab SFX流媒体解决方案基于安防行业推出了以媒体汇聚平台(SfxMCP)为主,以媒体分发平台(SfxMDP)和媒体 ...

  6. 测试方案,测试计划文档中的内容

    当时我们公司的测试方案主要是从七个方面进行的: 1 文档标识:是对被测系统的简单描述 2 概要:主要是针对被测系统的介绍以及包含的主要功能业务,测试的目的,测试的范围,测试环境的描述以及测试所需的相关 ...

  7. Android专项测试之崩溃测试(CPU)

    Android专项测试之崩溃测试(CPU) 崩溃问题类型 ❖ ANR:❖ 主线程5s内没响应 ❖ Java Crash: ❖ 未捕获的android vm异常 ❖ Native Crash: ❖ 未处 ...

  8. 1-性能测试方案与流程剖析

    1.性能测试需求 有效的性能测试能给研发.运维团队提供有效的容量规划能力,系统风险识别.系统瓶颈识别.性能调优指导.保障尽量避免系统崩溃问题的发生. 良好的容量规划能力+性能调优能力=为老板省钱 2. ...

  9. 方形物体绕中心旋转的扭力_转轴扭力测试方案

    什么是转轴扭力?转轴是连接产品能够承受弯矩以及承受扭矩的轴:扭力,指扭转物体使物体产生形变的力.扭力计施力于轴上或旋转臂所产生之旋转力:力臂长x磨擦力量之大小为扭力值. 转轴可分为无扭力式和扭力式: ...

  10. WEB网站压力测试方案 压力测试如何换算并发用户数

    http://wenku.baidu.com/view/bedf1a93daef5ef7ba0d3c29.html 压力测试通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大的服务级别 ...

最新文章

  1. Python使用PIL将png图片转化为jpg图片
  2. mysql低级知识坑
  3. 算法 求和为n的连续正整数序列 C
  4. 如何设计一个牛逼的API接口
  5. FatFs源码剖析(2)
  6. Windows Server 2008 R2之活动目录回收站
  7. 【英语学习】【Level 07】U06 First Time L1 My very first trip
  8. Java 经典面试题 —— 性能与安全
  9. 谈谈我在自然语言处理入门的一些个人拙见
  10. 算法4-中兴捧月杯热身赛1素数判断-热身赛2亲和串-热身赛3旅游路线-
  11. 栈和队列有什么区别、以及他们的共同点
  12. 带管理职位面试中遇到的常见经典问题的回答
  13. vue echarts柱状统计图,多组数据对比
  14. 计算英文句子中有多少单词?
  15. android好用的NFC软件,5个有用的NFC应用程序为Android,以利于NFC | MOS86
  16. 移动端苹果安卓卓适配
  17. PayPal取消了连连支付快捷提现,我是如何提现到国内的?
  18. ansible 学习
  19. 真实孔径雷达——东方至远
  20. 从站寄存器EEPROM内容解析之SII(Slave Information Interface)

热门文章

  1. java+vue+onlyoffice的简单集成
  2. linux alarm函数clock,linux c之alarm函数的使用,定时器的实现
  3. 如何用python画帆船_简单几步,100行代码用Python画一个蝙蝠侠的logo
  4. 参与openEuler社区不到1年,我成为了社区Maintainer……
  5. (转)ICO泡沫:8万本金赚套房子和宝马 几分钟十几万没了
  6. 计算机产品可以进项抵扣,企业购入的软件产品可以全额抵扣进项税吗?
  7. DAOS整体设计分析 (二)
  8. 网易微专业java高级笔记_网易前端微专业------页面架构笔记
  9. Ecshop各个页面文件介绍,主要文件功能说明
  10. 阅读器android工程,一种简单的纯粹——全球首款 EINK屏 安卓手机 BOOX E43 工程机测试体验...