From Brad.Cox to Chris.Lattner.
我是一个代表本篇文章未完成的标记!
尝试利用一些业余时间研究下 Swift,写一些由 OC 到 Swift 的变化。
当我使用 ClassDump 对一个项目操作的时候,输出了一些看不懂的东西,今天研究一下这奇怪的字符串到底是什么意思?!(后来知道了这是一个 OC Swift 混编的工程)
1 |
|
通过 Reveal 分析 UI,我大概知道这个类是 BalaBalaKit.LoadingView
,通过查看 MachO 发现 __TEXT
段中有 __swift5_typeref
,其中的数据跟这些很类似,所以这些就是Swift输出的类名。
Swift 这样进行转换的原因是为了防止不同的库不会出现命名冲突。
OC & C
OC 的符号表中没有这些复杂的符号重整,OC 使用 Selector + Type Encoding,并且 OC 在一个类下是不允许重载 Selector 的。
C 和 OC 在语言设计上,就避免了符号冲突,所以虽然做了 Name Magling,但是并没有什么实际的用处,只是为了历史性的考虑。
C 语言有轻微的 Name Mangling,即会将 void main(){return 0;}
符号化为:_main
,增加一个下划线。
OC 举一个栗子:Point类下的 + (id) initWithX: (int) number andY: (int) number;
方法
1 | + (id) initWithX: (int) number andY: (int) number; |
C++
我们知道 C++ 是允许函数重载的,也就是对于下面的第一个 fooInt 方法和 fooDouble 两个方法是可以共存的:
1 | int foo(int a) { return a * 2; } |
C++编译器遵循一套严格的 mangles 规则,参考这个链接Itanium C++ ABI documentation
以 int foo(double a)
为例,重整后的符号为 __Z3fooi
大致意思如下:
1 | _ _Z 3 foo d |
Swift
Swift 的重整规则基于 C++,也有些不同,重整的符号中包含更多的信息和概念。
xcrun 命令提供了还原ManglingName的方法:
xcrun swift-demangle $s4test004GrIh3lhs3rhsS2i_SitF
栗子:
1 | xcrun swiftc -emit-library -o test - |
栗子2:
1 | didi ~ xcrun swiftc -emit-library -o test - |
字符替换:
如果上面 caculate 函数的参数命名中包含了前面出现过的字符串会如何呢?
1 | 没有字符串重叠的时候是: |
以上
对专业人员,从算法的意义上讲,读取变形的名称是相当简单的,但是对于人眼来说则是不必要的困难。
这就是为什么存在拆解工具的原因。
补充
关于curried & uncurried function:
上面案例中的方法d是一个uncurried function
,因为参数是一个一个传递进去的,并不是当做一个多元元组传递进去的。(可能理解有误。。)
这个概念是跟函数式编程相关的,暂未深入了解,挖个坑,稍后填坑。
ref:stackOverFlow:How is this exactly a curried function?
参考链接:
- 最权威:官方 GitHub Doc
- https://www.mikeash.com/pyblog/friday-qa-2014-08-15-swift-name-mangling.html
- wikipedia:Name mangling
- https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
- 官方SwiftDoc关于mangling的章节
其他:
OS X ABI Mach-O File Format Reference
- Post link: http://yangzai360.top/2021/03/05/OC2Swift01_SwiftNameMangling/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.