2015-10-01 16:46:37 WackoSix 阅读数 2713

CSV全称 Comma Separated values,是一种用来存储数据的纯文本文件格式,通常用于电子表格或数据库软件。用Excel或者Numbers都可以导出CSV格式的数据。


CSV文件的规则

   1. 可含或不含列名,含列名则居文件第一行。 

   2. 一行数据不垮行,无空行。

   3. 以半角符号,作分隔符,列为空也要表达其存在。

   4. 列内容如存在,,则用“”包含起来。

   5. 列内容如存在“”则用“”“”包含。

   6. 文件读写时引号,逗号操作规则互逆。

   7. 内码格式不限,可为ASCII、Unicode或者其他。

以上介绍来自于网络!


//保存一个字典

-(void)writeDict:(NSDictionary *)dict forFirst:(BOOL)first{
    
    NSMutableString *str = [NSMutableString  string];

    //第一次写入字典的key值
    if (first) {
        
        for (NSString *key in dict.allKeys) {
            //"," 换列
            [str appendString:[NSString stringWithFormat:@"%@,",key]];
        }
        
    }
    //换行
    [str appendString:@"\n"];
    
    for (NSString *value in dict.allValues) {
        
        [str appendString:[NSString stringWithFormat:@"%@,",value]];
    }
    
    [self writeData:[str dataUsingEncoding:self.encode]];
    
    isFirst = false;
    
}

//保存一个数组

-(void)writeArray:(NSArray *)arr{

    id element = arr[0];
    
    if ([element isKindOfClass:[NSString class]]) {
        
        NSMutableString *str_M = [NSMutableString string];
        
        for (NSString *str in arr) {
            
            [str_M appendString:[NSString stringWithFormat:@"%@,",str]];
        }
        
        [str_M appendString:@"\n"];
        
        [self writeData:[str_M dataUsingEncoding:self.encode]];
    }
    else if ([element isKindOfClass:[NSDictionary class]]){
        
        isFirst = true;
        
        for (NSDictionary *dict in arr) {
            
            [self writeDict:dict forFirst:isFirst];
        }
    
    }
    else if ([element isKindOfClass:[NSArray class]]){
        
        for (NSArray *subArr in arr) {
            
            [self writeArray:subArr];
        }
    
    }
    
}


完整代码:

http://download.csdn.net/detail/wackosix/9151755



2018-07-09 15:25:33 Coco__D 阅读数 1172

符号表文件.dSYM实际上是从Mach-O文件中抽取调试信息而得到的文件目录,实际用于保存调试信息的文件是DWARF,其出身可以从这篇文章了解。

这个是我T9项目导出的文件路径

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/donglizheng/Library/Developer/Xcode/DerivedData/T9-assomxyruqaaigdwvwpkrmuokreu/Build/Products/Debug-iphoneos/T9.app/T9 -o T9.dSYM

这个路径是我在APP中的路径只需要把donglizheng换成自己电脑上的用户,然后把T9换成自己项目名称就可以导出了,如果想导出指定文件夹,那就先cd进入该文件夹,否则就在用户目录下

2016-08-22 19:51:04 xiaofei125145 阅读数 1410


xcode7.3   命令行工具 symbolicatecrash 在如下目录中

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources

接着需要三个文件

1. 崩溃日志xxx.crash:

Xcode->Window->Devices,选中设备,点击View Device Logs,然后可以看到好多日志,你可以根据时间来判断需要导出哪个日志,选中一个crash日志,右击选择Export log,然后就可以导出日志为aaa.crash,复制到crash文件。

2. 对应的 xxx.app.dSYM文件或者xxx.xcarchive :

打完包之后 注意 备份上述文件中的一个 (xxx.xcarchive  内部是包含 xxx.app.dSYM 的)。


3. symbolicatecrash工具:

/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash 


创建一个 crash文件目录吧,将上述三个文件放入 crash文件目录内。

然后,打开终端,cd到 crash文件目录(可以直接把文件拖到终端,就可以看到crash的路径)


可以用 dwarfdump --uuid xxx.app.dsym 命令先查看一下 dsym 的  uuid如下:

$ dwarfdump --uuid imeituan.app.dSYM
UUID: 846F3B51-91C1-30BD-B725-E77E6544C285 (armv7) imeituan.app.dSYM/Contents/Resources/DWARF/imeituan
UUID: 50232D18-8497-388F-B949-F4128F174C9A (arm64) imeituan.app.dSYM/Contents/Resources/DWARF/imeituan

