kkbox wwdc17 xcode debug - oliver

56
Xcode - Debug KKBOX WWDC 2017 Study Oliver Huang iOS Engineer

Upload: liyao-chen

Post on 22-Jan-2018

2.105 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: KKBOX WWDC17  Xcode debug - Oliver

Xcode - DebugKKBOX WWDC 2017 Study

Oliver Huang iOS Engineer

Page 2: KKBOX WWDC17  Xcode debug - Oliver

Related Video Sessions

404 - Debugging with Xcode 9https://developer.apple.com/videos/play/wwdc2017/404/

406 - Finding Bugs Using Xcode Runtime Toolshttps://developer.apple.com/videos/play/wwdc2017/406/

407 - Understanding Undefined Behaviorhttps://developer.apple.com/videos/play/wwdc2017/407/

411 - What's New in LLVMhttps://developer.apple.com/videos/play/wwdc2017/411/

Page 3: KKBOX WWDC17  Xcode debug - Oliver

Debugging with Xcode 9

• Development: Unplugged (Wireless Development)

• Breakpoint Workflow Enhancements

• Debug View Hierarchy Improvements

Page 4: KKBOX WWDC17  Xcode debug - Oliver
Page 5: KKBOX WWDC17  Xcode debug - Oliver

Wireless Development NEW

Page 6: KKBOX WWDC17  Xcode debug - Oliver

Wireless Development

• Minimum requirement

- iOS 11, tvOS 11, macOS 10.12.4+

• Tools support

- Xcode, Instruments, Accessibility Inspector, Console, Configurator

- (tvOS only) Safari Web Inspector for TVMLKit, QuickTime Screen Recording

Page 7: KKBOX WWDC17  Xcode debug - Oliver

Demo

Page 8: KKBOX WWDC17  Xcode debug - Oliver
Page 9: KKBOX WWDC17  Xcode debug - Oliver

Wireless Development tvOS device pairing

Page 10: KKBOX WWDC17  Xcode debug - Oliver

Breakpoint Workflow Enhancements

• Code Completion in Text Field

• Options Indicator

• Deep Filtering

Breakpoints

Page 11: KKBOX WWDC17  Xcode debug - Oliver

Demo

Page 12: KKBOX WWDC17  Xcode debug - Oliver

Debug View Hierarchy Enhancements

• View Controller Debugging

• SpriteKit Debugging

• SceneKit Debugging

Page 13: KKBOX WWDC17  Xcode debug - Oliver

View Controller Debugging NEW

Page 14: KKBOX WWDC17  Xcode debug - Oliver

SpriteKit Debugging NEW

SpriteKit Debugging

Page 15: KKBOX WWDC17  Xcode debug - Oliver
Page 16: KKBOX WWDC17  Xcode debug - Oliver

SceneKit Debugging NEW

Page 17: KKBOX WWDC17  Xcode debug - Oliver
Page 18: KKBOX WWDC17  Xcode debug - Oliver

Finding Bugs Using Xcode Runtime ToolsImprovements in Runtime Checking

Page 19: KKBOX WWDC17  Xcode debug - Oliver

Improvements in Runtime Checking

Runtime Issues

Finding Bugs Using Xcode Runtime Tools

Page 20: KKBOX WWDC17  Xcode debug - Oliver

Improvements in Runtime Checking

• Main Thread Checker (New)

• Address Sanitizer

• Thread Sanitizer

• Undefined Behavior Sanitizer (New)

Page 21: KKBOX WWDC17  Xcode debug - Oliver

4

Main Thread Checker

Page 22: KKBOX WWDC17  Xcode debug - Oliver
Page 23: KKBOX WWDC17  Xcode debug - Oliver

Designing Asynchronous APIs

Let API user specify callback queue

DeepThought.asyncComputeAnswer(to: theQuestion) { reply in … }

Page 24: KKBOX WWDC17  Xcode debug - Oliver

Designing Asynchronous APIs

Let API user specify callback queue

DeepThought.asyncComputeAnswer(to: theQuestion, completionQueue: queue) { reply in … }

