iOS写一个MallocStackLogging日志离线分析前言最近看了自己搞一个MemoryGraph工具行不行?

本着学习心态,去简单实现一下mallocstacklogging日志的离线分析,同时记录一下本次遇到的问题。个人水平有限,代码仅供参考。

除了项目代码以外,MallocStackLogging文件是我从自己的越狱iPhone7提取出来的系统MallocStackLogging动态库,可以拖进Hopper分析。libmalloc-166.251.2是我加了注释的源码。

离线解析日志文件,需要知道日志文件在哪里,日志文件的数据是以什么格式保存的

其实文中有提到,日志文件是放在沙盒的tmp目录下的。不过,还是要自己探究一下。

经过测试,当选择为LiveAllocationsOnly时是不生成日志的。(原因是libmalloc源码中就是这么写的)。当选择为AllAllocationandFreeHistory的时候,

externboolean_tturn_on_stack_logging(stack_logging_mode_typemode);externvoidturn_off_stack_logging(void);我决定从两个已知的开关方法入手。翻阅源码libmalloc-317.140.5得知libmalloc都是调用的MallocStackLogging.framework的方法

LoadtheMallocStackLogginglibraryandregisteritwithlibmallocboolean_tmalloc_register_stack_logger(void);

扔到Hopper里瞅瞅。

整个库其实并不大,符号也不多。我看到了一些感兴趣的符号,比如_create_log_file。

那下一步呢?不会要真的分析汇编吧

遇事不决,github搜一波

在低版本的libmalloc库中,是有源码的。

以下的分析都是基于libmalloc-166.251.2版本的。之后libmalloc-283就不存在这些代码了。

所以,我有一个大胆的想法:

你们什么都没干,只是把代码移到了MallocStackLogging.framework中对吧?(其实是改了的)

我把加了注释的libmalloc-166.251.2源码也放入了代码文件中,里面有我的很多注释和蹩脚的翻译。如果对源码感兴趣的朋友,可以翻阅。希望对你有帮助。

比如这样的注释。

turn_on_stack_logging函数

turn_on_stack_logging __prepare_to_log_stacks(false);//初始化pre_write_buffers __create_uniquing_table//创建用于保存内存分配堆栈的哈希表uniquing_table create_log_file//创建日志文件 index_file_descriptor//静态变量日志文件句柄 __stack_log_file_path__//全局变量日志文件地址 malloc_logger=__disk_stack_logging_log_stack; __syscall_logger=__disk_stack_logging_log_stack;缩进表示调用关系。可以看到MallocStackLogging.framework也是利用两个勾子函数malloc_logger和__syscall_logger来实现内存分配日志信息的记录的。核心是__create_uniquing_table函数,这个函数会用来创建存放分配堆栈信息哈希表backtrace_uniquing_table。

假如我们有这样两个函数调用堆栈:

funcCfuncDfuncBfuncBfuncAfuncA他们在哈希表中的存放是这样的:上才艺!

为了方便理解,我把图画成这样了。其实parent存放的是父节点的hash值也就是下标。更多详细资料可以参考函数enter_frames_in_table。我在其中加了很多注释。

其实我们只需要知道一个事情,哈希表backtrace_uniquing_table存放了堆栈信息。最后返回的stack_id就是最上层调用指令(比如funcCfuncD)的hash值也是下标。有一个stack_id,我就可以一连串地拿到funcCfuncBfuncA。

一个stack_id对应一个堆栈列表信息。

在__prepare_to_log_stacks函数中,我还看到了

turn_off_stack_logging函数

turn_off_stack_logging malloc_logger=NULL; __syscall_logger=NULL; stack_logging_enable_logging=0;这个函数就没什么好讲了,把两个勾子置空。

__disk_stack_logging_log_stack函数

但是,根据我看源码的结果。树的操作只会在精简模式下进行,而且入树的是stack_id和分配的内存地址。不知道是不是因为我看的是libmalloc库老版本的缘故。

什么数据?stack_logging_index_event

