前语
之前,咱们在探求动画及烘托相关原理的时分,咱们输出了几篇文章,回答了
iOS动画是怎么烘托,特效是怎么作业的疑问
。咱们深感系统设计者在创作这些系统框架的时分,是如此脑洞大开,也深深意识到了解一门技能的底层原理关于从事该方面作业的重要性。
因而咱们决议
进一步探求iOS底层原理的任务
,本文探求的底层原理围绕“LLDB【指令结构、查询指令、断点设置、流程控制、模块查询、内存读写、chisel插件】
”展开
一、概述
工欲善其事必先利其器,咱们要探求iOS的底层原理,需求把握必定的前知识,如:
- 编译器项目-LLVM
- Xcode调试器-LLDB
-
iOS汇编-ARM、x86(
待输出
)
本文的中心方针便是对LLDB
进行简单介绍 且 对其常用的指令进行适当的实践
1.什么是LLDB?
在LLDB官网上介绍LLDB如下:
- LLDB是
Xcode在macOS上的默许调试器
,支撑在桌面、iOS设备和模拟器上调试C、Objective-C和c++。 - LLDB 是作为一组可重用组件构建的,高度利用了较大的LLVM项目中的现有库,如Clang表达式解析器和LLVM反汇编器。
- LLDB 是一个有着 REPL 的特性和 C++ 、Python 插件的开源调试器
2.LLDB 指令结构
<command> [<subcommand> [<subcommand>...]] <action> [-options [option- value]] [argument [argument...]]
对应:
- 1
<command>
: 指令 - 2
<subcommand>
: 子指令 - 3
<action>
: 指令操作 - 4
[-options [option- value]]:
指令选项 - 5
[argument [argument...]]:
指令参数`
其中:
- command、subcommand:LLDB调试指令的称号
- 指令和子指令按层级结构来摆放:
- 一个指令方针为跟随其的子指令方针创立一个上下文
- 子指令又为其子指令创立一个上下文,依此类推。
- 指令和子指令按层级结构来摆放:
- action:指令操作,想在前面的指令序列的上下文中履行的一些操作。
- options:指令选项,行为修正器(action modifiers)。通常带有一些值。
- argument:指令参数,依据运用的指令的上下文来表明各种不同的东西。
- []:表明指令是可选的,能够有也能够没有
示例:
指令:breakpoint set -n main
对应到上面的语法便是:
- command:breakpoint 断点指令
- action:set 设置断点
- option:-n 表依据办法 name 设置断点
- arguement:mian 表明办法名为 mian
3.LLDB原始指令
LLDB支撑不带指令选项
的原始指令
-
原始指令会将指令后边的一切东西当做参数(arguement)处理
-
但很多原始指令
也能够带指令选项
,当你运用指令选项的时分,需求在指令选项后边加--
区别指令选项和参数。 如:expression
(便是p
/print
/call
)、expression -o
(便是po
),打印一个UIView
方针地址:
前者是计算其地址的值,后者调用了方针的 description 办法,其中体现了仅有匹配准则:
- 假如依据前n个字母现已能仅有匹配到某个指令
- 则只写前n个字母等效于写下完好的指令
- 再用设置断点的指令举例,下面两条指令等效:
更多指令结构的介绍及用法,请参阅 LLDB 入门。
接下来介绍点 LLDB 常用指令
4.LLDB查询指令
4.1 apropos
当咱们并不能彻底记住某个指令
的时分,运用 apropos 通过指令中的某个关键字
就能够找到一切相关的指令信息。
- 比如: 咱们想运用stop-hook的指令,可是现已不记住stop-hook指令是啥样了: 咱们也能够检查官方文档的介绍: LLDB command map。
4.2help
指令 查询 指令用法
除了 apropos
、检查官方网文档LLDB command map,咱们也能够通过 help
指令 快速查找 LLDB指令的用法,示例如下:
help breakpoint
help breakpoint set
二.断点设置指令|breakpoint
、watchpoint
通过调试器断点指令操作断点:罗列 断点列表
、使断点 失效/收效
、删去/设置 断点
1.breakpoint
相关指令
breakpoint
(可简写成br
)
1.1 breakpoint set
= br set
设置断点
-
br set -a 函数地址
:给函数设置断点 -
br set -n 函数名
:给函数设置断点 -
breakpoint set -n test
:给大局的test办法设置断点 -
breakpoint set -n touchesBegan:withEvent:
:给大局的touchesBegan:withEvent:
办法设置断点 -
breakpoint set -n "-[ViewController touchesBegan:withEvent:]"
:给ViewController
的touchesBegan:withEvent:
办法设置断点 -
breakpoint set -r 正则表达式
给正则表达式
匹配上的办法设置断点-
此处跟上正则表达式,会将一切匹配到的办法
都加上断点
-
此处跟上正则表达式,会将一切匹配到的办法
-
breakpoint set -s 动态库 -n 函数名
:将指定动态库
的指定函数
打上断点 - 其它: breakpoint 支撑按文件名、函数名、行数、正则等各种条件筛选设置断点。概况参阅官方文档:
示例:
br set -r testSel
:遍历整个项目中包括 testSel 这个字符的一切办法并设置断点
1.2 breakpoint list
= br list
:列出一切的断点,每个断点都有单独的编号
1.3 breakpoint disable 断点ID
= br disable 断点ID
: 禁用断点
1.4 breakpoint enable 断点ID
= br enable 断点ID
: 启用断点
1.5 breakpoint delete 断点ID
= br delete 断点ID
: 删去断点
1.6 breakpoint command add 断点ID
= br command add 断点ID
: 给指定断点编号的断点预先设置需求履行1条或许多条指令
,到触发断点时,就会按顺序履行预先设置的命,设置多条指令时,用Done
表明设置结束
示例: 假定咱们需求在ViewController的viewDidLoad中检查self.view的值 咱们首先给-[ViewController viewDidLoad]添加一个断点
能够看到添加成功之后,这个breakpoint的id为3,然后咱们给他添加一个指令:po self.view
-o完好写法是–one-liner,表明添加一条指令。3表明对id为3的breakpoint添加指令。 添加完指令之后,每次程序履行到这个断点就能够自动打印出self.view的值了
假如咱们一会儿想添加多条指令,比如我想在viewDidLoad中打印当时frame的一切变量,可是咱们不想让他中止,也便是在打印完成之后,需求继续履行。咱们能够这样玩:
输入breakpoint command add 5
:对 断点编号为5
的断点 添加指令。它会让咱们输入添加哪些指令,输入’DONE’表明结束。这时分咱们就能够输入多条指令了
1.7 breakpoint command list 断点编号
= br command list 断点ID
:检查某个编号的断点一切预先设置的指令
1.8 breakpoint command delete 断点编号
= br command delete 断点ID
:删去指定编号断点的一切预设指令
2. 内存断点watchpoint
watchpoint
可简写为 wa
给指定的内存下断点,当内存中的数据发生改动时会触发
2.1 watchpoint set variable 变量
= wa set variable 变量
:对指定的变量设置内存断点,当变量值改动的时分会触发
2.2 watchpoint set expression 内存地址
= wa set expression 内存地址
:对指定内存地址设置断点,作用和watchpoint set variable相同
2.3 watchpoint list
= wa disable list
:列出一切的内存断点
2.4 watchpoint disable 断点ID
= wa disable 断点ID
:禁用内存断点
2.5 watchpoint enable 断点ID
= wa enable 断点ID
:启用内存断点
2.6 watchpoint delete 断点ID
= wa delete 断点ID
:删去内存断点
2.7 watchpoint command add 断点ID
= wa command add 断点ID
:给指定断点编号的内存断点预先设置需求履行的指令,到触发内存断点时,就会按顺序履行预先设置的指令
2.8 watchpoint command list 断点编号
= wa command list 断点ID
:检查某个编号的内存断点一切预先设置的指令
2.9 watchpoint command delete 断点编号
= wa command delete 断点ID
:删去指定编号内存断点的一切预设指令
3.target stop-hook
-
target stop-hook add -o "frame variable"
:添加每次程序 stop 时都希望履行的指令:frame variable(打印当时栈内的一切变量)
- target stop-hook、watchpoint 的增删改查指令与 breakpoint 的根本相同
4.其它断点
其它断点玩法需自定义插件支撑,在第五段介绍。
三.流程控制
Xcode断点流程控制按钮 如图:
以下指令从左到右顺次表明:指令全称、指令简称、极简指令:
-
第一个按钮:= 指令
process continue/continue/c
: 让程序越过断点继续运转 -
第二个按钮:单步运转,将子函数当做整体一步履行
- 源码等级 调试: =
thread step-over/next/n
- 汇编等级 调试: =
thread step-inst-over/nexti/ni
- 源码等级 调试: =
-
第三个按钮:单步运转,遇到子函数会进入子函数
- 源码等级 调试: =
thread step-in/step/s
- 汇编等级 调试: =
thread step-inst-over/stepi/si
- 源码等级 调试: =
-
第四个按钮:
thread step-out/finish
: 退出当时帧栈
si、ni和s、n指令相似,可是s、n是源码等级,si、ni是汇编指令等级。
- 每一句OC代码会有一条或多条汇编指令构成
- s、n指令表明
一步一步履行每一句OC代码
- 而si、ni表明
一步一步履行汇编指令
其他指令:
-
thread return
:它有一个可选参数,在履行时它会把可选参数加载进回来寄存器里,然后马上履行回来指令,跳出当时栈帧。-
这意味这函数剩余的部分不会被履行。
-
这会给 ARC 的引用计数形成一些问题,或许会使函数内的清理部分失效。
-
可是在函数的最初履行这个指令,是个十分好的阻隔方针函数、伪造回来值的方式。
-
四.image模块查询指令(模块:可履行文件&同享库等)
这些指令在逆向及定位错误时运用频率十分高。
4.1 image list
-
image list
: 列出一切所加载的模块信息
(lldb) image list
[ 0] 927601BD-5A00-319C-B8AF-8D501BB5D849 0x0000000100c01000 /Users/pinba/Library/Developer/Xcode/DerivedData/LLDBDemo-dkmvkvkytmalsoensevrvixujugm/Build/Products/Debug-iphonesimulator/LLDBDemo.app/LLDBDemo
[ 1] EEA931D0-403E-3BC8-862A-CBA037DE4A74 0x000000010d352000 /usr/lib/dyld
[ 2] 75369F31-702D-364A-95C3-8AFA9DD4B3A2 0x0000000100c0d000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
......
-
image list -o -f
: 打印出模块的偏移地址、全途径
lldb) image list -o -f
[ 0] 0x0000000000c01000 /Users/pinba/Library/Developer/Xcode/DerivedData/LLDBDemo-dkmvkvkytmalsoensevrvixujugm/Build/Products/Debug-iphonesimulator/LLDBDemo.app/LLDBDemo
[ 1] 0x000000010d352000 /usr/lib/dyld
[ 2] 0x0000000100c0d000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
......
4.2 image lookup
-
image lookup --address 内存地址
: 依据内存地址查找在模块中的方位- =
image lookup -a 内存地址
- =
(lldb) image lookup -a 0x00000001088b7cdb
Address: LLDBDemo[0x0000000100000cdb] (LLDBDemo.__TEXT.__text + 187)
Summary: LLDBDemo`-[ViewController touchesBegan:withEvent:] + 123 at ViewController.m:26:15
-
image lookup -v --address 内存地址
:查找完好的源代码行信息- =
image lookup -v -a 内存地址
- =
-
image lookup --type 类型
:查找某个类型的信息- =
image lookup -t 类型
- =
(lldb) image lookup -t NSUInteger
Best match found in /Users/pinba/Library/Developer/Xcode/DerivedData/LLDBDemo-dkmvkvkytmalsoensevrvixujugm/Build/Products/Debug-iphonesimulator/LLDBDemo.app/LLDBDemo:
id = {0x1000000ab}, name = "NSUInteger", byte-size = 8, decl = NSObjCRuntime.h:13, compiler_type = "typedef NSUInteger"
typedef 'NSUInteger': id = {0x1000000b8}, name = "long unsigned int", qualified = "unsigned long", byte-size = 8, compiler_type = "unsigned long"
-
image lookup -n 符号或函数名
: 查找某个符号或许函数的方位
(lldb) image lookup -n "-[ViewController touchesBegan:withEvent:]"
2 matches found in /Users/pinba/Library/Developer/Xcode/DerivedData/LLDBDemo-dkmvkvkytmalsoensevrvixujugm/Build/Products/Debug-iphonesimulator/LLDBDemo.app/LLDBDemo:
Address: LLDBDemo[0x0000000100000c60] (LLDBDemo.__TEXT.__text + 64)
Summary: LLDBDemo`-[ViewController touchesBegan:withEvent:] at ViewController.m:22 Address: LLDBDemo[0x0000000100000c60] (LLDBDemo.__TEXT.__text + 64)
Summary: LLDBDemo`-[ViewController touchesBegan:withEvent:] at ViewController.m:22
五、expression
指令
expression指令被用来履行一个表达式
expression self.view.backgroundColor = [UIColor redColor]
//或许
expression -- self.view.backgroundColor = [UIColor redColor]
-
expression
- =
print
、p
、call
作用等同
- =
-
expression -o
- =
po
作用等同
- =
(lldb) expression -o -- self.view
<UIView: 0x7f8f77c1dde0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x600002098d20>>
(lldb) po self.view
<UIView: 0x7f8f77c1dde0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x600002098d20>>
expression后的 — 表明指令选项结束符,表明一切的指令选项现已设置完毕,假如没有指令选项,–能够省略。假如expression之后有指令选项,则–不能省略。
六.内存读写指令
1.格局
- x是16进制
- f是浮点
- d是10进制
2.字节巨细
- b:byte 1字节
- h:half word 2字节
- w:word 4字节
- g:giant word 8字节
3.读取内存
格局:memory read/数量格局字节数 内存地址
- x/数量-格局-字节巨细 内存地址
- x/3xw 0x10010
4. 修正内存中的值
格局:memory write 内存地址 数值
- memory write 0x0000010 10
七.寄存器相关的指令
- register read:显现当时线程的通用寄存器。
- register write rax 123:将一个新的十进制值“123”写入当时线程寄存器“rax”。
八.其他常用指令
8.1 thread backtrace
= bt
:指令的作用是打印线程的堆栈信息
8.2 frame variable
打印当时栈帧的变量
(lldb) frame variable
(ViewController *) self = 0x00007f8f7b0091e0
(SEL) _cmd = "touchesBegan:withEvent:"
(__NSSetM *) touches = 0x00006000020c13e0 1 element
(UITouchesEvent *) event = 0x00006000011c43c0
(lldb) frame variable self
(ViewController *) self = 0x00007f8f7b0091e0
8.3 LLDB小技巧
- 每次敲Enter键,都会自动履行上次的指令
- 绝大部分的指令都能够运用缩写
(lldb) breakpoint list
(lldb) br li
(lldb) br l
(lldb) breakpoint set -n test
(lldb) br s -n test
九.LLDB第三方插件
有一些公司(如Facebook)专门为LLDB写了一些插件,便于提供给开发者更多快捷的调试
推荐插件: facebook 开源的 LLDB 插件 chisel
快捷指令
: 它提供的快捷 指令清单及阐明
9.1 装置
- 未装置Homrebrew,先装置Homrebrew 参阅MAC上Homebrew常用指令
- 装置Chisel
brew install chisel
9.2 装备
- 假如没有创立 .lldbinit 文件,则在终端创立文件
$ cd ~
$ touch .lldbinit
//open .lldbinit
- 修改 .lldbinit 文件
- 1、找到
chisel
的装置途径$ brew list chisel
- 2、找到
fbchisellldb.py
的途径/opt/homebrew/Cellar/chisel/2.0.1/libexec/fbchisellldb.py
- 3、修改
$ vim ~/.lldbinit
, 并添加以下内容:command script import /opt/homebrew/Cellar/chisel/2.0.1/libexec/fbchisellldb.py
- 1、找到
9.3 运用
最终wq保存,重启Xcode,就能够运用Chisel了。
9.4 快捷指令
指令 | 指令描绘 | iOS | OS X |
---|---|---|---|
pviews | Print the recursive view description for the key window. | YES | YES |
pvc | Print the recursive view controller description for the key window. | YES | NO |
visualize | Open a UIImage, CGImageRef, UIView, CALayer, NSData (of an image), UIColor, CIColor, or CGColorRef in Preview.app on your Mac. | YES | NO |
fv | Find a view in the hierarchy whose class name matches the provided regex. | YES | NO |
fvc | Find a view controller in the hierarchy whose class name matches the provided regex. | YES | NO |
show/hide | Show or hide the given view or layer. You don’t even have to continue the process to see the changes! | YES | YES |
mask/unmask | Overlay a view or layer with a transparent rectangle to visualize where it is. | YES | NO |
border/unborder | Add a border to a view or layer to visualize where it is. | YES | YES |
caflush | Flush the render server (equivalent to a “repaint” if no animations are in-flight). | YES | YES |
bmessage | Set a symbolic breakpoint on the method of a class or the method of an instance without worrying which class in the hierarchy actually implements the method. | YES | YES |
wivar | Set a watchpoint on an instance variable of an object. | YES | YES |
presponder | Print the responder chain starting from the given object. | YES | YES |
… | … | … | … |
总结
通过通篇介绍,咱们了解了:
- LLDB指令结构
- 查询指令
- 断点设置
- 流程控制
- 模块查询
- 内存读写
- 第三方LLDB插件:chisel
专题系列文章
1.前知识
- 01-探求iOS底层原理|综述
- 02-探求iOS底层原理|编译器LLVM项目【Clang、SwiftC、优化器、LLVM】
- 03-探求iOS底层原理|LLDB
- 04-探求iOS底层原理|ARM64汇编
2. 根据OC言语探求iOS底层原理
- 05-探求iOS底层原理|OC的实质
- 06-探求iOS底层原理|OC方针的实质
- 07-探求iOS底层原理|几种OC方针【实例方针、类方针、元类】、方针的isa指针、superclass、方针的办法调用、Class的底层实质
- 08-探求iOS底层原理|Category底层结构、App启动时Class与Category装载过程、load 和 initialize 履行、关联方针
- 09-探求iOS底层原理|KVO
- 10-探求iOS底层原理|KVC
- 11-探求iOS底层原理|探求Block的实质|【Block的数据类型(实质)与内存布局、变量捕获、Block的品种、内存办理、Block的修饰符、循环引用】
- 12-探求iOS底层原理|Runtime1【isa详解、class的结构、办法缓存cache_t】
- 13-探求iOS底层原理|Runtime2【消息处理(发送、转发)&&动态办法解析、super的实质】
- 14-探求iOS底层原理|Runtime3【Runtime的相关使用】
- 15-探求iOS底层原理|RunLoop【两种RunloopMode、RunLoopMode中的Source0、Source1、Timer、Observer】
- 16-探求iOS底层原理|RunLoop的使用
- 17-探求iOS底层原理|多线程技能的底层原理【GCD源码剖析1:主行列、串行行列&&并行行列、大局并发行列】
- 18-探求iOS底层原理|多线程技能【GCD源码剖析1:dispatch_get_global_queue与dispatch_(a)sync、单例、线程死锁】
- 19-探求iOS底层原理|多线程技能【GCD源码剖析2:栅门函数dispatch_barrier_(a)sync、信号量dispatch_semaphore】
- 20-探求iOS底层原理|多线程技能【GCD源码剖析3:线程调度组dispatch_group、事件源dispatch Source】
- 21-探求iOS底层原理|多线程技能【线程锁:自旋锁、互斥锁、递归锁】
- 22-探求iOS底层原理|多线程技能【原子锁atomic、gcd Timer、NSTimer、CADisplayLink】
- 23-探求iOS底层原理|内存办理【Mach-O文件、Tagged Pointer、方针的内存办理、copy、引用计数、weak指针、autorelease
3. 根据Swift言语探求iOS底层原理
关于函数
、枚举
、可选项
、结构体
、类
、闭包
、特点
、办法
、swift多态原理
、String
、Array
、Dictionary
、引用计数
、MetaData
等Swift根本语法和相关的底层原理文章有如下几篇:
- Swift5中心语法1-基础语法
- Swift5中心语法2-面向方针语法1
- Swift5中心语法2-面向方针语法2
- Swift5常用中心语法3-其它常用语法
- Swift5使用实践常用技能点
其它底层原理专题
1.底层原理相关专题
- 01-计算机原理|计算机图形烘托原理这篇文章
- 02-计算机原理|移动终端屏幕成像与卡顿
2.iOS相关专题
- 01-iOS底层原理|iOS的各个烘托框架以及iOS图层烘托原理
- 02-iOS底层原理|iOS动画烘托原理
- 03-iOS底层原理|iOS OffScreen Rendering 离屏烘托原理
- 04-iOS底层原理|因CPU、GPU资源耗费导致卡顿的原因和解决计划
3.webApp相关专题
- 01-Web和类RN大前端的烘托原理
4.跨渠道开发计划相关专题
- 01-Flutter页面烘托原理
5.阶段性总结:Native、WebApp、跨渠道开发三种计划功能比较
- 01-Native、WebApp、跨渠道开发三种计划功能比较
6.Android、HarmonyOS页面烘托专题
- 01-Android页面烘托原理
-
02-HarmonyOS页面烘托原理 (
待输出
)
7.小程序页面烘托专题
- 01-小程序框架烘托原理