将上面的 50232D18-8497-388F-B949-F4128F174C9A 去掉 中间横线后 和 

 和 xxx.crash 文件内部 Binary Images: 内对应 imeituan 段的 50232d188497388fb949f4128f174c9a 是一致的 。

Binary Images:
0x100038000 - 0x103607fff imeituan arm64  <50232d188497388fb949f4128f174c9a> /var/containers/Bundle/Application/C58C...


如果不一致,说明 dsym 文件 不匹配。



接着输入

./symbolicatecrash ./xxx.crash ./xxx.app.dSYM > new_symbol.cash

运行完上面这句可能会出现以下问题:Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 60.

解决方法是输入以下命令:export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

然后再重复执行

./symbolicatecrash ./xxx.crash ./xxx.app.dSYM > new_symbol.cash


没问题的话会 在  crash文件目录下 就多了个new_symbol.cash文件,这个就是符号化之后的crash文件了


2019-10-14 12:11:18 WangErice 阅读数 33

异常日志符号化

一般情况下如果我们可以通过Xcode来查看异常日志的话,获取到的异常日志都是符号化之后,可以直接查看并定位异常.但是如果在测试阶段需要从手机上导出异常日志,或者集成了第三方异常收集但是未能上传符号表到对应的后台等情况下就只能获取到未符号化的异常日志,这时候就需要对异常日志进行符号化.

生成符号表文件的前提

想要进行异常日志的符号化,前提就是保存了打包时生成的.dSYM文件,如果没有保存的话,符号化是不可能了,能靠经验去找了.

  • 在Generate Debug Symbols --> Apple Clang --> Code Generation中,设置Generate Debug Symbols为YES,模式是打开的;
  • 在Build Settings --> Build Options--> Debug Information Format中,将需要产生符号表的模式对应的值设置为DWARF with dsym File,将不需要产生符号表的模式对应值设置为DWARF.默认Debug模式下不产生符号表,Release模式不产生符号表.

符号表的存储位置

在默认情况下,符号表会存储在跟.xcarchive --> dSYMs文件夹下.

异常日志的符号化

准备

  • 新建一个文件夹CrashAnalysis,用来存储需要的文件;
  • 查找symbolicatecrash,并将该工具保存到新创建的文件夹CrashAnalysis中;

Xcode内置了符号化异常日志的工具symbolicatecrash.打开terminal输入下边的指令,通过find命令查找Mac上的symbolicatecrash位置:

find /Applications/Xcode.app -name symbolicatecrash -type f -print | grep iPhoneSimulator

然后将symbolicatecrash复制到CrashAnalysis中.

  • 将异常日志(.crash),符号表(.dSYM),复制到文件夹CrashAnalysis中;

日志符号化

对于异常日志的符号化,分为两种情况进行讨论:

  • 可以获取到完整的.crash系统异常日志,将全部异常日志一次性进行符号化;
  • 不能获取到完整的.crash系统日志(例如自定义异常获取时,只保留了调用堆栈等部分异常信息),只将需要的部分进行符号化.

(1) 将完整的系统异常日志全部符号化

  • 使用dwarfdump命令查看.dSYM文件的UUID;
dwarfdump --uuid xxx.dSYM
  • 查看.crash中的UUID是否与.dSYM中的UUID一致[在Xcode 11.0上发现每次打包会产生三个.dSYM文件,两个文件名以UUID开头,另外一个文件名以工程名开头];
  • 然后使用以下命令符号化日志
./symbolicatecrash xxx.crash xxx.app.dSYM > result.txt

可能会遇到

Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 69.

错误提示,如果遇到了,使用

//如果Xcode.app不是默认的名称,修改为自己Xcode名称即可
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

然后再次运行开始的命令,即可得到一个result.txt的符号化文件,在该文件中即可看到符号化之后的异常日志.

(2) 将局部异常日志符号化:

有时候我们并不能获取到完整的crash日志,或者只是想对一部分异常日志进行符号化.这时候也可以使用atos命令来进行.

例如自定义异常捕获方法时,我们只获取到了异常调用堆栈的信息:

0   libsystem_kernel.dylib        	0x0000000183d35348 0x183d14000 + 136008
1   libsystem_pthread.dylib       	0x0000000183e49354 0x183e46000 + 13140
2   libsystem_c.dylib             	0x0000000183ca4fd8 0x183c42000 + 405464
3   libc++abi.dylib               	0x0000000183708068 0x183706000 + 8296
4   libc++abi.dylib               	0x0000000183708210 0x183706000 + 8720
5   libobjc.A.dylib               	0x0000000183730810 0x183728000 + 34832
6   libc++abi.dylib               	0x000000018372054c 0x183706000 + 107852
7   libc++abi.dylib               	0x00000001837205b8 0x183706000 + 107960
8   libdispatch.dylib             	0x0000000183ba105c 0x183ba0000 + 4188
9   libdispatch.dylib             	0x0000000183ba86c8 0x183ba0000 + 34504
10  FrontBoardServices            	0x00000001868f1a04 0x1868b1000 + 264708
11  FrontBoardServices            	0x00000001868f16a8 0x1868b1000 + 263848
12  FrontBoardServices            	0x00000001868f1c44 0x1868b1000 + 265284
13  CoreFoundation                	0x00000001841c4358 0x1840da000 + 959320
14  CoreFoundation                	0x00000001841c42d8 0x1840da000 + 959192
15  CoreFoundation                	0x00000001841c3b60 0x1840da000 + 957280
16  CoreFoundation                	0x00000001841c1738 0x1840da000 + 948024
17  CoreFoundation                	0x00000001840e22d8 0x1840da000 + 33496
18  GraphicsServices              	0x0000000185f73f84 0x185f69000 + 44932
19  UIKit                         	0x000000018d68e880 0x18d61b000 + 473216
20  SymblicateCrashDemo             0x0000000100e77770 0x100e70000 + 30576
21  libdyld.dylib                 	0x0000000183c0656c 0x183c05000 + 5484

根据异常堆栈的调用信息可以看到,异常日志调用堆栈包含了四列信息:

  • 第一列是调用顺序序号:只不过时机的执行调用顺序是按照序号的逆序相同(栈);
  • 第二列是对应函数所属的Binary Images:包含了系统的库和自定义的库;
  • 第三列是实际调用的函数栈地址:调用的函数在内存中的栈地址(stack address);
  • 第四列是函数栈地址的偏移量表示法:使用函数所在的的Binary Image起始地址+偏移量来表示函数的栈地址.

目之所及,只有调用序号为20的这一行是自己编写代码中的调用,其余的都是系统Binary Image的调用,没有操作权限,所以不是我们关注的信息.

查看出错信息时,使用

atos -o {.dSYM中可执行文件的路径} -l {函数所在Binary Image起始地址} -arch {对应设备使用的指令集} {实际函数栈地址}

对于用例

20  SymblicateCrashDemo                       	0x0000000100e77770 0x100e70000 + 30576

来说(当前路径是/CrashAnalysis),

  • {.dSYM中可执行文件的路径}:SymblicateCrashDemo.app.dSYM/Contents/Resources/DWARF/SymblicateCrashDemo;
  • {函数所在Binary Image起始地址}:0x100e70000;
  • 所使用测试设备为iPhone XS,所以{对应设备使用的指令集}:arm64(在实际操作中可以获取到当前的设备类型映射到对应的指令集);
  • {实际函数栈地址}:0x0000000100e77770

执行:

atos -o SymblicateCrashDemo.app.dSYM/Contents/Resources/DWARF/SymblicateCrashDemo -l 0x100e70000 -arch arm64 0x0000000100e77770

输出:

__44+[ExceptionHandler registerExceptionHandler]_block_invoke (in SymblicateCrashDemo) (AppDelegate.m:38)

可以知道,出错的代码在Appdelegate实现文件第38行[ExceptionHandler registerExceptionHandler]中.

其他

其实对于局部异常日志符号化,还有一种方法,那就使用 dwarfdump命令,只不过这个命令使用起来比较麻烦.

ASLR (Address space layout randomization):

在iOS中为了防止缓冲区溢出攻击而采用了ASLR技术将可执行文件加载到设备内存.简单来说就是设备每次加载应用可执行文件到内存时,系统都会随机生成一个地址偏移量slide,然后在原来虚拟内存的基础上偏移slide得到得到一个加载可执行文件的起始地址,所以设备每次加载应用的可执行文件到内存的起始地址都是随机的.

在链接时,符号表地址产生了一个实际存储符号的虚拟地址,这个地址存储在应用的可执行文件中,可以使用(mach O文件中load commands中的text段虚拟地址)