typedefstruct{ uintptr_targument; uintptr_taddress; uint64_toffset_and_flags;//top8bitsareactuallytheflags!}stack_logging_index_event;address存放是分配或者释放的内存地址(经过伪装处理)argument存放是内存的大小offset_and_flags就有些复杂了。经过一堆宏的位运算。

(16个0_stack_id的低48位)|(type_flags的低8位_56个0)|(type_flags的24-32位_48个0)=type_flags的低8位_type_flags的24-32位_stack_id的低48位=共64位offset_and_flags的64位存放了stack_id和type_flags和user_tag

那么目前为止,我知道了日志文件中存放的是一个个stack_logging_index_event结构体。那么通过解析日志文件,拿到stack_logging_index_event后,我就能知道address对应的stack_id,再拿stack_id去查堆栈哈希表,就能拿到分配或释放这块内存的堆栈信息。

接下来就是写代码了。

解析出来的数据,怎么看都不对劲。

我们来看看用系统api解析出来的数据是什么样子的。

externkern_return_t__mach_stack_logging_enumerate_records(task_ttask,mach_vm_address_taddress,voidenumerator(my_mach_stack_logging_record_t,void*),void*context);voidenumerate_records_hander(my_mach_stack_logging_record_trecord,void*context){NSString*type=typeString(record.type_flags);NSLog(@"%@size:%llustackid:0x%llxaddress:%p",type,record.argument,record.stack_identifier,(void*)record.address);}-(void)test_enumerate_records{if(!_isOpen){NSLog(@"还没有打开日志开关呢");return;}__mach_stack_logging_enumerate_records(mach_task_self(),NULL,enumerate_records_hander,NULL);}结果是

这个数据,看起来就正常多了。

问题出在哪里呢?我试图去找私有库的头文件,了解真正的结构,未果。这个时候,我想起《自己搞一个MemoryGraph工具行不行?》文中提到,日志文件的内容是4个数一组的。这个跟我看源码的结果是不一致。不过不妨一试。其实第一次解析时,有一个细节。就是第一条数据看上去像是一点点正常。

修改一下结构体:

//第二次错误尝试typedefstruct{uint64_targument;uint64_taddress;uint64_toffset_and_flags;uint64_twhat;}wrong_stack_logging_index_event64;结果:

看起来address和size是对了。stack_id和type_flags不对。

这里,我也思考一下,什么情况下会需要修改结构体?1.增加新功能了2.成员的类型不够存了,需要改变结构......

所以,会不会offset_and_flags被拆出来了?那就不需要那么多位运算了。

验证一下:

好了,再次修改结构体。

//这是现在的版本了typedefstruct{uint64_targument;uint64_taddress;uint64_toffset;uint64_tflags;}test_stack_logging_index_event64;这一次尝试就不贴图了,结果和系统api解析出来的一致。

获取到stack_id。我就可以查哈希表了。

接下来,用到了很多系统库的api。都可以在libmalloc-317.140.5库中的stack_logging.h文件中找到。

到此,解析日志文件,查询哈希表的逻辑就通了。

至于离线解析,系统api中已经提供哈希表的序列化和反序列化方法。

其实在看源码的过程中,我一直在思考这个功能的使用场景。利用系统开放的两个勾子,来记录内存分配释放的堆栈信息的功能。其实在matrix-iOS和OOMDetector库中都已经见识过了。这两个库也许也是参考了官方的实现方式。甚至于,在matrix-iOS的wiki中也写到__syscall_logger勾子是有审核风险的。

我真的能通过这个功能,收集用户手机上的日志信息吗?

就算可以。这么巨量的日志文件,又如何上传到我们的服务器呢?用户的手机磁盘空间是非常宝贵的。不然iOS系统也不会用内存压缩的方式替换内存交换了。那是不是意味着,只能在开发阶段使用?

libmalloc-317.140.5的stack_logging.h中的大量哈希表的操作方法也被标记为了过期。

THE END
1.学堂在线数据挖掘网课答案mob64ca12d70c79的技术博客数据分析:通过不同的算法来分析数据并提取有价值的模式。 结果评估:评估模型的效果,选择最佳模型。 结果呈现:通过可视化工具展示分析结果。 下面是数据挖掘流程的示意图: 数据采集数据预处理数据分析结果评估结果呈现 实际代码示例 在这个示例中,我们将使用Python进行简单的数据分析。我们假设有一个包含客户消费数据的CSVhttps://blog.51cto.com/u_16213327/12894449
2.大数据在线分析近线分析与离线分析近线分析介于在线分析和离线分析之间,它允许数据处理和分析在短时间内完成,但不一定要求实时处理。近线分析的目标是在可接受的延迟范围内提供分析结果。 特点 准实时性:数据处理延迟通常在几分钟到几小时内,具体取决于应用场景。 灵活性:相比在线分析,近线分析可以处理更复杂的数据处理任务。 https://blog.csdn.net/weixin_44231544/article/details/142467700
3.在线分析并且,有些目标物不稳定,不便于长期贮存,离线检测中从采样到送检的这段时间有可能发生变化,导致检测结果与实际情况的差异,这时候在线检测就体现出它的优势。离线分析通常只是用于产品(包括中间产品)质量的检验,而在线分析可以进行全程质量控制,保证整个生产过程最优化。https://www.360doc.cn/article/1081018318_1081018318.html
4.离线分析离线分析 就是生产流取样并将样品送到便于分析器分析的某一分析地点进行的分析 离线分析 analysis off-line 从生产流取样并将样品送到便于分析器分析的某一分析地点,此处并不与生产装置直接相连,也可以说分析器位于远处的实验室。https://baike.baidu.com/item/%E7%A6%BB%E7%BA%BF%E5%88%86%E6%9E%90/12730463
5.OLAP在线分析引擎介绍及应用嘲腾讯云开发者社区OLAP(Online Analytical Processing,在线分析处理)引擎是一种专为复杂数据分析和报告设计的系统,它使用户能够从多个角度快速地对大量数据进行交互式分析。 核心原理:1. 多维数据模型:OLAP的核心是一个多维数据模型,通常体现为数据立方体(Data Cube)。数据立方体由维度(Dimensions)、层次(Levels)和度量(Measures)组成。维度https://cloud.tencent.com/developer/article/2424720
6.总有机总有机碳toc分析仪在线离线有什么特点?怎么选用?大家在使用总有机总有机碳toc分析仪的时候,不了解什么是在线监测,什么是离线检测?应该怎么选用?下面有我为大家介绍一下:如果是实验室使用,选择离线检测,如果是测流动的水,比如连接管道,选择在线检测。总有https://www.chem17.com/tech_news/detail/3008773.html
7.用手机导航是个坑细说麻烦在哪里?GPSGPS新闻离线版软件优缺点分析 那么看到了在线电子地图导航的一些缺陷之后,我们最快能够相当的解决办法就是安装一款离线版导航软件。其实行货手机中偶尔会附赠一些离线版的导航软件供用户使用,但是不一定好用,所以很多用户更加倾向于选择比较熟悉的凯立德、道道通、高德等导航软件。 https://gps.zol.com.cn/239/2399981_all.html
8.啥是离线数据处理什么是离线数据处理离线数据处理是指在数据存储和处理过程中,将数据从其原始来源中移除,并在离线环境中进行处理和分析的过程。这种处理方式通常用于对历史数据进行分析,以便找出趋势、模式和其他有价值的信息。 离线数据处理的主要优势包括: 更大的数据处理能力:离线处理可以使用更大的计算资源和存储空间,以处理大量的数据。 https://cloud.tencent.cn/developer/information/%E5%95%A5%E6%98%AF%E7%A6%BB%E7%BA%BF%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86-video
9.什么是离线大数据分析帆软数字化转型知识库什么是离线大数据分析 离线大数据分析是指在不依赖实时数据流的情况下,对收集到的大规模数据进行批处理分析的过程,高效、灵活、经济是其显著特点。高效是指能够在较短时间内处理大规模数据,灵活则是指可以根据需求进行多种分析和处理,经济主要体现在可以利用相对低廉的硬件资源进行大规模数据处理。高效是离线大数据分析的https://www.fanruan.com/blog/article/46659/
10.全面解析十七种数据分析方法,具象数据分析思维!在当今数据驱动的商业环境中,数据分析已经成为了企业获取竞争优势的关键工具。无论是为了优化运营效率,提高客户满意度,还是推动产品创新,企业都需要通过分析大量数据来做出明智的决策。数据分析方法多种多样,每种方法都有其独特的定义和用途,适用于不同的业务场https://mp.weixin.qq.com/s?__biz=MzU3OTg5Njk2NA==&mid=2247496232&idx=1&sn=ed89f750c935267d4a22d9e57fe28c7c&chksm=fd5da1c3ca2a28d581a1063b691e029137d86bbb2a7640e3a50bbd3dc6553a46ebbfcb51cda1&scene=27
11.在线气相色谱仪软件中的在线和脱机模式的功能比较在线气相色谱仪是一种常用的化学分析仪器,其软件系统在实验过程中起到至关重要的作用。其中,在线模式和脱机模式是两种常见的工作模式。http://www.jinghe17.com/huaijun-News-1510187/
12.一文入门Go的性能分析go tool pprof 可以对采集到的 CPU、内存等信息进行分析,go tool trace 则是对采集的 trace 信息进行分析。 2.1 在线分析 go tool pprof 既可以对采集到的离线数据进行分析,也可以是结合上面的 pprof Http 接口,直接在线上进行分析,比如分析程序的内存使用情况: https://xie.infoq.cn/article/58f7ed6c58b97ed01d859f2e3
13.笔记——Dragoon:ahybridandefficientbigtrajectory在本文中,我们提出了一个混合和高效的框架,称为dragoon,基于Spark,以支持离线和在线大轨迹管理和分析。该框架具有一个可变的弹性分布式数据集模型,包括RDD共享、RDD 更新和RDD镜像,它支持历史和流轨迹的混合存储。它还包含一个实时分配器,能够有效地分发轨迹数据,并支持离线和在线分析。因此,Dragoon提供了一个混合分析https://www.jianshu.com/p/e2a4474d8b98
14.NanoscopeAnalysis官方版(AFM数据离线分析软件)下载v1.5.0.0在实验室做研究的各位用户一定需要一款软件帮助分析各种数据,尤其是一些做秘密研究的更是不能够在有网络的情况下使用,这款nanoscope analysis就是非常不错的AFM离线数据分析软件,如果是一位实验室工作人员,那么一定知道AFM是什么,如果你是不小心点进来的那么小编告诉你,这就是原子力显微镜,是众多现代实验室必备的一个东https://www.32r.com/soft/12163.html
15.关于DataLake的概念架构与应用嘲介绍极客公园支持多种分析引擎 可以通过多种引擎对湖上数据进行分析计算,例如离线分析、实时分析、交互式分析、机器学习等多种数据分析场景。 计算可扩展性 计算引擎需要具备可扩展的能力,具备随数据量不断变大、业务不断增长的弹性数据分析的能力。 存储与计算分离(云上) https://www.geekpark.net/news/303245
16.JProfiler帮助文档分析一个应用程序,JProfiler有两种完全不同的方式:默认情况下,你在连接JProfiler GUI的情况下进行分析。 JProfiler GUI为你提供了开始和停止记录按钮,并显示所有记录的分析数据。 在某些情况下,你想在没有JProfiler GUI的情况下进行分析,并在以后分析结果。对于这种情况,JProfiler提供离线分析。 离线分析允许你使用https://www.ej-technologies.com/resources/jprofiler/help_zh_CN/doc/main/offline.html
17.大显身手!固态拉曼分析仪轻松应对各类分析应用(文末有礼)在过程分析技术中有四种主要的分析类型:在线,线上,旁线和离线。新型过程分析技术(PAT)对准确性和可靠性有更高的要求。对 PAT 而言,最 重要的也许就是不受位置和接口限制,使过程分析具有充分的适应性。 本文介绍了在线,线上,旁线和离线四种采样方式的过程分析类型中,固态拉曼系统如何提供快速、连续和准确的成分分https://www.yiqi.com/news/detail_15588.html