简介

LLDB是Low Lever Debugger的简称,翻译成中文应该叫做底层调试器,它是LLVM项目的调试器组件。LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。如果你了解过Swift语言及其作者,那么一定对Chris Lattner博士不陌生,那这里为什么要提到他呢?没错LLVM开发最初就是由Chris Lattner博士主持开展的。

LLDB支持调试C、Objective-C和C++编写的程序。Swift社区维护了一个版本,增加了对该语言的支持。默认内置于Xcode中,LLDB提供了一组广泛的命令,旨在与老版本的GDB命令兼容。除了使用标准配置以外,还可以很容易的自定义LLDB命令以满足实际需要。可以在Xcode的控制器进入lldb调试模式后,输入help可以查看所有Debugger commands,也可以在这个网站查询

breakpoint命令

断点命令,在平时使用Xcode开发的过程中,我们设置断点一般都是通过在界面上点击代码所在的行数设置的。其实也可以使用lldb的命令来设置断点。

根据名字设置断点

设置C函数名断点

<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1df1a8fc0824a1eb514cbc346414faf~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image) 在touchedBegan方法中,我们从界面设置了一个断点,进入了lldb调试模式,再输入以下命令设置函数断点:breakpoint set -n "test1",-n是--name的缩写,然后点击继续按钮,或者输入lldb命令c继续执行,可以看到其实Xcode集成的很多的调试功能就是从lldb这来的。调试下一步就在lldb输入n或者s,n遇到子函数不会进入,s遇到子函数会进入" style="margin: auto" />

设置OC方法名断点

先搭建个如图所示的简单界面 <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/026b14e3117e49d6b98f474643da37e3~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image) 然后暂停程序,在控制台输入如下命令:breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continue:]"这样就设置了一组断点,它有三个断点。可以使用以下命令查看当前所有断点:breakpoint list ![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9c17f3eaf4df4d32b259e2295a1da0bd~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image" style="margin: auto" />

禁用和启用断点

禁用断点,后面的数字是breakpoint list显示的编号,可以同时禁用1组,也可以单独禁用组里的某个 breakpoint disable 编号

删除断点

删除断点breakpoint delete 编号,这里有个小细节,我们无法删除一组断点里面的某一个,只能删除一整组断点。如果delete后面跟的是某个组里面的某个断点,等同于禁用这个断点。如果不输入编号,那就相当于删除所有断点

根据方法设置断点

刚刚我们设置的断点,是某个类的某些具体方法,我们也可以设置与类无关的方法断点:breakpoint set --selector touchesBegan:withEvent:

如果不想这样把断点断到系统库里面去,可以指定文件设置方法断点,我们在ViewController里加上touchesBegan:方法:breakpoint set --file ViewController.m --selector touchesBegan:withEvent:

正则匹配设置断点

可以输入help breakpoint set看到-r参数的介绍

Set the breakpoint by function name, evaluating a regular-expression to find the function name(s). 

breakpoint set -r save:这样就会根据-r后面的参数去寻找所有能匹配到的方法

同样的,我们可以配合指定文件来使用这个命令 breakpoint set -r save: --file ViewController.m

断点执行命令

breakpoint command add 编号可以给断点加一些命令,这样断点来到的时候,可以自动执行这些命令,能否为我们节省一些操作

以上这些所有的lldb命令,都可以缩写,比如:breakpoint set -r save: --file ViewController.m可以缩写成b -r save: -f ViewController.m``breakpoint list可以缩写成break li``breakpoint disable 8.1可以缩写成bre dis 8.1``breakpoint enable 8.1可以缩写成bre en 8.1反正你可以去各种尝试,多一个少一个字母或许都能行,比较随意,比起普通的命令错一个字符都不行还是蛮牛逼的。

expression命令

我们平时在lldb控制台里面干的最多的是什么?po打印某个对象吧,那么这个po到底是什么意思呢?可以在终端输入如下命令查看一下: help po

通过help po我们知道就是在主线程执行表达式,那么我们可以试试在lldb中修改一些常见的属性,比如self.view.backgroundColor,首先来到touchesBegan:断点,在lldb输入如下指令p self.view.backgroundColor = [UIColor redColor];<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dc5c508108d54a81a3481ba930115338~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image) 发现确实执行了这句代码,但是却报了一个让人疑惑的错误,而且过掉断点之后并没有任何效果,当然了明明执行都报错了,怎么可能会有效果呢。。。但是这一行代码,在程序中运行的话,肯定是没有问题的,我们查看UIView的头文件也可以发现它确定是有backgroundColor这个属性的。至于为什么我在网上搜索半天没有找到任何答案,感觉可能是lldb的bug?虽然这句代码无效,但是我们依然可以尝试使用其他的方式来修改,比如:p [self.view setValue:[UIColor blueColor] forKey:@"backgroundColor"]