Page 25: KKBOX WWDC17  Xcode debug - Oliver

Address Sanitizer

• Detects use-after-scope

• Detects use-after-return (opt-in)

• Compatible with Malloc Scribble

Finding Memory Issues

Security critical bugs • Use-after-free and buffer overflows

Diagnoses hard-to-reproduce crashes

Advanced Debugging and the Address Sanitizer WWDC 2015

Page 26: KKBOX WWDC17  Xcode debug - Oliver

Use of out of scope stack memory

// Use of Stack Memory Out of Scope

int *integer_pointer = NULL; if (is_some_condition_true()) { int value = calculate_value(); integer_pointer = &value; } *integer_pointer = 42;

Page 27: KKBOX WWDC17  Xcode debug - Oliver

// Use of Stack Memory after Return

int *returns_address_of_stack() { int a = 42; return &a; }

int *integer_pointer = returns_address_of_stack(); *integer_pointer = 43;

Page 28: KKBOX WWDC17  Xcode debug - Oliver
Page 29: KKBOX WWDC17  Xcode debug - Oliver

Thread Sanitizer

• Race on collections

• Swift access races

What is Thread Sanitizer

Multithreading issues

Finds races even if they did not manifest

64-bit macOS, 64-bit simulators

Thread Sanitizer and Static Analysis WWDC 2016

Page 30: KKBOX WWDC17  Xcode debug - Oliver

// Thread 1 eventLog.log(source: networkingSubsystem, message: "Download finished")

// Thread 2 eventLog.log(source: databaseSubsystem, message: "Query complete")

Thread 2: Data race in EventLog.log(source:message:)

// Swift Data Race Example

class EventLog { private var lastEventSource: LogSource?

func log(source: LogSource, message: String) { print(message) lastEventSource = source } }

Page 31: KKBOX WWDC17  Xcode debug - Oliver

// Use DispatchQueue to Synchronize Access

class EventLog { private var lastEventSource: LogSource? private var queue = DispatchQueue(label: "com.example.EventLog.queue")

func log(source: LogSource, message: String) { queue.async { print(message) lastEventSource = source } } }

Page 32: KKBOX WWDC17  Xcode debug - Oliver

// Swift Access Race with Mutating Methods

struct BluePoliceBoxLocation { private var x, y, z: Int private var time: Int

}

mutating func teleport(toPlanet: String) { … } mutating func fly(toCity: String) { … } mutating func travelToEndOfTime() { … }

Thread 2: Swift access race

Thread 1: Previous access

// Thread 1 location.teleport(toPlanet: "Mars")

// Thread 2 location.travelToEndOfTime()

changes x, y, z

changes time

Page 33: KKBOX WWDC17  Xcode debug - Oliver

Undefined Behavior Sanitizer

Page 34: KKBOX WWDC17  Xcode debug - Oliver

Alignment Violation

Nonnull Return Value Violation

Integer Overflow

C++ Dynamic Type Violation Invalid Float Cast

Invalid Shift Exponent

Invalid Boolean Invalid EnumInvalid Variable-Length Array Integer Division by Zero

Invalid Shift BaseInvalid Integer Cast

Out-of-Bounds Array Access

Invalid Object SizeMissing Return Value

Reached Unreachable Code

Nonnull Parameter ViolationNonnull Assignment Violation

Null Dereference

Page 35: KKBOX WWDC17  Xcode debug - Oliver

“undefined behavior:behavior for which this International Standard imposes no requirements.”

•ISO C++14 Standard

Page 36: KKBOX WWDC17  Xcode debug - Oliver

Undefined Behavior Is About Tradeoffs

Performance over safety

Page 37: KKBOX WWDC17  Xcode debug - Oliver

(INT_MAX + 1) ≯ INT_MAX

Integer Overflow

Page 38: KKBOX WWDC17  Xcode debug - Oliver

Null pointer returned from function declared to never return null

// Nonnull Return Value Violation

