Swift Name Mangling - Swift_0x01

From Brad.Cox to Chris.Lattner.

尝试利用一些业余时间研究下 Swift,写一些由 OC 到 Swift 的变化。

背景

当我使用 ClassDump 对一个项目操作的时候,输出了一些看不懂的东西。(后来知道了这是一个 OC Swift 混编的工程)

#import <UIKit/UIViewController.h>
@interface _TtC11MandrakeKit11LoadingView : UIViewController {
}
- (id)initWithCoder:(id)arg1;
- (id)initWithNibName:(id)arg1 bundle:(id)arg2;
- (void)viewDidLoad;
@end

通过 Reveal 分析 UI,我大概知道这个类是 MandrakeKit.LoadingView,通过查看 MachO 发现 __TEXT 段中有 __swift5_typeref,其中的数据跟这些很类似,所以这些就是Swift输出的类名。

Swift 这样进行转换的原因是为了防止不同的库不会出现命名冲突

OC & C

OC 的符号表中没有这些复杂的符号重整,OC 使用 Selector + Type Encoding,并且OC 无重载。

C 语言有轻微的 Name Mangling,即会将 void main(){return 0;} 符号化为:_main,增加一个下划线。

OC 举一个栗子:Point类下的 + (id) initWithX: (int) number andY: (int) number;方法

+ (id) initWithX: (int) number andY: (int) number;
- (id) value;

_c_Point_initWithX_andY_
_i_Point_value

C++

对于如下方法,C++的NameMangling会翻译成下面这样:

    int foo(int a) { return a * 2; }
    int foo(double a) { return a * 2.0; }
    int main() { return foo(1) + foo(1.0); }

    0000000100000f30 T __Z3food
    0000000100000f10 T __Z3fooi
    0000000100000000 T __mh_execute_header
    0000000100000f60 T _main

C++编译器遵循一套严格的 mangles 规则,参考这个链接Itanium C++ ABI documentation

int foo(double a) 为例,重整后的符号为 __Z3fooi

大致意思如下:

_ _Z 3 foo d

-   : 代表C风格的符号
_Z  : 这个前缀标记这个符号是一个mangled(重整)的全局C++名字
3   : 字符长度,foo 这个名字,有3个字符
foo : 
d   : 代表`double`,如果是 `int` 的话就是`i`

Swift

Swift 的重整规则基于 C++,也有些不同,包含更多的信息和概念。

栗子:

xcrun swiftc -emit-library -o test -
public class myClass{
    public func calculate(x: Int) -> Int {
        return 0;
    }
}

nm -g test
0000000000002bb0 T _$s4test7myClassC9calculate1xS2i_tF
_$s4test7myClassC9calculate1xS2i_tF

_  // 通用起始
 $s // '$s' global  // Swift 稳定mangling版本
  4test // 字符长度,模块名
  7myClass // 方法归属的类名
  C // 从属关系,myClass 是 test 模块中的 Class
    9calculate // 字符 calculate
     1x // 参数类型
     S2i // 堆栈中放入两个 Swift.Int
     _
       tF // 从属关系,calculate 是 test.myClass 的 Function ???

这里解释一下S2i,这个是从后往前取的,参数往里放是栈结构,先进后出,第一个进栈的是参数 `x:Int`  第二个是返回的参数 Int,所以S2i两个`Swift.Int`。
如果入参是 `x:String`,反参是 Int,那就变成是 `SSSi` 了。

/* 此段过期,是以前的老版本
_TFC4test7MyClass9calculatefS0_FT1xSi_Si

_T // Swift通用起始标记
  F // Non-curried function
    C // Function of a class. (method)
      4test // 字符长度,模块名
        7MyClass // 方法归属的类名
          9calculate // 函数名
            f // 非柯里化函数(Uncurried Function)
              S0 // 指定 类实例 为类型堆栈的第一个参数
                _FT // 参数开始
                  1x // 第一个参数参数名
                    Si // Swift 内置类型 Swift.Int
                _Si // 返回类型,同上 Swift.Int
*/

// 结果:
test.MyClass.calculate(test.MyClass) -> (x: Swift.Int) -> Swift.Int

栗子2:

 didi ~  xcrun swiftc -emit-library -o test -
public func 💛 (lhs: Int, rhs: Int) -> Int {
    return 0;
}

 didi ~  nm -g test
0000000000002d60 T _$s4test004GrIh3lhs3rhsS2i_SitF

_  // 通用起始
  $s // '$s' global  // Swift 稳定mangling版本
    4test // 符号 4是长度
      004GrIh // 00 特殊字符 GrIh 就是 emoji U+1F49B
        3lhs // 参数 3是字符串长度
        3rhs // 参数 3是字符串长度
         S2i // 解释参数的类型,两个Swift.Int
         _ // end??? 待填坑
          Si // Swift.Int
           tF // 从属关系,💛 是 test 的 Function ???

//结果:
test.💛(Swift.Int, Swift.Int) -> Swift.Int

以上

对大多数人来说,不是很多。从算法的意义上讲,读取变形的名称是相当简单的,但是对于人眼来说则是不必要的困难。
这就是为什么存在拆解工具的原因。

补充

关于curried & uncurried function:
上面案例中的方法d是一个uncurried function,因为参数是一个一个传递进去的,并不是当做一个多元元组传递进去的。(可能理解有误。。)
这个概念是跟函数式编程相关的,暂未深入了解,挖个坑,稍后填坑。
ref:stackOverFlow:How is this exactly a curried function?


参考链接:

其他:
OS X ABI Mach-O File Format Reference

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容