Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >lldb 入坑指北(1) - 给Xcode批量添加启用&禁用断点功能

lldb 入坑指北(1) - 给Xcode批量添加启用&禁用断点功能

作者头像
酷酷的哀殿
发布于 2021-03-03 07:34:35
发布于 2021-03-03 07:34:35
1.1K00
代码可运行
举报
文章被收录于专栏:酷酷的哀殿酷酷的哀殿
运行总次数:0
代码可运行

前言

为了避免浪费你的时间,在阅读本文前,请先思考以下问题:

  • 你是否经常使用 Xcode 的断点功能?
  • Xcode 的断点功能好用吗?
  • 如果给 Xcode 批量添加启用&禁用断点功能,是否会提高你的工作效率?

如果都是NO,那么,请先阅读 调试器共舞 - LLDB 的华尔兹[1] 后再回来阅读本文章。相信我,掌握甚至精通 lldb 能够快速的提供你的生产力。

如果以上问题都是YES,那么,欢迎继续阅读以下内容。

阅读本文需要以下技能:

  • Python 有基本的了解
  • 对 Xcode 的断点功能有基本的了解(相关的文档可以参考 Xcode 断点文档[2]

通过本文,希望大家可以了解以下内容:

  • 了解 lldb 的 API 架构
  • 通过 lldb 相关 API,构建自己的效率工具(Python 脚本)

入门

LLDB

LLDB 是一个开源调试器,它已经被内置在 Xcode 程序中。如下图所示,位于主窗口的底部,名为Conseole的窗口就是用于和 lldb 交互的区域。

x

断点

首先,我们先通过以下步骤对 lldb 进行初步的了解。

  • 创建一个程序
  • viewDidLoad 处添加添加断点
  • 运行程序,并使程序停在断点处
  • 在 Console 区域输入 po self 并回车
  • 观察输出结果

当程序暂停后(通过断点或者手动点击暂停按钮),Console 区域就会进入 lldb 模式。po self 是指把 self 当做一个对象进行打印,类似的还有 p self 等命令。

ps. 通过help命令,可以打印所有的可用命令。pss. 通过help po命令,可以打印该命令的用法。

Chisel

Chisel 是一个 Python 脚本集合,建议读者先阅读 与调试器共舞 - LLDB 的华尔兹 后再看下面的部分

进阶

再看 LLDB

LLDB 的调试接口本质上是一个 C++ 共享库,在 Mac 系统上,它被打包为 LLDB.framework(正常情况下,我们可以 /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework 路径看到它),在类 unix 系统上,它是 lldb.so。这些调试接口可以在 lldb 的脚本解释器内直接使用,或者可以被引入 lldb.py 模块的 Python 脚本使用。

LLDB 本身支持用户自定义命令,比如通过脚本可以自定义一个pviews 命令,该命令可以打印 APP 所有的视图。

该命令已经在 Chisel 中实现。

lldb 脚本入门

首先,我们先通过一个非常简单的脚本,构造一个自定义命令。

创建脚本

在~/ls.py 位置创建一个脚本,内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lldb
import subprocess

def ls(debugger, command, result, internal_dict):
    print(command)
    ret = subprocess.getstatusoutput('ls ' + command)
    for i in ret[1].split("\n"):
        print(i)

def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand('command script add -f ls.ls ls')
    print ('The "ls" python command has been installed and is ready for use.')
在 lldb 中载入脚本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(lldb) command script import ~/ls.py
执行命令
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    (lldb) ls ./
  Applications
    Users
    ...

到此为止,我们已经成功的实现了一个自定义的命令。

OK,让我们重新解释一下上面的代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    command script import ~/ls.py

command是 lldb 用于管理自定义命令的一个入口。

command script import 可以导入一个自定义的脚本文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    def __lldb_init_module(debugger, internal_dict):
        debugger.HandleCommand('command script add -f ls.ls ls')
        print 'The "ls" python command has been installed and is ready for use.'

脚本文件被导入时,并且def __lldb_init_module(debugger, internal_dict):方法会被检测到时,它会被自动调用。我们可以在这里一次性实现多个自定义命令。

debuggerlldb.SBDebuggerlldb.SBDebugger-class[3] 的一个实例,代表了当前的调试器对象。

internal_dict 包含了当前脚本会话的变量和方法。

HandleCommand 是一个实例方法,通过它,我们可以在 Python 脚本里面,调用 lldb 的方法。比如,这里的command script add -f ls.ls ls

command script add -f ls.ls ls 的含义是“声明一个自定义的命令ls,这个命令的实现是 ls.ls”。command script add -f 函数名 自定义命令名 -f 代表后面跟着一个函数名,类似还有-c,代表一个 Python 类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lldb
import subprocess

def ls(debugger, command, result, internal_dict):
    print(command)
    ret = subprocess.getstatusoutput('ls ' + command)
    for i in ret[1].split("\n"):
        print(i)

debugger上面已经讲过,不再赘述。

command 是一个字符串,是我们命令的参数。以我们在 lldb 输入 ls -l var 为例,command-l var

resultlldb.SBCommandReturnObject的实例。

internal_dict上面已经讲过,不再赘述。

这个函数是我们自定义命令的核心,它通过调用 Python 模块 subprocessgetstatusoutput 方法,获取ls 命令的输出结果,并打印到结果中。

批量管理断点

通过上面的介绍,相信我们很容易实现一个批量管理断点的自定义命令。

这里简单分享一下思路。

  • 注册两个自定义命令作为入口,benable&bdisable
  • 通过一个函数实现状态的控制def switchBreakpointState(expression,on):
  • 遍历断点和 location,当 location 符合要求时,切换断点和 location 的状态。

完整源码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/python

import lldb
import optparse
import shlex

import re

def switchBreakpointState(expression, on):

    expression_pattern = re.compile(r"{}".format(expression), re.I)

    target = lldb.debugger.GetSelectedTarget()
    for breakpoint in target.breakpoint_iter():
        if breakpoint.IsEnabled() != on and (
            expression_pattern.search(str(breakpoint))
        ):
            print(str(breakpoint))
            breakpoint.SetEnabled(on)
        for location in breakpoint:
            if location.IsEnabled() != on and (
                expression_pattern.search(str(location))
                or expression == hex(location.GetLoadAddress())
            ):
                print(str(location))
                location.SetEnabled(on)

def benable(debugger, command, result, internal_dict):
    switchBreakpointState(str(command),True)

def bdisable(debugger, command, result, internal_dict):
    switchBreakpointState(str(command),False)

def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand('command script add -f ls.ls ls')
    debugger.HandleCommand('command script add -f ls.benable benable')
    debugger.HandleCommand('command script add -f ls.bdisable bdisable')
    print 'The python commands has been installed and is ready for use.'

扩展阅读

  • lldb 命令[4]
  • LLDB Python Reference[5]

参考资料

[1]

与调试器共舞 - LLDB 的华尔兹: https://objccn.io/issue-19-2/

[2]

Xcode 断点文档: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/debugging_with_xcode/chapters/quickstart.html#//apple_ref/doc/uid/TP40015022-CH7-SW3

[3]

lldb.SBDebugger-class: https://lldb.llvm.org/python_reference/lldb.SBDebugger-class.html

[4]

lldb 命令: http://lldb.llvm.org/lldb-gdb.html

[5]

LLDB Python Reference: http://lldb.llvm.org/python-reference.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 酷酷的哀殿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
lldb-入坑指北(1)-给xcode添加批量启用禁用断点功能
如果都是NO,那么,请先阅读 https://objccn.io/issue-19-2/ 后再回来阅读本文章。相信我,掌握甚至精通 lldb 能够快速的提供你的生产力,提高生活品质。
酷酷的哀殿
2020/10/26
1.1K0
lldb-入坑指北(1)-给xcode添加批量启用禁用断点功能
iOS逆向(7)-LLDB,自制LLDB脚本,窜改微信红包金额
https://juejin.im/post/5caad5d6f265da251d4b875a”
iOSSir
2019/06/14
1.1K0
iOS逆向(7)-LLDB,自制LLDB脚本,窜改微信红包金额
lldb 入坑指北(3) - 打印 c++ 实例的虚函数表
打印 c++ 的虚函数表可以快速的帮助我们了解 c++ 父类与子类的 override 关系。 但是,lldb 目前却只支持常用的变量或者地址打印功能。所以,我们通过自定义 vt 实现打印虚函数表的诉求。
酷酷的哀殿
2020/10/26
1.7K0
lldb 入坑指北(3) - 打印 c++ 实例的虚函数表
XCode调试器LLDB
与调试器共舞 - LLDB 的华尔兹 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThisThing); 或者跳过一个函数调用来简化程序的行为? NSNumber *n = @7; // 实际应该调用这个函数:Foo(); 或者短路一个逻辑检查? if (1 || theBooleanAtStake) { ... } 或者伪造一个函数实现? int calculateTheTrickyValue { return 9; /* 先
用户1941540
2018/05/11
1.4K0
lldb 入坑指北(2)-​ 15行代码搞定二进制与源码映射
http://mpvideo.qpic.cn/tjg_3013949891_50000_5817e3ee3a3244308677fd52dcfc2a8f.f10002.mp4?dis_k=8605d8
酷酷的哀殿
2020/10/26
1.9K0
使用Python扩展lldb
Xcode集成了LLDB,进一步简化了程序调试流程。虽然LLDB很强大,但是它的命令很有限。所幸的是,lldb包含了对python的支持,使得lldb的拓展成为可能。本人在开发过程中很喜欢使用image lookup 命令,但是苦于每次只能执行一条,相当耗时,因此一直想要找到一种批量执行的方法。于是将目光放到了lldb python上......
py3study
2020/01/07
1.8K0
Xcode忽略指定的异常断点
日常的Xcode开发中,我们时常用【All Exceptions Breakpoint】来定位一些异常情况的断点 但该功能同时也会在@try@catch或者在使用诸如CoreData或Accessibility之类的异常大量框架时,很难追踪到您实际遇到的异常
freesan44
2021/03/03
9100
iOS开发 Xcode的各种调试、DEBUG
BUG,简单来说就是程序运行结果与预期的不同,下面来说说Xcode中的DEBUG方法 参考博文 断点调试 普通断点 全局断点 条件断点 1.普通断点 看图 当程序运行到断点处时会停下,然后进行单步
BY
2018/05/11
2.3K0
Swift进阶-LLDB调试
工欲善其事,必先利其器。程序猿最好的利器就是开发工具,iOS开发者最基本,最关键的一点就是熟练使用Xcode,而LLDB则是Xcode中至关重要的一环。 作为开发者,我们大部分的工作时间都用于调试,调试协议,调试UI,调试bug,用好LLDB,打遍iOS无敌手。
sweet说好的幸福
2020/12/23
8950
Xcode Debug 大全
我们如果在一个循环里面使用了断点,如果这个循环执行了100万次,那你的断点要执行那么多次,你不觉得蛋蛋都凉了的忧伤么?所以我们这么做:
零式的天空
2022/03/22
1.2K0
Xcode Debug 大全
iOS——调试工具LLDB学习
  LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。在日常的开发和调试过程中给开发人员带来了非常多的帮助。了解并熟练掌握LLDB的使用是非常有必要的。这篇文章将会带着大家一起了解在iOS开发中LLDB调试器的使用。
