mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 20:00:40 +00:00
docs: image url
This commit is contained in:
@@ -43,9 +43,9 @@ print("全局变量", Mems.ptr(ofVal: &p))
|
||||
print("堆空间", Mems.ptr(ofRef: p))
|
||||
```
|
||||
|
||||
<img src="./../assets/ClassMemoryLayoutExcludeFunction.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClassMemoryLayoutExcludeFunction.png" style="zoom:25%">
|
||||
|
||||
<img src="./../assets/ClassMemoryLayoutExcludeFunction2.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClassMemoryLayoutExcludeFunction2.png" style="zoom:25%">
|
||||
|
||||
代码段:Person.sayHi 0x1000034d0
|
||||
|
||||
@@ -183,7 +183,7 @@ print(fn(2)) // 2
|
||||
print(fn(3)) // 3
|
||||
```
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo1.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo1.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ print(fn(3)) // 6
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo2.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo2.png" style="zoom:25%">
|
||||
|
||||
可以看到上面有 `allocObject` 方法调用,说明产生了堆空间对象,用于存放 `num` 。是由 `var fn = getFn()` 造成的,调用1次 `getFn` 则产生1次堆空间分配,用于保存 num。
|
||||
|
||||
@@ -235,7 +235,7 @@ print(fn3(3)) // 4
|
||||
|
||||
我们在汇编 `swift_allocObject` 下面下个断点
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo3.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo3.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ print(fn3(3)) // 4
|
||||
|
||||
敏感点,查看到字面量1,给汇编代码15行加断点,执行完15行,继续查看内存信息
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo4.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo4.png" style="zoom:25%">
|
||||
|
||||
可以看到内存数据发生了改变。绿色框内有了值1。
|
||||
|
||||
@@ -253,13 +253,13 @@ print(fn3(3)) // 4
|
||||
|
||||
敏感点,查看到字面量1,给汇编代码15行加断点,执行完15行,继续查看内存信息
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo5.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo5.png" style="zoom:25%">
|
||||
|
||||
第三次:可以看到 `alloc` 在堆空间申请后的内存被存放到寄存器 `rax` 中,此时只是申请内存,没有赋值的。利用 `Debug -> Debug Workflow -> View Memory` 查看内存信息`0x000060000020d460`。此时还没值。
|
||||
|
||||
敏感点,查看到字面量1,给汇编代码15行加断点,执行完15行,继续查看内存信息
|
||||
|
||||
<img src="./../assets/ClosureCaptureVariableDemo6.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClosureCaptureVariableDemo6.png" style="zoom:25%">
|
||||
|
||||
打印结果也说明了问题,因为调用3次 `getFn()` 所以会在堆上 alloc 3块内存,用于保存捕获的变量。所以调用 fn1 得到 2,调用 fn2 得到 3,调用 fn3 得到 4。
|
||||
|
||||
@@ -279,7 +279,7 @@ print(fn(1, 2)) // 3
|
||||
|
||||
在 `var fn = sum` 处下断点,可以看到下面汇编
|
||||
|
||||
<img src="./../assets/ClouserMemoryLayoutExploreDemo1.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouserMemoryLayoutExploreDemo1.png" style="zoom:25%">
|
||||
|
||||
我们知道 `leaq` 是从 `%rip + 0x10f` 算出来的地址,赋值给 `%rax`。所以大概可以推测 `%rip + 0x10f` 就是 `sum` 函数地址。LLDM p 打印 `sum` 地址为 `0x0000000100003a30`。
|
||||
|
||||
@@ -297,15 +297,15 @@ print(fn(1, 2)) // 3
|
||||
|
||||
直奔主题,研究闭包内存
|
||||
|
||||
<img src="./../assets/ClouseExploreNotCaptureVariableDemo1.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreNotCaptureVariableDemo1.png" style="zoom:25%">
|
||||
|
||||
可以看到在调用完第六行的函数后将寄存器 `rax`、`rdx` 里的值取出来使用了。进入函数内部看看发生了什么,LLDB 输入 `si`
|
||||
|
||||
<img src="./../assets/ClouseExploreNotCaptureVariableDemo2.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreNotCaptureVariableDemo2.png" style="zoom:25%">
|
||||
|
||||
可以看到 `rax` 里面存放了 `plus` 函数地址。第7行汇编是异或运算,2个 `ecx` 异或,结果为0,写入到 `ecx` 里。然后第8行汇编将 `ecx` 里的0写入到 `edx`,`edx` 也就是 `rdx`。走完第6行的汇编,继续看第7、8行
|
||||
|
||||
<img src="./../assets/ClouseExploreNotCaptureVariableDemo1.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreNotCaptureVariableDemo1.png" style="zoom:25%">
|
||||
|
||||
将第6行函数的返回结果 `rax` 里的函数地址赋值给 `rip +0x89e7 = 0x100003819 + 0x89e7 = 0x10000C200 `, 第7行的`rdx` 的值赋值个给 `rip +0x89e8 = 0x100003820 + 0x89e8 = 0x10000C208`。
|
||||
|
||||
@@ -315,7 +315,7 @@ print(fn(1, 2)) // 3
|
||||
|
||||
继续对比实验,查看闭包放了什么东西(注意和上面的实验不同,下面存在闭包)
|
||||
|
||||
<img src="./../assets/ClouseExploreNotCaptureVariableDemo3.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreNotCaptureVariableDemo3.png" style="zoom:25%">
|
||||
|
||||
基本可以断定:函数会返回一个长度为16 Byte 的内存。分别保存在 `rax` 和 `rdx`上。所以针对性的研究 `rdx` 和 `rax`
|
||||
|
||||
@@ -323,7 +323,7 @@ print(fn(1, 2)) // 3
|
||||
|
||||
20行的 `rax` 保存了一个看似是 `plus` 的函数地址。具体是:`rip + 0x167 = 0x100003969 + 0x167= 0x100003C37 `
|
||||
|
||||
<img src="./../assets/ClouseExploreNotCaptureVariableDemo3.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreNotCaptureVariableDemo3.png" style="zoom:25%">
|
||||
|
||||
继续走,走到真正的 `plus` 方法内,可以看到函数地址是 `0x100003970` 。所以返回的 `rax` 里面可能是间接调用真正的 `plus` 函数的。
|
||||
|
||||
@@ -340,13 +340,13 @@ Tips:由于地址是动态生成的,所以真正去调用 plus 的时候一
|
||||
|
||||
顺着思路,分析下汇编:
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo1.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo1.png" style="zoom:25%">
|
||||
|
||||
我们看到25行 `callq *%rax` 存在动态调用,所以需要找到 `%rax` 里的值是哪里来的。然后顺着向上找,找到23行 `movq -0x30(%rbp), %rax`。然后继续向上看到16行 `movq %rax, -0x30(%rbp)`。继续向上看到15行 `movq 0x88db(%rip), %rax`。相当于就是在 `rip + 0x88db ` 处取出8个字节出来,当作函数地址调用(汇编代码的右边写了,`fn1` ),地址为:`0x88db(%rip) = rip + 0x88db = 0x10000392d + 0x88db = 0x10000C208` 。
|
||||
|
||||
断点继续放开,在汇编25行处加断点 `callq *%rax`
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo2.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo2.png" style="zoom:25%">
|
||||
|
||||
可以看到在方法内部,第6行汇编处,直接调用一个代码段的函数地址 `jmp 0x1000039f0 `
|
||||
|
||||
@@ -357,13 +357,13 @@ Tips:由于地址是动态生成的,所以真正去调用 plus 的时候一
|
||||
|
||||
LLDB 输入 `si`,可以看到是 `plus` 函数真正的地址
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo3.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo3.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
`fn1` 函数调用的时候,参数如何传递?
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo4.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo4.png" style="zoom:25%">
|
||||
|
||||
汇编17行 `movq 0x88d8(%rip), %r13 ; SwiftDemo.fn1 : (Swift.Int) -> Swift.Int + 8`可以看到将返回的 fn1 本身16字节的后8个字节,也就是堆地址空间值,保存到寄存器 `edi` 也就是寄存器 `rdi` 上了。
|
||||
|
||||
@@ -371,7 +371,7 @@ LLDB 输入 `si`,可以看到是 `plus` 函数真正的地址
|
||||
|
||||
然后 LLDB 输入 `si` 去分析 callq 内部
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo5.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo5.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ LLDB 输入 `si`,可以看到是 `plus` 函数真正的地址
|
||||
|
||||
继续输入 `si`
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo6.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo6.png" style="zoom:25%">
|
||||
|
||||
可以看到汇编的第5行 `movq %rsi, -0x50(%rbp)` 将 `rsi` 里的1,保存到 `rbp - 0x50` 处。第6行汇编 `movq %rdi, -0x58(%rbp)` 将 `rdi` 堆地址值保存到 `rbp - 0x58` 处。
|
||||
|
||||
@@ -387,7 +387,7 @@ LLDB 输入 `si`,可以看到是 `plus` 函数真正的地址
|
||||
|
||||
然后真正做 `plus` 加法运算的就是28行的 `addq 0x10(%rsi), %rdi`, 从 `rsi` 堆地址值的第16个字节的地方取出8个字节的值,也就是捕获的外部变量 `num` 再和参数1相加。
|
||||
|
||||
<img src="./../assets/ClouseExploreCaptureVariableDemo7.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ClouseExploreCaptureVariableDemo7.png" style="zoom:25%">
|
||||
|
||||
可以看到第6行堆地址空间的值写入到 `rbp -0x58` ,第26行又将 `rbp -0x58` 写入到 `rdi`,29行将 `rdi` 的值,写入到 `rbp - 0x48`,34行将 `rbp - 0x48` 写入到 `rcx`,35行将 `rcx` 的地址值,写入到 `rax` 对应的存储空间。也就是堆上的 `num` 值已经修改,被覆盖了。
|
||||
|
||||
@@ -502,7 +502,7 @@ serve(customer: group.remove(at: 0))
|
||||
|
||||
但如果函数参数没有加 `@autoclosure`,在调用函数的时候,传参没有加 `{}` 编译器是会报错的
|
||||
|
||||
<img src="./../assets/SwiftAutoClosureError.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SwiftAutoClosureError.png" style="zoom:25%">
|
||||
|
||||
正确的做法是:要么加 `@autoclosure` 要么在函数调用的时候加 `{}`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user