【注意】最后更新于 November 9, 2018,文中内容可能已过时,请谨慎使用。
{% github it-boyer chisel f331dc6 width = 30% %}
这个pull请求添加findinstances命令
,该命令完成Add findinstances, and new support framework in Chisel.xcodeproj 和Add Makefile for installing framework的工作。
用户可以运行help findinstances
获取findinstances
的详细信息。简要总结一下,findinstances
可以找到给定class
类或protocol
协议的所有实例,并使用谓词表达式过滤这些结果。
如果您有一个名为XXSocialUser
的类,那么您可以通过运行findinstances XXSocialUser == 'curry'
来找到一个特定的用户。
Chisel.xcodeproj
为新建findinstance
提供了凿子框架支持。
使用Chisel.xcodeproj
支持新建chisel Framework
通过本地代码实现command
,findinstances
等功能。也可以通过这种方式来实现更多chisel命令
。
findinstance
命令通过扫描iOS/macOSmalloc API
。对于每个allocation
分配,都会使用heuristics
来识别可能的Objective-C实例
。heuristics
不调用对象上的method,而是依赖objc runtime
运行时函数,基于class metadata
类元数据来匹配到oc实例
。这避免了在objc运行时
机制下分配和有状态副作用。
在第一次传递之后,候选对象将通过第二次传递,检查它们是否与可选的NSPredicate
匹配。如果没有谓词,则输出对象的信息最少。如果有谓词,并且对象传递谓词,那么对象将输出更多细节,特别是谓词中查询的细节。
1
2
3
4
5
6
7
| findinstances UIView
findinstances *UIView
findinstances UIScrollViewDelegate
findinstances UIView window == nil || hidden == true || alpha == 0 || layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0
findinstances UIView subviews.@count == 0
findinstances NSDictionary any @allKeys beginswith 'perf_'
findinstances NSArray @count > 100
|
开发使用
构建Xcode项目,并获得到Chisel Framework
的路径。:
1
| /Users/<me>/Library/Developer/Xcode/DerivedData/Chisel-<stuff>/Build/Products/Debug-iphonesimulator/Chisel.framework/Chisel
|
在lldb环境下执行:
1
2
3
| $ lldb
>>> expr -l objc -- (void*)dlopen("/path/to/Chisel.framework/Chisel", 2)
script o=lldb.SBExpressionOptions(); o.SetLanguage(lldb.eLanguageTypeObjC); o.SetTrapExceptions(False); o.SetTryAllThreads(False); o.SetTimeoutInMicroSeconds(10*1000000); lldb.frame.EvaluateExpression('(void)PrintInstances("<classname>", "<predicate>")', o)
|
<classname>
:可以是class
类名或protocol
协议名
<predicate>
:是一个可由NSPredicate
解析的字符串
可以使用regex command 命令
:
(注意,findinstance
后面必须换行)
1
2
| command regex findinstances
s/(\S+) *(.*)/script o=lldb.SBExpressionOptions(); o.SetLanguage(lldb.eLanguageTypeObjC); o.SetTrapExceptions(False); o.SetTryAllThreads(False); o.SetTimeoutInMicroSeconds(10*1000000); lldb.frame.EvaluateExpression('(void)PrintInstances("%1", "%2")', o)/
|
或者,作为python命令
,存储在path/to/findinstances.py
中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| import lldb
def findinstances(debugger, command, exe_ctx, result, _):
options = lldb.SBExpressionOptions()
options.SetTrapExceptions(False)
options.SetTryAllThreads(False)
options.SetTimeoutInMicroSeconds(10*1000000)
options.SetLanguage(lldb.eLanguageTypeObjC)
frame = exe_ctx.frame
if not exe_ctx.target.module['Chisel']:
frame.EvaluateExpression('(void*)dlopen("/path/to/Chisel.framework/Chisel", 2)', options)
args = command.split(' ', 1)
typeName = args[0]
predicate = args[1] if len(args) > 1 else ''
frame.EvaluateExpression('(void)PrintInstances("{}", "{}")'.format(typeName, predicate), options)
def __lldb_init_module(debugger, _):
debugger.HandleCommand('command script add -f findinstances.findinstances findinstances')
|
安装
Add Makefile for installing framework
This allows you to run make install with optional environment variables
in order to build and install Chisel.framework.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| PREFIX ?= /usr/local/lib
export INSTALL_NAME =
ifneq ($(LD_DYLIB_INSTALL_NAME),)
INSTALL_NAME = "LD_DYLIB_INSTALL_NAME=$(LD_DYLIB_INSTALL_NAME)"
endif
install:
xcodebuild \
-scheme Chisel \
-configuration Release \
-sdk iphonesimulator \
install \
$(INSTALL_NAME) \
DSTROOT=/ \
INSTALL_PATH="$(PREFIX)"
|