@implementation SolarSystem + (nonnull NSDictionary *)planetMoons { return @{@"Earth": @[@"Moon"], @"Mars" : @[@"Phobos", @"Deimos"], // … }; } - (nonnull NSArray *)moonsOfPlanet:(nonnull NSString *)planet { return [[self class] planetMoons][planet]; } @end

// Find the biggest moon for each planet NSMutableArray *biggestMoons = [NSMutableArray new]; [biggestMoons addObject:[solarSystem moonsOfPlanet:@"Pluto"][0]];

Nonnull Return Value Violation

Page 39: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 1

Dead Code Elimination

Redundant Null Check Elimination

Redundant Null Check Elimination

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

*P = 4;

} Keep the brace in MM

if (P == NULL) return;

Dead Code Elimination

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

if (P == NULL)

return;

*P = 4;

} Keep the closing brace MM

Compiler Optimization

Page 40: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 1

Dead Code Elimination

Redundant Null Check Elimination

Redundant Null Check Elimination

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

*P = 4;

} Keep the brace in MM

Dead Code Elimination

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

if (P == NULL)

return;

*P = 4;

} Keep the closing brace MM

Compiler Optimization 1

Page 41: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 1

Dead Code Elimination

Redundant Null Check Elimination

Dead Code Elimination

int unused = *P;

void contains_null_check(int *P) {

…Hidden text for MM

*P = 4;

} Keep closing brace in MM

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

*P = 4;

} Keep the brace in MM

Compiler Optimization 1

Page 42: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 1

Dead Code Elimination

Redundant Null Check Elimination

Dead Code Elimination

void contains_null_check(int *P) {

…Hidden text for MM

*P = 4;

} Keep closing brace in MM

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

*P = 4;

} Keep the brace in MM

Compiler Optimization 1

Page 43: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 2

Redundant Null Check Elimination

Dead Code Elimination

Dead Code Elimination

void contains_null_check(int *P) { …Hidden text for MM if (P == NULL) return; *P = 4; } Please keep the brace MM

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

if (P == NULL)

return;

*P = 4;

} Keep brace during MM

int unused = *P;

Compiler Optimization 2

Page 44: KKBOX WWDC17  Xcode debug - Oliver

Compiler 2

Source code

.c, .m, .cpp, .mm

Object file

.o

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 2

Redundant Null Check Elimination

Dead Code Elimination

Dead Code Elimination

void contains_null_check(int *P) { …Hidden text for MM if (P == NULL) return; *P = 4; } Please keep the brace MM

void contains_null_check(int *P) {

int unused = *P; …Hidden text for MM

if (P == NULL)

return;

*P = 4;

} Keep brace during MM

Compiler Optimization 2

Page 45: KKBOX WWDC17  Xcode debug - Oliver

Source code

.c, .m, .cpp, .mm

Object file

.o Compiler 2

Let’s Experiment: A Very Simple Optimization Pipeline Compiler 2

Redundant Null Check Elimination

Dead Code Elimination

Redundant Null Check Elimination

void contains_null_check(int *P) {

…Hidden text for MM

if (P == NULL)

return;

*P = 4;

} Please keep me MM!

void contains_null_check(int *P) { …Hidden text for MM if (P == NULL) return; *P = 4; } Please keep the brace MM

Compiler Optimization 2

Page 46: KKBOX WWDC17  Xcode debug - Oliver

Let’s Experiment: A Very Simple Optimization Pipeline A surprising result

void contains_null_check(int *P) {

int unused = *P; …

if (P == NULL)

return;

*P = 4;

} Keep brace during MM

Compiler 1

void contains_null_check(int *P) {

*P = 4;

} Keep closing brace in MMvoid contains_null_check(int *P) {

if (P == NULL)

return;

*P = 4;

}

void contains_null_check(int *P) {

int unused = *P; …

if (P == NULL)

return;

*P = 4;

} Keep brace during MM

Compiler 2

Compiler Optimization

Page 47: KKBOX WWDC17  Xcode debug - Oliver

Using Runtime Tools Effectively

• Exercise more code

• Use the tools together

Page 48: KKBOX WWDC17  Xcode debug - Oliver

Runtime Tool Overhead

Execution overhead Memory overhead

Main Thread Checker 1.02x negligible

