【iOS】class-dump源码学习(一)

本文介绍了在学习class-dump 3.5版本时,如何解决Xcode build报错问题,涉及OpenSSL的安装与路径调整。接着深入分析class-dump源码,从main函数开始,详细讲解了CDFatFile和CDMachOFile的初始化过程,包括fat_header和fat_arch的处理。同时,文章探讨了Mach-O文件的结构,特别是LC_SEGMENT和LC_MAIN命令的作用,为后续动态连接器命令的分析奠定基础。
摘要由CSDN通过智能技术生成

学习版本:class-dump-3.5.dmg


Build

上手打开工程先build一次(Xcode10)

报错缺少openssl的头文件

命令行指令 which openssl 打印 LibreSSL 2.6.5,说明苹果已经将openssl替换成了libressl

使用 brew install openssl安装openssl

安装完毕后会有这样的提示,应该是和现有有冲突,暂不做处理。

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because openssl/libressl is provided by macOS so don't link an incompatible version.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.bash_profile

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

打开/usr/local/opt/openssl@1.1/1.1.1d/include,把里面的openssl拷贝一份到/Applications/Xcode.app/Contents/DeveloperPlatforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/

/usr/local/opt/openssl@1.1/1.1.1d/lib也拷贝一份放到对应目录下

再次build,success


直接从class-dump.m的main函数入手

处理参数的代码略过

从读取文件入手

CDFile *file = [CDFile fileWithContentsOfFile:executablePath searchPathState:classDump.searchPathState];

CDFile是基本的文件单位,子类有CDFatFiIe、CDMachOFile,对应fat文件(胖二进制文件,可以看作是多个mach-o文件的聚合体)、mach-o文件。

关注CDFile静态方法

+ (id)fileWithContentsOfFile:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState;

核心逻辑是分别调用两个子类的initWithData:filename:searchPathState:方法。

先看CDFatFile中的initWithData:filename:searchPathState:方法

- (id)initWithData:(NSData *)data filename:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState;
{
    if ((self = [super initWithData:data filename:filename searchPathState:searchPathState])) {
        CDDataCursor *cursor = [[CDDataCursor alloc] initWithData:data];

        struct fat_header header;
        header.magic = [cursor readBigInt32];
        
        //NSLog(@"(testing fat) magic: 0x%x", header.magic);
        if (header.magic != FAT_MAGIC) {
            return nil;
        }
        
        _arches = [[NSMutableArray alloc] init];
        
        header.nfat_arch = [cursor readBigInt32];
        //NSLog(@"nfat_arch: %u", header.nfat_arch);
        for (NSUInteger index = 0; index < header.nfat_arch; index++) {
            CDFatArch *arch = [[CDFatArch alloc] initWithDataCursor:cursor];
            arch.fatFile = self;
            [_arches addObject:arch];
        }
    }

    return self;
}

CDDataCursor很好理解,就是一个可以读取定长数据的指针。而fat_header是系统定义的fat文件头结构。

第一步读取魔数magic。加载器通过这个数值来判断当前文件是什么文件,主要区分32位和64位

#define FAT_MAGIC	0xcafebabe
#define FAT_MAGIC_64	0xcafebabf

不过能看到class-dump并没有处理FAT_MAGIC_64的情况(return nil;意味着会走到mach-o文件的逻辑),个人理解fat文件的魔数并不重要,不能作为加载器选择执行文件的参考。

同时这里有个点,如果使用machoview打开fat文件,一般会看到魔数的值为FAT_CIGAM,意味着魔数实际是以小端模式的形式存储的,而class-dump在读取时使用OSReadBigIn

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值