KVC还是牛逼啊,还有一种办法,我们知道UIView真正用来显示的是它的layer,修改layer:p self.view.layer.backgroundColor = [UIColor yellowColor].CGColor ![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0487a68486ae4ceba1fe407eca761560~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image" style="margin: auto" />

再来一个案例,我么创建一个persons数组,存放一组Person模型,然后通过lldb的expression命令动态添加一个Person。

bt命令

进入lldb输入help bt可以看到,bt是查看当前线程调用栈的意思

新建以下这四个方法,并给demo4方法下个断点,然后点击屏幕进入断点

thread return 命令

当我们调试到某一帧的时候,如果不想让程序之后的代码,可以使用thread return线程返回,需要注意return后面根据实际情况返回对应的值,例如:

以上所有方式在逆向中都没法使用。。。因为逆向的项目我们都拿不到符号

那么逆向应该如何玩lldb?内存断点

watchpoint 内存断点

内存断点,不仅可以给方法断点,还可以给变量断点

watchpoint 根据变量名设置内存断点

watchpoint set variable p1->_name如图所示,Person类有一个name属性,但是我们设置内存断点的时候,属性是没法用的,因为属性的本质是getter和setter加下划线的成员变量嘛,所以需要使用p1->_name设置成功之后,当程序中有给p1.name赋值的地方,都会来到断点。下图马上给p1.name赋值lldb就提示Watchpoint 1 hit命中了。然后还会显示old value和new value

watchpoint 根据内存地址设置内存断点

watchpoint set expression 地址 还是刚刚的例子,我们在p1实例化之后,它在内存中的地址就确定了,那么它的成员变量的地址也是确定的,我们可以拿到p1.name的内存地址,根据它的内存地址设置断点。当程序对p1.name进行修改的时候,都会来到断点,可以看到下面的断点来了两次,一次是在viewDidload中,另一次在touchesBegan里面进行的修改

target stop-hook 命令

这个命令有点类似breakpoint的断点执行命令,只不过breakpoint的断点执行命令需要指定某个断点,而这个命令是全局的,只要是断点来了,就会执行后面的命令

.lldbinit文件

可以将一些经常使用的命令配置到.lldbinit文件里面,这样就不用每次都去添加一些命令。这个文件一般放在用户目录下,点开头的代表是隐藏文件,如果没有可以自己新建一个。如图我们在里面添加这样一句指令

image 指令

这个是查看当前进程加载的镜像相关信息,什么是镜像,一个Mach-O文件就是一个镜像。我们的APP也是一个镜像。我们先来查看一下我们APP中的某个类的信息image look up -t name

image list

输入help image list查看命令的介绍

逆向中下内存地址断点

如图我们在touchesBegan:方法中调用了demo4方法

这里提一下ASLR,是一种防范内存损坏漏洞被利用的计算机安全技术,就是我们的APP每次加载进手机的真实内存的时候,位置不是固定的,所以我们每次APP运行起来后通过image list看到的我们APP的首地址是随机的。

我们APP的Mach-O文件中的内容,相对于Mach-O文件的首地址来说都是固定不变的,APP加载进内存之后首地址就确定了,那么Mach-O文件中的内容,比如方法实现,函数实现,常量等数据在内存中的位置都可以找到了。。。

可以在ViewController.m文件中定义一个全局变量,然后我们在Mach-O文件看能否找到它。如图定义一个全局变量,然后运行起来之后,打印它所在的地址,和当前APP的首地址,它的地址减去APP的首地址就是它相对于我们APP的Mach-O文件的偏移了。 <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6691afc10908400598503fe1abae024f~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image) 0x102b959f0 - 0x102b8c000 = 0x99F0在使用MachOView查看我们APP的Mach-O文件,找到地址0x99F0,看看是不是这个a的值0x123456678