Undefined Behavior Sanitizer 1.2x negligible

Address Sanitizer 2–3x 2x

Thread Sanitizer 5–10x 4x

Page 49: KKBOX WWDC17  Xcode debug - Oliver

What's New in LLVM• API Availability Checking for Objective-C

• Static Analyzer Checks

• New Warnings

• C++ Refactoring & Features from C++17

• Link-Time Optimization (LTO)

• API Availability Checking for Objective-C

• Static Analyzer Checks

• New Warnings

• C++ Refactoring & Features from C++17

• Link-Time Optimization (LTO)

Page 50: KKBOX WWDC17  Xcode debug - Oliver

API Availability Checking for Objective-C

[UIView instancesRespondToSelector:@selector(addInteraction:)]

[UIDragInteraction class]

[NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]

&ARErrorDomain != NULL futimens != NULL

[UIView instancesRespondToSelector:@selector(addInteraction:)]

[UIDragInteraction class]

[NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]

&ARErrorDomain != NULL futimens != NULL

[UIView instancesRespondToSelector:@selector(addInteraction:)]

[UIDragInteraction class]

[NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]

&ARErrorDomain != NULL futimens != NULL

[UIView instancesRespondToSelector:@selector(addInteraction:)]

[UIDragInteraction class]

[NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]

&ARErrorDomain != NULL futimens != NULL

[UIView instancesRespondToSelector:@selector(addInteraction:)]

[UIDragInteraction class]

[NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]

&ARErrorDomain != NULL futimens != NULL

Page 51: KKBOX WWDC17  Xcode debug - Oliver

API Availability Checking in Objective-C

if (@available(iOS 11,x*)) { r = [VNDetectFaceRectanglesRequest new]; if ([handler performRequests:@[r] error:&error]) { // Draw rectangles } } else { // Fall back when API not available }

Compiler warns about unguarded uses of new API

Use @available to query API availability at run time

API Availability Checking for Objective-C

Page 52: KKBOX WWDC17  Xcode debug - Oliver

Factor out Code with API_AVAILABILITY()

Convenient to write entire methods with limited availability

@interface MyAlbumController : UIViewController

- (void)showFaces

@end

API_AVAILABILITY(ios(11.0));

Factor out Code with API_AVAILABILITY()

Convenient to write entire methods with limited availability

@interface MyAlbumController : UIViewController

- (void)showFaces

@end

API_AVAILABILITY(ios(11.0))

;

Can apply to entire classes

Factor out Code with API_AVAILABILITY()

Page 53: KKBOX WWDC17  Xcode debug - Oliver

API Availability Checking in C/C++

Use __builtin_available to check availability at runtime

if (__builtin_available(iOS 11, macOS 10.13, *)) { CFNewAPIOniOS11(); }

Page 54: KKBOX WWDC17  Xcode debug - Oliver

API Availability Checking in C/C++

Use __builtin_available to check availability at runtime

Include <os/availability.h> for the API_AVAILABILITY macro

#include <os/availability.h>

void myFunctionForiOS11OrNewer(int i) API_AVAILABILITY(ios(11.0), macos(10.13));

Page 55: KKBOX WWDC17  Xcode debug - Oliver

Do Not Compare Number Objects to Scalars

Comparing NSNumber pointer value to 0 checks for nil – not zero number

@property NSNumber *photoCount;

- (BOOL)hasPhotos {

} Comparing pointer value to a scalar integer valuereturn self.photoCount > 0;

Do Not Auto-Synthesize NSMutable copy Properties

Setter calls -copy, which yields an immutable copy

- (void)replaceWithStockPhoto:(NSImage *)stockPhoto { self.photos = [NSMutableArray<NSImage *> new]; [self.photos addObject:stockPhoto]; }

-[__NSArray0 addObject:]: unrecognized selector sent to instance

@property (copy) NSMutableArray<NSImage *> *photos;

Static Analyzer Checks

Run Analyzer on Your Code! Supports Objective-C, C, C++

Analyze during build

Page 56: KKBOX WWDC17  Xcode debug - Oliver

Q & A