otool -arch {设备指令集} -l {应用对应的二进制可执行文件} | grep "segname __TEXT" --after-context=1 | grep "vmaddr"

来进行查看.这个可执行文件在打包时会被存储在符号表的可执行文件中,保存在xxx.app.dSYM/Contents/Resources/DWARF/路径下.

针对用例中:

otool -arch arm64 -l SymblicateCrashDemo.app.dSYM/Contents/Resources/DWARF/SymblicateCrashDemo | grep "segname __TEXT" --after-context=1 | grep "vmaddr"

可以得到:

vmaddr 0x0000000100000000

这个地址就是编译时存储符号表内容的加载地址.

而在设备加载应用可执行文件到内存时会有一个加载起始地址,可以在完整的系统.crash中可以查看(设备加载的第一个Binary Image起始地址):

...
Binary Images:
0x100e70000 - 0x100f53fff SymblicateCrashDemo arm64  <02162b5d77623cd9b937e2633b497b2e> /var/containers/Bundle/Application/0DF5E4BF-6B77-4EC1-982F-1FCC2C2E0642/SymblicateCrashDemo.app/SymblicateCrashDemo
...

所以,有以上两个地址可以得到在加载时产生的随机偏移量slide:

0x100e70000 - 0x0000000100000000 = 0x0000000000e70000

而实际的调用函数地址为0x0000000100e77770,所以可以得到在符号表中的地址:

0x0000000100e77770-0x0000000000e70000 = 0x00000000100007770

上述slide的值也可以在加载时通过代码获取:

//该方法包含在mach-o/dyld.h声明中,使用时需要引入#import <mach-o/dyld.h>
intptr_t slide_address = _dyld_get_image_vmaddr_slide(0);

最后使用:

dwarfdump --arch {设备对应的指令集} --lookup {函数在符号表中的地址} {符号表(.dSYM文件)} 

dwarfdump --arch arm64 --lookup 0x00000000100007770 SymblicateCrashDemo.app.dSYM

得到结果:

0x00075e5a: Compile Unit: length = 0x000005a2 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00076400)

0x00075e65: DW_TAG_compile_unit
              DW_AT_producer	("Apple clang version 11.0.0 (clang-1100.0.33.8)")
              DW_AT_language	(DW_LANG_ObjC)
              DW_AT_name	("/Users/ericydong/Desktop/Exercises/CrashDemo/CrashDemo/AppDelegate.m")
              DW_AT_stmt_list	(0x00011e29)
              DW_AT_comp_dir	("/Users/ericydong/Desktop/Exercises/CrashDemo")
              DW_AT_GNU_pubnames	(true)
              DW_AT_APPLE_optimized	(true)
              DW_AT_APPLE_major_runtime_vers	(0x02)
              DW_AT_low_pc	(0x00000001000076a8)
              DW_AT_high_pc	(0x0000000100007998)

0x00075fac:   DW_TAG_subprogram
                DW_AT_low_pc	(0x0000000100007708)
                DW_AT_high_pc	(0x000000010000781c)
                DW_AT_frame_base	(DW_OP_reg29 W29)
                DW_AT_call_all_calls	(true)
                DW_AT_name	("__44+[ExceptionHandler registerExceptionHandler]_block_invoke")
                DW_AT_decl_file	("/Users/ericydong/Desktop/Exercises/CrashDemo/CrashDemo/AppDelegate.m")
                DW_AT_decl_line	(33)
                DW_AT_prototyped	(true)
                DW_AT_APPLE_optimized	(true)
Line info: file 'AppDelegate.m', line 38, column 39, start line 33

 

2017-09-05 10:56:23 a12041543 阅读数 428

友盟错误分析工具使用,

所需: a. umcrashtool b. archive包

  1. 找到当时发布到线上那个版本的archive包,cd Library/Developer/Xcode/Archives/ 找到线上的.xcarchive包,右键显示包内容,将.DSYM文件导出复制到Library/Developer/Xcode/
    如图
    这里写图片描述
  2. 下载友盟错误统计分析工具umcrashtool 下载地址:http://dev.umeng.com/files/download/umcrashtool.zip
  3. 打开终端,cd 到 到根目录下, 先拖入umcrashtool 文件夹路径到终端,再拖入 友盟官网下载的crash的csv文件。(这里建议将umcrashtool 和csv文件放在同一文件目录下)这里写图片描述
  4. enter即可打印crash代码行
    这里写图片描述

技术资料汇总

阅读数 90

没有更多推荐了,返回首页