mukekeheart
2019/09/29
1K0
iOS——调试工具LLDB学习
XCode基本使用及调试技巧
对于初学iOS开发的同学,了解了Objective-C的基本使用后,最关心的应该是如何把OC程序运行起来。由于Xcode的基本使用比较简单,所以本文着重介绍一些Xcode的调试技巧。 一、基本使用 二、断点 三、常用命令 四、多线程 五、UI调试 六、其他 一、基本使用 1、如何创建一个工程: 打开Xcode -> File -> New -> Project 创建一个最简单的Single View Application。 一路Next,输入工程名,选择工程所在目录,最后Create。 2、Xcode
微信终端开发团队
2018/01/29
6.7K0
XCode基本使用及调试技巧
Xcode断点的小知识
我们在日常开发中离不开代码的调试和分析,断点调试是任何开发环境都必不可少的功能。Xcode提供了强大的断点调试,可以帮助我们进行差错分析等。
CC老师
2022/01/14
1.8K0
Xcode断点的小知识
XCode的debug断点调试
debug 流程控制 当你通过 Xcode 的源码编辑器的侧边槽 (或者通过下面的方法) 插入一个断点,程序到达断点时会就会停止运行。 调试条上会出现四个你可以用来控制程序的执行流程的按钮。 从左
用户1941540
2018/05/11
1.7K0
iOS代码调试之LLDB命令
在LLDB模式下,根据需要输入相关的LLDB调试命令既可进行代码调试,下面小编将给大家介绍几款常用的LLDB命令。 1.打印 打印是代码调试中最常用的命令,相关的命令有:p和po。 p 命令: print 命令的简写,使用p 命令可以查看基本数据类型的值;如果使用p命令查看的是对象,那么只会返回对象的指针地址。 p命令后面除了可以接变量、常量,还可以接表达式。 po 命令:print object的缩写,可以理解为打印对象。功能与p命令类似,也可以打印常量、变量,打印表达式返回的对象等。p 和 po 的区别在于使用 po 只会输出对应的值,而 p 则会返回值的类型以及命令结果的引用名。 用法如下:
用户5521279
2019/06/02
1.9K0
[译]使用 LLDB 调试 Go 程序
我一般调试Go程序都是通过log日志,性能调试的话通过 pprof 、trace、flamegraph等,主要是Go没有一个很好的集成的debugger,前两年虽然关注了delve,但是在IDE中集成比较粗糙,调试也很慢,所以基本不使用debugger进行调试, 最近看到滴滴的工程师分享的使用debugger在调试Go程序,我觉得有必要在尝试一下这方面的技术了。
李海彬
2018/08/16
2.1K0
[译]使用 LLDB 调试 Go 程序
lldb入坑指北(4)-打印任意函数的汇编代码
如果希望看到另外一个函数或方法的指令,通常需要打开另外的工具。比如 Hopper。
酷酷的哀殿
2020/10/26
3K0
lldb入坑指北(4)-打印任意函数的汇编代码
逆向开发从零到整(LLDB)
LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。在日常的开发和调试过程中给开发人员带来了非常多的帮助。
CC老师
2019/01/23
1.1K0
Go调试利器,手把手入门dlv (上)
说到调试器,首先让人想到大名鼎鼎的GDB,在mac上对应的有lldb,dlv是针对Go语言单独开发的调试利器,而且dlv也是用go语言开发的。在windows平台也可以同样运行。今天我们简单介绍一下dlv如何调试go程序的。
用户1072003
2022/12/02
2.6K0
Go调试利器,手把手入门dlv (上)
扒虫篇-Debug几个实用的方法
Bebug调试程序是开发中最常见的问题,对于一些简单有效的调试技巧的了解是很有必要的。这篇文章就列举Debug中用到的一些简单的技巧。
進无尽
2018/09/12
1.6K0
扒虫篇-Debug几个实用的方法
相关推荐
lldb-入坑指北(1)-给xcode添加批量启用禁用断点功能
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档