有些同学可能会好奇,这个怎么是这个样子,其实这是因为机器的存取数据方式决定的,有些是大端模式,而有些机器是小端模式,这里贴一下百度的[大小端模式](https://link.juejin.cn/?target=https%3A%2F%2Fbaike.baidu.com%2Fitem%2F%25E5%25A4%25A7%25E5%25B0%258F%25E7%25AB%25AF%25E6%25A8%25A1%25E5%25BC%258F%2F6750542%3Ffr%3Daladdin "https://baike.baidu.com/item/%E5%A4%A7%E5%B0%8F%E7%AB%AF%E6%A8%A1%E5%BC%8F/6750542?fr=aladdin"" style="margin: auto" />

从这里也可以看出我们的全局变量是存放在__DATA,__data节的。

LLDB命令简单介绍相关推荐

  1. linux fg 参数,Linux的bg和fg命令简单介绍

    我们都知道,在 Windows 上面,我们要么让一个程序作为服务在后台一直运行,要么停止这个服务.而不能让程序在前台后台之间切换.而 Linux 提供了 fg 和 bg 命令,让我们轻松调度正在运行的 ...

  2. ping命令简单介绍+用ping简单测网速

    ping命令简单介绍+用ping简单测网速 ping可以用来检查网络是否通畅或者网络连接速度,而作为网络管理员ping命令是第一个必须掌握的DOS命令.我们可以用ping来给网络上指定IP的计算机发送 ...

  3. git 命令 简单介绍

    爱无路,恨无情.相思无缘,相爱无份.曾相识,恨离别.无风雨,无同舟,何结果.情远天边,心无挂碍,唯爱你独一. git简单介绍 三个区 工作区(working diretory) 用于修改文件 缓存区( ...

  4. linux系统shell知识点,Linux 系统中shell知识点说明和常用的帮助命令简单介绍 | IT工程师的生活足迹...

    linux 系统内核和各种驱动程序覆盖在下层的硬件系统之上:对上提供各种系统调用接口API,供shell和各种程序应用程序调用. 总体结构图如下: 操作系统的层次架构 一般我们理解shell指的是BA ...

  5. Linux 命令简单介绍第一课笔记

    第一: 相对路径和绝对路径 相对路径:从当前路径开始进入blog文件夹 cd blog 绝对路径:从跟目录开始进入blog文件夹 cd /home/yq/Desktop/blog 全称:根目录下hom ...

  6. Linux 命令简单介绍第二课笔记

    第一:touch touch 1.txt 创建文件 第二:ls ls 用来查看当前文件中的内容,其中加上不同参数-a,-h,-l可以有不同的显示,同事也可以将一个具体内容从定向到一个TXT文件中:具体 ...

  7. python中if命令简单介绍及注意事项(含笔记)

    if语句是用来进行判断的,其使用格式如下:

  8. AT命令的简单介绍和使用

    一.AT命令的简单介绍 AT即Attention,AT指令集是从终端设备(Terminal Equipment, TE)或数据中断设备(Data Terminal Equipment, DTE)向终端 ...

  9. HDFS简单介绍及用C语言訪问HDFS接口操作实践

    一.概述 近年来,大数据技术如火如荼,怎样存储海量数据也成了当今的热点和难点问题,而HDFS分布式文件系统作为Hadoop项目的分布式存储基础,也为HBASE提供数据持久化功能,它在大数据项目中有很广 ...

最新文章

  1. 赵方庆 北京生科院Computational strategies in exploring circular RNAs 探索环状rna的计算策略
  2. [LUOGU] P3128 [USACO15DEC]最大流Max Flow
  3. 神策 FM | 关于定价的 10 年经验总结
  4. 使用CXF与Spring集成实现RESTFul WebService
  5. python人工智能是什么意思_Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现...
  6. 用Emit技术替代反射
  7. 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...
  8. Docker 深入理解概念
  9. python在工业上的应用_工业+python - IT屋-程序员软件开发技术分享社区
  10. 训练 AI 创作诗歌 6 NLP 从零到英雄 Training an AI to create poetry
  11. git如何添加远程主机_Git由浅入深之远端主机(git remote)
  12. 什么是黑帽seo?黑帽seo技术盘点。
  13. 【VHDL】分频器设计要求:25分频,占空比为50%
  14. 怎么在电脑上创建一个虚拟机
  15. 上传资料总是显示服务器异常,云盘上传总是服务器异常
  16. 基本DOS命令---6.关机重启操作命令
  17. SpringBoot之RMI的简单使用
  18. 小米云备份的正确打开方式,你学会了吗
  19. Carsim 与 Simulink 联合仿真用到的ABS.mdl模型文件
  20. winform中的UI刷新总结

热门文章

  1. 股票交易日(动态规划)----美团2016研发工程师编程题(二)
  2. 超级计算机多层网络,超级计算机多层体系结构的摘要和描述(2)
  3. OpenGL学习-球体和phong光照模型
  4. 【数据库02】==== 表的增删改查(基础)
  5. 2021年焊工(初级)考试资料及焊工(初级)免费试题
  6. 如何通过轨迹信息判断驾驶人是否为同一人?
  7. mac记事本写html,MAC 记事本的选择
  8. 05【React再造之旅】从零实现一个React(下)
  9. python中n 是什么意思_python中\n是什么意思啊?
  10. 给对象做的暖心微信公众号推送(可自定义信息和天气预报的城市)