SlideShare a Scribd company logo
Advanced Debugging With XCode
Extending LLDB
Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
Aijaz
@_aijaz_
360|iDev
(Since 1982)
😱
Debug
Sample
Project
360|iDev
360|iDev
Session
id: String
title: String?
sessionDescription: String?
startTime: Date
endTime: Date
speaker: Speaker?
startDate: String
init?(withId id: String)
Speaker
id: String
name: String
imagePath: String?
bio: String?
twitterHandle: String?
website: String?
sessions: [Session]
init?(withId id: String)
speaker
sessions
Demo 1
Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
Let’s Recap
# In ~/.lldbinit, available to all LLDB sessions
type summary add --summary-string 
"(${var._indexes[0]}, ${var._indexes[1]})" IndexPath
type summary add --summary-string 
"${var.title} by ${var.speaker.name}" MyConf.Session
Quick & Dirty Type Summaries
Summaries in Python
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format ()
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
title = valobj.GetChildMemberWithName('title')
name = valobj.GetChildMemberWithName(‘speaker’)
.GetChildMemberWithName('name')
return stripQuotes(title.GetObjectDescription())
+ " by " + 
stripQuotes(name.GetObjectDescription())
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
title = valobj.GetChildMemberWithName('title')
name = valobj.GetChildMemberWithName(‘speaker’)
.GetChildMemberWithName('name')
return stripQuotes(title.GetObjectDescription())
+ " by " + 
stripQuotes(name.GetObjectDescription())
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
title = valobj.GetChildMemberWithName('title')
name = valobj.GetChildMemberWithName(‘speaker’)
.GetChildMemberWithName('name')
return stripQuotes(title.GetObjectDescription())
+ " by " + 
stripQuotes(name.GetObjectDescription())
def __lldb_init_module(debugger, dict):
command = 'type summary add —-python-function 
sessionFormatter.format MyConf.Session'
debugger.HandleCommand(command)
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
title = valobj.GetChildMemberWithName('title')
name = valobj.GetChildMemberWithName(‘speaker’)
.GetChildMemberWithName('name')
return stripQuotes(title.GetObjectDescription())
+ " by " + 
stripQuotes(name.GetObjectDescription())
def __lldb_init_module(debugger, dict):
command = 'type summary add —-python-function 
sessionFormatter.format MyConf.Session'
debugger.HandleCommand(command)
sessionFormatter.py
#!/usr/bin/python
import re
regex = re.compile('[^"]*"(.*)"n$')
def stripQuotes(str):
"""Utility method to strip the first and last quote
and anything outside them"""
match = regex.match(str)
if match :
return match.group(1)
return str
def format (valobj,internal_dict):
title = valobj.GetChildMemberWithName('title')
name = valobj.GetChildMemberWithName(‘speaker’)
.GetChildMemberWithName('name')
return stripQuotes(title.GetObjectDescription())
+ " by " + 
stripQuotes(name.GetObjectDescription())
def __lldb_init_module(debugger, dict):
command = 'type summary add —-python-function 
sessionFormatter.format MyConf.Session'
debugger.HandleCommand(command)
sessionFormatter.py
command script import …/sessionFormatter.py
# Add things here, like type summaries, breakpoints
# Even execute Swift or Objective-C code with 'expr'
.lldbinit-MyConf
Project-Specific Loading
in main() or application(_:didFinishLaunchingWithOptions:)
Any
Questions?
{ "version": 1,
"speakers": [
{"id": 3,
"img": “chad.jpg",
"name": “Chad Perk",
"twitter": "chad",
"blog": “www.example.com/chad”,
"bio": "Chad is the co-author of…”
},
jq
http://feelgrafix.com/data_images/out/28/973590-avatar-the-last-airbender.jpg
$ cat avatar.json
[{"name":"Aang","sex":"M","born":-12,"died":153,"bending":["Air","Water","Earth","Fire","Energy"],"identity":
{"nationality":"Southern Air Temple","ethnicity":"Air Nomad"},"spouse":"Katara","children":[{"sex":"M","name":"Bumi"},
{"sex":"F","name":"Kya"},{"sex":"M","name":"Tenzin"}]},{"name":"Katara","sex":"F","born":85,"died":null,"bending":
["Water","Blood"],"identity":{"nationality":"Southern Water Tribe","ethnicity":"Water Tribe"},"spouse":"Aang","children":
[{"sex":"M","name":"Bumi"},{"sex":"F","name":"Kya"},{"sex":"M","name":"Tenzin"}]},{"name":"Sokka","sex":"M","born":84,"died":
164,"bending":[],"identity":{"nationality":"Southern Water Tribe","ethnicity":"Water Tribe"},"spouse":null,"children":[]},
{"name":"Toph Beifong","sex":"F","born":88,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Gaoling, Earth
Kingdom","ethnicity":"Earth Kingdom"},"spouse":null,"children":[{"sex":"F","name":"Lin Beifong"},{"sex":"F","name":"Suyin
Beifong"}]},{"name":"Iroh","sex":"M","born":null,"died":null,"bending":["Fire","Energy"],"identity":{"nationality":"Fire Nation
Capital, Fire Nation","ethnicity":"Fire Nation"},"spouse":null,"children":[{"sex":"M","name":"Lu Ten"}]},
{"name":"Zuko","sex":"M","born":83,"died":null,"bending":["Fire","Energy"],"identity":{"nationality":"Fire Nation Capital, Fire
Nation","ethnicity":"Fire Nation"},"spouse":null,"children":[{"sex":"F","name":"Izumi"}]},
{"name":"Kya","sex":"F","born":null,"died":null,"bending":["Water"],"identity":{"nationality":"Southern Water
Tribe","ethnicity":"Water Tribe, Air Nomad"},"spouse":null,"children":[]},
{"name":"Bumi","sex":"M","born":null,"died":null,"bending":["Air"],"identity":{"nationality":"United Republic","ethnicity":"Water
Tribe, Air Nomad"},"spouse":null,"children":[]},{"name":"Tenzin","sex":"M","born":null,"died":null,"bending":["Air"],"identity":
{"nationality":"Republic City, United Republic","ethnicity":"Water Tribe, Air Nomad"},"spouse":null,"children":
[{"sex":"F","name":"Jinora"},{"sex":"F","name":"Ikki"},{"sex":"M","name":"Meelo"},{"sex":"M","name":"Rohan"}]},{"name":"Lin
Beifong","sex":"F","born":120,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Republic City, United
Republic","ethnicity":"Earth Kingdom"},"spouse":null,"children":[]},{"name":"Suyin Beifong","sex":"F","born":
126,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Republic City, United Republic","ethnicity":"Earth
Kingdom"},"spouse":null,"children":[{"sex":"M","name":"Bataar Jr."},{"sex":"F","name":"Opal"},{"sex":"M","name":"Wei"},
{"sex":"M","name":"Wing"},{"sex":"M","name":"Huan"}]}]
$
# Pretty print the jq
$ jq '.' avatar.json
command input filefilter
# Pretty print the jq
$ jq '.' avatar.json
...
{
"sex": "M",
"name": "Huan"
}
]
}
]
$
# Pretty print the jq
$ jq '.' avatar.json
...
{
"sex": "M",
"name": "Huan"
}
]
}
]
$
# The ']' on the last line tells me this is an array
# Pretty print the jq
$ jq '.' avatar.json
...
{
"sex": "M",
"name": "Huan"
}
]
}
]
$
# The ']' on the last line tells me this is an array
# The '}' on the 2nd-last line tells me this is an array of objects
# List the keys of each object
$ jq ' .[] | keys ' avatar.json
foreach item in array print the keys of each object
pipe the output of one filter into the input of the next
# List the keys of each object
$ jq ' .[] | keys ' avatar.json
[
"bending",
"born",
"children",
"died",
"identity",
"name",
"sex",
"spouse"
]
[
"bending",
"born",…
$
# The name of each character
$ jq ' .[] | .name ' avatar.json
foreach item in array extract the ‘name’ field
# The name of each character
$ jq ‘.[] | .name’ avatar.json
"Aang"
"Katara"
"Sokka"
"Toph Beifong"
"Iroh"
"Zuko"
"Kya"
"Bumi"
"Tenzin"
"Lin Beifong"
$
# The name of each female character
$ jq ' .[] | select(.sex == "F") | .name ' avatar.json
foreach item in array
extract the ‘name’ field
where sex is F
# The name of each female character
$ jq ' .[] | select(.sex == "F") | .name ' avatar.json
"Katara"
"Toph Beifong"
"Kya"
"Lin Beifong"
"Suyin Beifong”
$
Demo 2
Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
(lldb) jq ‘.speakers[]|keys’ jsonString
jq filter (program) String
1. Gather input
2. Run the jq filter on the string, saving the output
3. Print the output
#!/usr/bin/python
import commands
import lldb
import shlex
#!/usr/bin/python
import commands
import lldb
import shlex
# The actual python function that is bound to the lldb command.
def jq_command(debugger, command, result, dict):
def jq_command(debugger, command, result, dict):
def jq_command(debugger, command, result, dict):
target = debugger.GetSelectedTarget()
def jq_command(debugger, command, result, dict):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
def jq_command(debugger, command, result, dict):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
def jq_command(debugger, command, result, dict):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry
about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>"
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry
about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq
will be invoked on the file, not using stdin
jq_json_file = “/tmp/jq_json"
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
f = open(jq_filter_file, 'w')
f.write(jq_filter)
f.close()
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
f = open(jq_filter_file, 'w')
f.write(jq_filter)
f.close()
# invoke jq and capture the output
output = commands.getoutput("%s -f %s %s" % (
jq_exe, jq_filter_file, jq_json_file) )
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
f = open(jq_filter_file, 'w')
f.write(jq_filter)
f.close()
# invoke jq and capture the output
output = commands.getoutput("%s -f %s %s" % (
jq_exe, jq_filter_file, jq_json_file) )
print >>result, output
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
f = open(jq_filter_file, 'w')
f.write(jq_filter)
f.close()
# invoke jq and capture the output
output = commands.getoutput("%s -f %s %s" % (
jq_exe, jq_filter_file, jq_json_file) )
print >>result, output
Gather Input
Run Command
Print Output
def jq_command(debugger, command, result, dict):
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
# The command is called like "jq <filter> <stringVar>”
command_args = shlex.split(command)
jq_filter = command_args[0]
val = frame.var(command_args[1]) # access the variable
val_string = eval(val.GetObjectDescription())
# path to the jq executable.
jq_exe = "/Users/aijaz/local/bin/jq"
# We save the filter to a file so that we don’t have to worry about escaping special characters.
jq_filter_file = "/tmp/jq_filter"
# the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin
jq_json_file = "/tmp/jq_json"
# write the json file and jq filter to temp files
f = open(jq_json_file, 'w')
f.write(val_string)
f.close()
f = open(jq_filter_file, 'w')
f.write(jq_filter)
f.close()
# invoke jq and capture the output
output = commands.getoutput("%s -f %s %s" % (
jq_exe, jq_filter_file, jq_json_file) )
print >>result, output
def __lldb_init_module(debugger, dict):
# Add any commands contained in this module to LLDB
command = 'command script add -f jq.jq_command jq'
debugger.HandleCommand(command)
What have
we learned?
Validate your
hypothesis
(if you’re lucky enough to have a hypothesis.)
Observe
Analyze
Extend
Any
Questions?
https://github.com/aijaz/lldbPythonScripts
http://aijaz.net/2017/01/11/lldb-python/index.html
https://github.com/facebook/chisel
LLDB: https://lldb.llvm.org/
A blog post from January, where I write about most of the same stuff:
Extending LLDB: http://aijaz.net/2017/01/11/lldb-python/index.html
JQ
jq: https://stedolan.github.io/jq/
A Facebook library that adds a lot of cool extensions to LLDB
Facebook Chisel: https://github.com/facebook/chisel
WWDC Sessions:
Debugging Tips and Tricks https://developer.apple.com/videos/play/wwdc2016/417/
What’s new in LLDB: https://developer.apple.com/videos/play/wwdc2015/402/
Introduction to LLDB and the Swift REPL https://developer.apple.com/videos/play/wwdc2014/409/
Advanced Swift Debugging in LLDB https://developer.apple.com/videos/play/wwdc2014/410/
Debugging in Xcode 6 https://developer.apple.com/videos/play/wwdc2014/413/
Debugging with Xcode https://developer.apple.com/videos/play/wwdc2013/407/
* Advanced Debugging with LLDB https://developer.apple.com/videos/play/wwdc2013/413/
* Debugging in Xcode https://developer.apple.com/videos/play/wwdc2012/412/
* Debugging with Xcode https://developer.apple.com/videos/play/wwdc2012/415/
*: Contains material related to this talk
Thank You!
https://www.theodysseyonline.com/overthinking-spongebob
@_aijaz_

More Related Content

PDF
Introduction to Rust
PDF
The Rust Programming Language: an Overview
PPTX
Groovy grails types, operators, objects
PDF
GR8Conf 2011: Effective Groovy
PPTX
ES6 in Real Life
PDF
(Greach 2015) Dsl'ing your Groovy
PDF
Why rust?
PPTX
C# 7.0 Hacks and Features
Introduction to Rust
The Rust Programming Language: an Overview
Groovy grails types, operators, objects
GR8Conf 2011: Effective Groovy
ES6 in Real Life
(Greach 2015) Dsl'ing your Groovy
Why rust?
C# 7.0 Hacks and Features

What's hot (18)

PDF
Functional Programming with Groovy
PDF
Advanced Python, Part 1
PPTX
Introduction to Gremlin
PDF
The Ring programming language version 1.5.4 book - Part 40 of 185
PDF
From android/java to swift (3)
PPTX
Python lec4
ODP
Ast transformations
PPTX
Groovy
ODP
Naïveté vs. Experience
PDF
How to Clone Flappy Bird in Swift
PDF
Designing with Groovy Traits - Gr8Conf India
PDF
Madrid gug - sacando partido a las transformaciones ast de groovy
KEY
groovy & grails - lecture 3
PDF
#살아있다 #자프링외길12년차 #코프링2개월생존기
PDF
Generics and Inference
PDF
PDF
Rust Mozlando Tutorial
PDF
Dynamic C++ Silicon Valley Code Camp 2012
Functional Programming with Groovy
Advanced Python, Part 1
Introduction to Gremlin
The Ring programming language version 1.5.4 book - Part 40 of 185
From android/java to swift (3)
Python lec4
Ast transformations
Groovy
Naïveté vs. Experience
How to Clone Flappy Bird in Swift
Designing with Groovy Traits - Gr8Conf India
Madrid gug - sacando partido a las transformaciones ast de groovy
groovy & grails - lecture 3
#살아있다 #자프링외길12년차 #코프링2개월생존기
Generics and Inference
Rust Mozlando Tutorial
Dynamic C++ Silicon Valley Code Camp 2012
Ad

Similar to 360|iDev (20)

PDF
Beyond Breakpoints: Advanced Debugging with XCode
PDF
Advanced Debugging with Xcode - Extending LLDB
PDF
Spring Framework - Expression Language
PDF
Grammarware Memes
ODP
AST Transformations
PDF
Automatically Spotting Cross-language Relations
KEY
Introduction to Groovy
PDF
Python basic
ODP
Groovy Ast Transformations (greach)
PDF
Functional Scala 2020
PDF
Type safe embedded domain-specific languages
PDF
Stupid Awesome Python Tricks
PDF
Swift와 Objective-C를 함께 쓰는 방법
PDF
Clojure for Java developers - Stockholm
PDF
Refactoring to Macros with Clojure
KEY
jRuby: The best of both worlds
PDF
WordCamp Portland 2018: PHP for WordPress
PDF
Kotlin Basics - Apalon Kotlin Sprint Part 2
ODP
Groovy intro for OUDL
Beyond Breakpoints: Advanced Debugging with XCode
Advanced Debugging with Xcode - Extending LLDB
Spring Framework - Expression Language
Grammarware Memes
AST Transformations
Automatically Spotting Cross-language Relations
Introduction to Groovy
Python basic
Groovy Ast Transformations (greach)
Functional Scala 2020
Type safe embedded domain-specific languages
Stupid Awesome Python Tricks
Swift와 Objective-C를 함께 쓰는 방법
Clojure for Java developers - Stockholm
Refactoring to Macros with Clojure
jRuby: The best of both worlds
WordCamp Portland 2018: PHP for WordPress
Kotlin Basics - Apalon Kotlin Sprint Part 2
Groovy intro for OUDL
Ad

Recently uploaded (20)

PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
PDF
Download FL Studio Crack Latest version 2025 ?
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Cost to Outsource Software Development in 2025
PPTX
history of c programming in notes for students .pptx
PDF
CapCut Video Editor 6.8.1 Crack for PC Latest Download (Fully Activated) 2025
PPTX
assetexplorer- product-overview - presentation
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
PDF
17 Powerful Integrations Your Next-Gen MLM Software Needs
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Designing Intelligence for the Shop Floor.pdf
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Complete Guide to Website Development in Malaysia for SMEs
PDF
Design an Analysis of Algorithms II-SECS-1021-03
Reimagine Home Health with the Power of Agentic AI​
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
CHAPTER 2 - PM Management and IT Context
Autodesk AutoCAD Crack Free Download 2025
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
Download FL Studio Crack Latest version 2025 ?
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Cost to Outsource Software Development in 2025
history of c programming in notes for students .pptx
CapCut Video Editor 6.8.1 Crack for PC Latest Download (Fully Activated) 2025
assetexplorer- product-overview - presentation
iTop VPN Free 5.6.0.5262 Crack latest version 2025
17 Powerful Integrations Your Next-Gen MLM Software Needs
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Designing Intelligence for the Shop Floor.pdf
Advanced SystemCare Ultimate Crack + Portable (2025)
Salesforce Agentforce AI Implementation.pdf
Operating system designcfffgfgggggggvggggggggg
Complete Guide to Website Development in Malaysia for SMEs
Design an Analysis of Algorithms II-SECS-1021-03

360|iDev

  • 1. Advanced Debugging With XCode Extending LLDB Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
  • 9. Session id: String title: String? sessionDescription: String? startTime: Date endTime: Date speaker: Speaker? startDate: String init?(withId id: String) Speaker id: String name: String imagePath: String? bio: String? twitterHandle: String? website: String? sessions: [Session] init?(withId id: String) speaker sessions
  • 11. Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
  • 13. # In ~/.lldbinit, available to all LLDB sessions type summary add --summary-string "(${var._indexes[0]}, ${var._indexes[1]})" IndexPath type summary add --summary-string "${var.title} by ${var.speaker.name}" MyConf.Session Quick & Dirty Type Summaries
  • 15. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') sessionFormatter.py
  • 16. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str sessionFormatter.py
  • 17. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str sessionFormatter.py
  • 18. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format () sessionFormatter.py
  • 19. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): sessionFormatter.py
  • 20. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): title = valobj.GetChildMemberWithName('title') name = valobj.GetChildMemberWithName(‘speaker’) .GetChildMemberWithName('name') return stripQuotes(title.GetObjectDescription()) + " by " + stripQuotes(name.GetObjectDescription()) sessionFormatter.py
  • 21. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): title = valobj.GetChildMemberWithName('title') name = valobj.GetChildMemberWithName(‘speaker’) .GetChildMemberWithName('name') return stripQuotes(title.GetObjectDescription()) + " by " + stripQuotes(name.GetObjectDescription()) sessionFormatter.py
  • 22. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): title = valobj.GetChildMemberWithName('title') name = valobj.GetChildMemberWithName(‘speaker’) .GetChildMemberWithName('name') return stripQuotes(title.GetObjectDescription()) + " by " + stripQuotes(name.GetObjectDescription()) def __lldb_init_module(debugger, dict): command = 'type summary add —-python-function sessionFormatter.format MyConf.Session' debugger.HandleCommand(command) sessionFormatter.py
  • 23. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): title = valobj.GetChildMemberWithName('title') name = valobj.GetChildMemberWithName(‘speaker’) .GetChildMemberWithName('name') return stripQuotes(title.GetObjectDescription()) + " by " + stripQuotes(name.GetObjectDescription()) def __lldb_init_module(debugger, dict): command = 'type summary add —-python-function sessionFormatter.format MyConf.Session' debugger.HandleCommand(command) sessionFormatter.py
  • 24. #!/usr/bin/python import re regex = re.compile('[^"]*"(.*)"n$') def stripQuotes(str): """Utility method to strip the first and last quote and anything outside them""" match = regex.match(str) if match : return match.group(1) return str def format (valobj,internal_dict): title = valobj.GetChildMemberWithName('title') name = valobj.GetChildMemberWithName(‘speaker’) .GetChildMemberWithName('name') return stripQuotes(title.GetObjectDescription()) + " by " + stripQuotes(name.GetObjectDescription()) def __lldb_init_module(debugger, dict): command = 'type summary add —-python-function sessionFormatter.format MyConf.Session' debugger.HandleCommand(command) sessionFormatter.py
  • 25. command script import …/sessionFormatter.py # Add things here, like type summaries, breakpoints # Even execute Swift or Objective-C code with 'expr' .lldbinit-MyConf
  • 26. Project-Specific Loading in main() or application(_:didFinishLaunchingWithOptions:)
  • 28. { "version": 1, "speakers": [ {"id": 3, "img": “chad.jpg", "name": “Chad Perk", "twitter": "chad", "blog": “www.example.com/chad”, "bio": "Chad is the co-author of…” },
  • 29. jq
  • 31. $ cat avatar.json [{"name":"Aang","sex":"M","born":-12,"died":153,"bending":["Air","Water","Earth","Fire","Energy"],"identity": {"nationality":"Southern Air Temple","ethnicity":"Air Nomad"},"spouse":"Katara","children":[{"sex":"M","name":"Bumi"}, {"sex":"F","name":"Kya"},{"sex":"M","name":"Tenzin"}]},{"name":"Katara","sex":"F","born":85,"died":null,"bending": ["Water","Blood"],"identity":{"nationality":"Southern Water Tribe","ethnicity":"Water Tribe"},"spouse":"Aang","children": [{"sex":"M","name":"Bumi"},{"sex":"F","name":"Kya"},{"sex":"M","name":"Tenzin"}]},{"name":"Sokka","sex":"M","born":84,"died": 164,"bending":[],"identity":{"nationality":"Southern Water Tribe","ethnicity":"Water Tribe"},"spouse":null,"children":[]}, {"name":"Toph Beifong","sex":"F","born":88,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Gaoling, Earth Kingdom","ethnicity":"Earth Kingdom"},"spouse":null,"children":[{"sex":"F","name":"Lin Beifong"},{"sex":"F","name":"Suyin Beifong"}]},{"name":"Iroh","sex":"M","born":null,"died":null,"bending":["Fire","Energy"],"identity":{"nationality":"Fire Nation Capital, Fire Nation","ethnicity":"Fire Nation"},"spouse":null,"children":[{"sex":"M","name":"Lu Ten"}]}, {"name":"Zuko","sex":"M","born":83,"died":null,"bending":["Fire","Energy"],"identity":{"nationality":"Fire Nation Capital, Fire Nation","ethnicity":"Fire Nation"},"spouse":null,"children":[{"sex":"F","name":"Izumi"}]}, {"name":"Kya","sex":"F","born":null,"died":null,"bending":["Water"],"identity":{"nationality":"Southern Water Tribe","ethnicity":"Water Tribe, Air Nomad"},"spouse":null,"children":[]}, {"name":"Bumi","sex":"M","born":null,"died":null,"bending":["Air"],"identity":{"nationality":"United Republic","ethnicity":"Water Tribe, Air Nomad"},"spouse":null,"children":[]},{"name":"Tenzin","sex":"M","born":null,"died":null,"bending":["Air"],"identity": {"nationality":"Republic City, United Republic","ethnicity":"Water Tribe, Air Nomad"},"spouse":null,"children": [{"sex":"F","name":"Jinora"},{"sex":"F","name":"Ikki"},{"sex":"M","name":"Meelo"},{"sex":"M","name":"Rohan"}]},{"name":"Lin Beifong","sex":"F","born":120,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Republic City, United Republic","ethnicity":"Earth Kingdom"},"spouse":null,"children":[]},{"name":"Suyin Beifong","sex":"F","born": 126,"died":null,"bending":["Earth","Metal"],"identity":{"nationality":"Republic City, United Republic","ethnicity":"Earth Kingdom"},"spouse":null,"children":[{"sex":"M","name":"Bataar Jr."},{"sex":"F","name":"Opal"},{"sex":"M","name":"Wei"}, {"sex":"M","name":"Wing"},{"sex":"M","name":"Huan"}]}] $
  • 32. # Pretty print the jq $ jq '.' avatar.json command input filefilter
  • 33. # Pretty print the jq $ jq '.' avatar.json ... { "sex": "M", "name": "Huan" } ] } ] $
  • 34. # Pretty print the jq $ jq '.' avatar.json ... { "sex": "M", "name": "Huan" } ] } ] $ # The ']' on the last line tells me this is an array
  • 35. # Pretty print the jq $ jq '.' avatar.json ... { "sex": "M", "name": "Huan" } ] } ] $ # The ']' on the last line tells me this is an array # The '}' on the 2nd-last line tells me this is an array of objects
  • 36. # List the keys of each object $ jq ' .[] | keys ' avatar.json foreach item in array print the keys of each object pipe the output of one filter into the input of the next
  • 37. # List the keys of each object $ jq ' .[] | keys ' avatar.json [ "bending", "born", "children", "died", "identity", "name", "sex", "spouse" ] [ "bending", "born",… $
  • 38. # The name of each character $ jq ' .[] | .name ' avatar.json foreach item in array extract the ‘name’ field
  • 39. # The name of each character $ jq ‘.[] | .name’ avatar.json "Aang" "Katara" "Sokka" "Toph Beifong" "Iroh" "Zuko" "Kya" "Bumi" "Tenzin" "Lin Beifong" $
  • 40. # The name of each female character $ jq ' .[] | select(.sex == "F") | .name ' avatar.json foreach item in array extract the ‘name’ field where sex is F
  • 41. # The name of each female character $ jq ' .[] | select(.sex == "F") | .name ' avatar.json "Katara" "Toph Beifong" "Kya" "Lin Beifong" "Suyin Beifong” $
  • 43. Image by Aijaz Ansari. Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
  • 44. (lldb) jq ‘.speakers[]|keys’ jsonString jq filter (program) String 1. Gather input 2. Run the jq filter on the string, saving the output 3. Print the output
  • 46. #!/usr/bin/python import commands import lldb import shlex # The actual python function that is bound to the lldb command. def jq_command(debugger, command, result, dict):
  • 48. def jq_command(debugger, command, result, dict): target = debugger.GetSelectedTarget()
  • 49. def jq_command(debugger, command, result, dict): target = debugger.GetSelectedTarget() process = target.GetProcess()
  • 50. def jq_command(debugger, command, result, dict): target = debugger.GetSelectedTarget() process = target.GetProcess() thread = process.GetSelectedThread()
  • 51. def jq_command(debugger, command, result, dict): target = debugger.GetSelectedTarget() process = target.GetProcess() thread = process.GetSelectedThread() frame = thread.GetSelectedFrame()
  • 52. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
  • 53. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command)
  • 54. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command)
  • 55. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0]
  • 56. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable
  • 57. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription())
  • 58. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq"
  • 59. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter"
  • 60. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>" command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = “/tmp/jq_json"
  • 61. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close()
  • 62. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close() f = open(jq_filter_file, 'w') f.write(jq_filter) f.close()
  • 63. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close() f = open(jq_filter_file, 'w') f.write(jq_filter) f.close() # invoke jq and capture the output output = commands.getoutput("%s -f %s %s" % ( jq_exe, jq_filter_file, jq_json_file) )
  • 64. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close() f = open(jq_filter_file, 'w') f.write(jq_filter) f.close() # invoke jq and capture the output output = commands.getoutput("%s -f %s %s" % ( jq_exe, jq_filter_file, jq_json_file) ) print >>result, output
  • 65. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close() f = open(jq_filter_file, 'w') f.write(jq_filter) f.close() # invoke jq and capture the output output = commands.getoutput("%s -f %s %s" % ( jq_exe, jq_filter_file, jq_json_file) ) print >>result, output Gather Input Run Command Print Output
  • 66. def jq_command(debugger, command, result, dict): frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() # The command is called like "jq <filter> <stringVar>” command_args = shlex.split(command) jq_filter = command_args[0] val = frame.var(command_args[1]) # access the variable val_string = eval(val.GetObjectDescription()) # path to the jq executable. jq_exe = "/Users/aijaz/local/bin/jq" # We save the filter to a file so that we don’t have to worry about escaping special characters. jq_filter_file = "/tmp/jq_filter" # the value of the NSString variable is saved in this file jq will be invoked on the file, not using stdin jq_json_file = "/tmp/jq_json" # write the json file and jq filter to temp files f = open(jq_json_file, 'w') f.write(val_string) f.close() f = open(jq_filter_file, 'w') f.write(jq_filter) f.close() # invoke jq and capture the output output = commands.getoutput("%s -f %s %s" % ( jq_exe, jq_filter_file, jq_json_file) ) print >>result, output def __lldb_init_module(debugger, dict): # Add any commands contained in this module to LLDB command = 'command script add -f jq.jq_command jq' debugger.HandleCommand(command)
  • 69. (if you’re lucky enough to have a hypothesis.)
  • 75. LLDB: https://lldb.llvm.org/ A blog post from January, where I write about most of the same stuff: Extending LLDB: http://aijaz.net/2017/01/11/lldb-python/index.html JQ jq: https://stedolan.github.io/jq/ A Facebook library that adds a lot of cool extensions to LLDB Facebook Chisel: https://github.com/facebook/chisel WWDC Sessions: Debugging Tips and Tricks https://developer.apple.com/videos/play/wwdc2016/417/ What’s new in LLDB: https://developer.apple.com/videos/play/wwdc2015/402/ Introduction to LLDB and the Swift REPL https://developer.apple.com/videos/play/wwdc2014/409/ Advanced Swift Debugging in LLDB https://developer.apple.com/videos/play/wwdc2014/410/ Debugging in Xcode 6 https://developer.apple.com/videos/play/wwdc2014/413/ Debugging with Xcode https://developer.apple.com/videos/play/wwdc2013/407/ * Advanced Debugging with LLDB https://developer.apple.com/videos/play/wwdc2013/413/ * Debugging in Xcode https://developer.apple.com/videos/play/wwdc2012/412/ * Debugging with Xcode https://developer.apple.com/videos/play/wwdc2012/415/ *: Contains material related to this talk