#0x00 摘要
Swift是2014年在WWDC上推出的新一代的编程语言。

#0x01 OC和swift的区别
因为没写过几行swift代码, 所以在这里不讲两门语言的语法区别。只从编译的角度聊一下两门语言的区别。

OC的本质其实是C, 苹果使用clang这个编译器前端在编译器端将整个OC的文件转换为与之对应的基于C的运行时, 有兴趣的可以使用clang的-rewrite-objc这个参数生成对应的cpp文件, 一个简单的”Hello World”程序在经过重写之后, 会变成大约十万行的代码, 可见运行时的复杂性。

Swift准确说有两种形式, 一种是类似python的那种基于解释器的运行方式; 还有一种就是在不使用解释器的情况下, 直接编译成可执行文件。第一种依赖swift这个解释器, 第二种依赖swiftc这个编译器前端。 这两个也是在这里需要讨论的两个组件。

#0x02 Swift & Swiftc

在命令行中简单的敲击一下, 这两个命令:

image

swift直接跳转到了解释器模式, 而swiftc则尝试寻找swift文件, 并编译文件。两个文件所在的路径分别为: /usr/bin/swiftc, /usr/bin/swift

0x03 逆向Swift & Swiftc
首先将swiftc扔到IDA中, 看到的如下的代码:

image

代码很简单, 只是将swiftc传给了一个函数, 函数指针的位置在$-5的位置, 为了确定这个指针的位置, 我们将swiftc中扔到lldb中去查看$+5指向的位置, 在lldb中代码查看到的汇编代码如下:

image

因为lldb会动态的解析符号, 因此, 这里可以看到swiftc最后调用了函数xcselect_invoke_xcrun这个函数, 这个函数只接受一个参数, 在这里这个参数是swiftc。

为了了解xcselect_invoke_xcrun, 这个函数中究竟做了啥, 必须逆向这个函数。通过查看macho文件的符号表和依赖库, 确定这个符号是在动态链接库libxcselect.dylib中, 这个库的位置如下:
image

将这个库拖进IDA中, 继续逆向。 一般来说, IDA的逆向必须紧紧的和动态调试配合。因此, 需要让lldb跳转到xcselect_invoke_xcrun这个函数中。 在这里有两个方法可以帮助你跳转到xcselect_invoke_xcrun中:
(1) Step in this symbol
在这里需要知道的是, 对于swiftc这个macho文件而言, xcselect_invoke_xcrun是一个外部符号, 动态连接器如果是第一次见到这个符号, 那么会跳转到函数dyld_stub_binder,尝试解析xcselect_invoke_xcrun这个函数指针的位置:
image

我们只需要跟过去, 然后跳过动态链接器的解析过程, 最后跳转到获得函数指针就可以了, 具体的过程如下:
image

%rqq中存储的就是, 动态链接器解析出来的函数指针地址, 跟进去就可以进入xcselect_invoke_xcrun函数中,
image

这样, 我们就进入了函数。

(2)break the symbol
这种方式无疑是最有效的, 但是如果当前macho中有大量重复的符号, 可能会导致设置无用的断点, 打个比方:
br set -n start
使用这样的方式, 会设置很多的断点, 有兴趣的可以试试看。

经过查看xcselect_invoke_xcrun的代码, 会发现, 这个函数主要做的一件事就是, 尝试找到动态链接库libxcrun.dylib, 并尝试解析符号xcrun_main, 如果成功就调用这个函数,
image

这个函数的参数看起来有三个, 但是经过调试,第一个参数是switfc, 而第二个则是0, 第三个参数 , 目前无法确定是啥。

进入xcrun_main中, 我们发现这货调用了一个指向xcode的swiftc, 具体路径可以使用如下的命令获得:
image

再逆向swift, 发现结果也是一样的,最后获得路径是:
image

通过查看文件属性, 可以看到如下的信息:
image

0x03 结论
(1)swift和swiftc命令在最后其实调用的都是文件:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift

(2)无法使用传统的clang去编译一个swift程序, 因为在xcode中编译swift代码的程序是swift这个“编译器”。之所以这样, 是因为swift在语言解释的时候和传统的clang有本质的区别, 感兴趣的可以查看https://www.youtube.com/watch?v=Ntj8ab-5cvE, Chris Lattner亲自解释了原因。

(3)为啥一个swiftc和swift指向同一个可执行文件, 却有两种截然不同的表现。我们可以通过如下的命令查看:
image

Happy Hacking
Axis