从print开始
2020-01-14
看了几天的metadata感觉没什么收获, 发现对swift的一些特性还不是很清楚, 决定从最常用的print开始分析
func callFunc() {
print("HelloWorld!")
}
callFunc() @ hackSwift:
0x100000a50: push rbp
0x100000a51: mov rbp, rsp
0x100000a54: sub rsp, 0x30
0x100000a58: mov rax, qword ptr [rip + 0x5b1] ; (void *)0x00007fff90c55908: type metadata for Any
0x100000a5f: add rax, 0x8 ; Any的Super point
0x100000a63: mov edi, 0x1 ; print第一个参数的个数
0x100000a68: mov rsi, rax
; 初始化(Any)数组
0x100000a6b: call 0x100000e60 ; symbol stub for: Swift._allocateUninitializedArray<A>(Builtin.Word) -> (Swift.Array<A>, Builtin.RawPointer)
0x100000a70: lea rdi, [rip + 0x4d5] ; "HelloWorld!"
0x100000a77: mov esi, 0xb ; length of "HelloWorld!"
0x100000a7c: mov ecx, 0x1 ; 是否为ASCII字符
0x100000a81: mov qword ptr [rbp - 0x8], rdx
0x100000a85: mov edx, ecx
0x100000a87: mov qword ptr [rbp - 0x10], rax
; 初始化String
0x100000a8b: call 0x100000e5a ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
0x100000a90: mov rsi, qword ptr [rip + 0x571] ; (void *)0x00007fff90c4dbc8: type metadata for Swift.String
0x100000a97: mov rdi, qword ptr [rbp - 0x8]
0x100000a9b: mov qword ptr [rdi + 0x18], rsi
; 拷贝字符串"HelloWorld!"
0x100000a9f: mov qword ptr [rdi], rax
0x100000aa2: mov qword ptr [rdi + 0x8], rdx
; 初始化分隔符字符串
0x100000aa6: call 0x100000b00 ; default argument 1 of Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> () at <compiler-generated>
0x100000aab: mov qword ptr [rbp - 0x18], rax
0x100000aaf: mov qword ptr [rbp - 0x20], rdx
; 初始化终结符字符串
0x100000ab3: call 0x100000b20 ; default argument 2 of Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> () at <compiler-generated>
0x100000ab8: mov rdi, qword ptr [rbp - 0x10]
0x100000abc: mov rsi, qword ptr [rbp - 0x18]
0x100000ac0: mov r8, qword ptr [rbp - 0x20]
0x100000ac4: mov qword ptr [rbp - 0x28], rdx
0x100000ac8: mov rdx, r8
0x100000acb: mov rcx, rax
0x100000ace: mov r8, qword ptr [rbp - 0x28]
; RSI: 保存分隔符
; RCX: 保存终结符
0x100000ad2: call 0x100000e66 ; symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> ()
; 释放终结符
0x100000ad7: mov rdi, qword ptr [rbp - 0x28]
0x100000adb: call 0x100000e96 ; symbol stub for: swift_bridgeObjectRelease
; 释放分隔符
0x100000ae0: mov rdi, qword ptr [rbp - 0x20]
0x100000ae4: call 0x100000e96 ; symbol stub for: swift_bridgeObjectRelease
; 释放Any数组
0x100000ae9: mov rdi, qword ptr [rbp - 0x10]
0x100000aed: call 0x100000e96 ; symbol stub for: swift_bridgeObjectRelease
0x100000af2: add rsp, 0x30
0x100000af6: pop rbp
0x100000af7: ret
0x100000af8: nop dword ptr [rax + rax]
调用的函数原型是 public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
字符串最后用0xEB定界(低八位是长度,这里是0xB)
//⚠️这里print少于16个字符,当大于等于16个字符的时候会开辟一个新的空间存储字符串,保存地址