Last active
July 6, 2022 19:40
-
-
Save kevinmbeaulieu/ea45786e1c28c3e4fe6289de205353fd to your computer and use it in GitHub Desktop.
LLDB utilities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Shortcuts to force execution in an Objective-C context instead of Swift (assuming current context is Swift) | |
command alias eobjc e -l objc | |
command alias pobjc e -l objc -- | |
command alias poobjc e -l objc -O -- | |
# Call while paused on closing } of a function to print return value | |
# TODO: Fix this, as $rax doesn't seem to be recognized anymore | |
# command alias retval p $rax | |
# Usage: let <variable-name> <memory-address> <type-name> | |
# | |
# variable-name: Name of variable to define (must start with $ to be persisted after completion of this command) | |
# memory-address: Pointer to data | |
# type-name: Name of type represented by the data at the given pointer | |
# | |
# Example: | |
# (lldb) let $foo 0x12345 UIView | |
# => Executes `e let $foo = unsafeBitCast(0x12345, to: UIView.self)` | |
command regex let 's/^([$A-Za-z0-9]+) +(0x[0-9a-f]+) +([A-Za-z0-9.]+)$/e let %1 = unsafeBitCast(%2, to: %3.self)/' | |
# Usage: j [+-] | |
# | |
# +-: + to jump forward, - to jump backward | |
# n: Number of lines to jump | |
# | |
# Example: | |
# (lldb) j +2 | |
# => Jumps forward by 2 lines (executes `thread jump --by 2`) | |
# | |
# (lldb) j -2 | |
# => Jumps backward by 2 lines (executes `thread jump --by -2`) | |
command regex j 's/^([\+-])([0-9]+)$/th jump --by %1%2/' | |
# Run AutoLayout trace on the view at the specified address | |
# | |
# Usage: autolayouttrace <memory-address> | |
command regex autolayouttrace 's/(.*)/e -l objc -O -- [(UIView *)%1 _autolayoutTrace]/' | |
# Refresh view hierarchy while paused by flushing the CATransaction queue | |
command alias refresh e CATransaction.flush() | |
command script import ~/.lldb/custom_lldb_commands.py |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lldb | |
import os | |
# Copy a variable from Swift LLDB context to Objective-C context | |
# Usage: swifttoobjc <variable> [<type>] [<name for objc variable>] | |
# E.g., | |
# swifttoobjc foo // Creates variable named `$foo` with same type as Swift variable `foo`. | |
# swifttoobjc foo UIView $bar // Creates variable named `$bar` with type `UIView`. | |
@lldb.command("swifttoobjc") | |
def copy_swift_to_objc(debugger, command, exe_ctx, result, internal_dict): | |
frame = exe_ctx.GetFrame() | |
args = command.split(" ") | |
swift_name = args[0] | |
try: | |
type_name = args[1] | |
except IndexError: | |
type_name = _get_value( | |
frame.EvaluateExpression("String(describing: type(of: {0}))".format(swift_name)) | |
) | |
try: | |
objc_name = args[2] | |
except IndexError: | |
objc_name = swift_name if swift_name.startswith("$") else ("$" + swift_name) | |
address = _get_value( | |
frame.EvaluateExpression( | |
"String(format: \"%p\", unsafeBitCast({0}, to: Int.self))".format(swift_name) | |
) | |
) | |
_execute_lldb( | |
debugger, | |
"e -l objc -- {0} *{1} = ({0} *){2};".format(type_name, objc_name, address) | |
) | |
# Show confirmation of success by printing the new Objective-C variable | |
_execute_lldb( | |
debugger, | |
"e -l objc -O -- {0}".format(objc_name) | |
) | |
# Copy a variable from Objective-C LLDB context to Swift context | |
# Usage: objctoswift <variable> [<type>] [<name for swift variable>] | |
# E.g., | |
# objctoswift foo // Creates variable named `$foo` with same type as Objective-C variable `foo`. | |
# objctoswift foo UIView $bar // Creates variable named `$bar` with type `UIView`. | |
@lldb.command("objctoswift") | |
def copy_objc_to_swift(debugger, command, exe_ctx, result, internal_dict): | |
frame = exe_ctx.GetFrame() | |
args = command.split(" ") | |
objc_name = args[0] | |
try: | |
type_name = args[1] | |
except IndexError: | |
type_name = _get_value( | |
frame.EvaluateExpression("{0}.description".format(objc_name)) | |
) | |
try: | |
swift_name = args[2] | |
except IndexError: | |
swift_name = objc_name if objc_name.startswith("$") else ("$" + objc_name) | |
address = _get_value( | |
frame.EvaluateExpression( | |
"[NSString stringWithFormat:@\"%p\", {0}]".format(objc_name) | |
) | |
) | |
_execute_lldb( | |
debugger, | |
"e -l swift -- let {0} = unsafeBitCast({1}, to: {2}.self)".format(swift_name, address, type_name) | |
) | |
# Show confirmation of success by printing the new Swift variable | |
_execute_lldb( | |
debugger, | |
"e -l swift -O -- {0}".format(swift_name) | |
) | |
# Execute a Swift source file | |
# Usage: execute_swift <path> | |
# E.g., | |
# execute_swift ~/MySwiftUtilities.swift | |
@lldb.command("execute_swift") | |
def execute_swift(debugger, path, ctx, result, _): | |
with open(os.path.expanduser(path)) as f: | |
contents = f.read() | |
print(contents) | |
options = lldb.SBExpressionOptions() | |
options.SetLanguage(lldb.eLanguageTypeSwift) | |
ctx.frame.EvaluateExpression(contents, options) | |
# _execute_lldb(debugger, "expression -l swift -- {0}".format(contents)) | |
def index_path_summary(value, internal_dict): | |
frame = value.GetFrame() | |
name = value.GetName() | |
section = frame.EvaluateExpression("{0}.section".format(name)).GetValueAsSigned() | |
item = frame.EvaluateExpression("{0}.item".format(name)).GetValueAsSigned() | |
return "(Section: {0}, Item: {1})".format(section, item) | |
def _get_value(sb_value): | |
# Trim trailing newline and enclosing double quotes. | |
return sb_value.description[1:-2] | |
def _execute_lldb(debugger, command): | |
print(command) | |
debugger.HandleCommand(command) | |
def __lldb_init_module(debugger, internal_dict): | |
debugger.HandleCommand("type summary add -F " + __name__ + ".index_path_summary IndexPath") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MIT License | |
Copyright (c) 2022 Kevin Beaulieu | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
SOFTWARE. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment