WWDC 2014 이후의 발전내용
이름이 고유할 필요는 없고, 한 breakpoint가 여러 이름을 가져도 된다.
커맨드에서는 이 이름을 받아서 사용한다.
이름 설정
breakpoint set -N name
br s -N name
br s -N name -N name // 여러개 이름 지정 가능
이름 가지고 다루기
breakpoint set -N name
br s -N name
breakpoint enable name
br e name
breakpoint disable name
br di name
breakpoint delete name
br de name
lldbinit 파일에서 모든 타겟이 공유하는 breakpoint를 만들 수도 있다.
breakpoint set -n malloc -N memory
breakpoint set -n free -N memory
breakpoint disable memory // 나중에 필요할 때 enable시킨다.
Xcode 7에서 처음 들어가는 기능
표현식 평가 개선
데이터 포매팅 개선
Address sanitizer 통합
메모리에 대해서 질의할 수 있다.
memory history
m h
memory read
m r
memory write
m w
memory find
m f
type lookup 명령 추가
(lldb) type lookup ErrorType
protocol ErrorType {
var _domain: Swift.String { get }
var _code: Swift.Int { get }
}
(lldb) type lookup Comparable
protocol Comparable: _Comparable, Equatable {
func <=(lhs: Self, rhs: Self) -> Swift.Bool
func >=(lhs: Self, rhs: Self) -> Swift.Bool
func >(lhs: Self, rhs: Self) -> Swift.Bool
}
ty l
Compilers in LLDB
컴파일러는 LLDB에서 중요한 부분이다.
swift 코드 실행시키기
p는 ex --
의 alias다.
--
는 더이상 옵션이 없음을 명시하는 것이다.
(lldb) p for i in (0..<5) { print(i) }
0
1
2
3
4
swift 코드를 실행 가능하다는 것은, 디버거를 통해서 실행중인 프로그램에 코드를 주입할 수 있다는 것이다.
게다가 프로그램에 정의된 데이터에도 접근할 수 있다.
(lldb) p for i in (0..<3) { print(names[i]) }
Kate
Sean
Enrico
다른 SDK에 있는 코드를 실행시킬수도 있다.
LLDB가 해당 코드를 포함하는 SDK 모듈을 찾아서, 안의 컴파일러가 접근할 수 있도록 한다.
컴파일러가 해당 코드를 찾아서 평가한다.
(lldb) p NSApplication.sharedApplication()
(NSApplication) $R1 = 0x0000600000100240 {
AppKit.NSResponder = {
NSObject = {
isa = NSApplication
}
_nextResponder = nil-
}
}
이 모든 게 Swift에서는 자동으로 이뤄진다.
Objective-C 코드 실행하기
Swift에서는 자동으로 되던게, Objective-C에서는 안되는 경우가 있다.
(lldb) p NSLog(@"%d", i)
error: 'NSLog' has unknown return type;
cast the call to its declared return type
error: 1 errors parsing expression
이는 SDK에 NSLog 정의가 있는데, LLDB가 이걸 못보고 심볼의 디버그 정보만 보기 때문이다.
이번에 수정해서 위 명령어가 정상적으로 돌아간다.
근데 일부는 아예 심볼을 못찾기도 한다.
(lldb) p NSMakeRect(0, 0, 10, 10)
error: use of undeclared identifier "NSMakeRect"
eror: 1 errors parsing expression
이는 inline으로 정의되어 있기 때문에, LLDB에서는 아무것도 못보기 때문이다.
NS_INLINE NSRect NSMakeRect(
CGFloat, CGFloat, CGFloat, CGFloat)
이것도 이번에 수정해서 동작한다.
sharedApplication의 프로퍼티를 접근해보자. 이번에도 잘 안된다.
(lldb) p [NSApplication sharedApplication].undoManager
error: property 'undoManager' not found on object of type 'id'
error: 1 errors parsing expression
이제는 잘 나온다. 게다가 nullable여부까지 나온다.
원래 LLDB에서 됐던 것과 안됐던 것들
이제는 모두 지원한다.
import 한번만 해주면
expr @import AppKit
expr @import UIKit
Swift error-handling support
throws가 되는 함수를 할때도 try를 붙이지 않아도 된다.
에러가 나오면 자동으로 출력해준다.
(lldb) expr ThisFunctionThrows()
(a.EnumError) $E0 = SeriousError
당연히 REPL에서도 try 안붙여도 된다.
1> ThisFunctionThrows()
$E0 = SeriousError
근데 무슨 에러가 던져졌는지 보다는 어디서 에러가 던져졌는지 알고 싶다.
에러가 던져질 때마다 breakpoint를 걸 수 있다.
objc exception
breakpoint set -E objc
br s -E objc
swift error
breakpoint set -E swift
br s -E swift
특정 타입의 에러에 대해서만 멈추기(Swift 전용)
br -s -E Swift -O EnumError
breakpoint에서 다시 시작할 때는
continue
Presentation is Everything
formatted data is comprehended data
관련 명령어
fr v(frame variable)
Xcode variables View가 쓰는 것
로컬 변수를 출력해준다.
(lldb) frame variable
(Int, String) myTuple = (0 = 12, 1 = "Hello World") // 0, 1은 children이라고 부른다.
(Int) theYear = 1984
(lldb) frame variable theYear
(Int) theYear = 1984
(lldb) frame variable --format hex theYear
(Int) theYear = 0x00000000000007c0
p(ex —)
(lldb) p theYear + 1
(Int) $R0 = 1985
(lldb) p String($R0 + 1)
(String) $R1 = "1986"
(lldb) expr --format hex -- [1,2,3]
([Int]) $R0 = 3 values {
[0] = 0x0000000000000001 // children
[1] = 0x0000000000000002 // children
[2] = 0x0000000000000003 // children
}
po(ex -O —)
(lldb) po [[MyView alloc] initWithFrame: myFrame]
<MyView: 0x101405110>
(lldb) po @[@1, @2, @3]
<__NSArrayI, 0x10050b2a0>(
1,
2,
3
)
(lldb) po @"Hello World"
Hello World
명령어 비교
LLDB formatter