Advanced+apple+debugging (4)

Source: Internet
Author: User
Tags ranges uikit

Whether you're using Swift, OBJECTIVE-C, C + +, C, or any other programming language, you need to learn how to create a breakpoint. In a GUI program such as Xcode, creating a breakpoint on the left side of the editing interface is very simple, But the LLDB console gives you more flexibility in controlling breakpoints.
In this chapter, you will learn all about breakpoints in Lldb.

Signals

In this chapter, you will use one of the projects I have provided; The project's name is signals, and you can find it in the Resources folder.

Page42image6392.png
Open the signals project with Xcode. Signals is an American football program themed app that shows some of the xxx styles called nerdily.
Inside the program, the project monitors several UNIX signals and displays the signals when the signals program receives them.

Unix signals is the basic form of communication between processes. For example, sigstop in signals can save the state of a process and halt the execution of the process. The corresponding is Sigcont, he told the program to continue execution. These two signals can be used by the debugger to pause or resume execution of the program.

This is an interesting program in the previous chapters because it is used not only to browse UNIX processing signal, but also to highlight what happens when a lldb-controlled thread handles the passed UNIX signals. By default, LLDB has custom actions when dealing with different signals. When LLDB is attached, some signals will not pass through the controlled thread.

To show signal, you can either add a signal to the application or send a signal in an external application, such as in terminal.

In addition, here is a uiswitch can switch processing signal code block, code block name called Sigprocmask to enable or disable the processing of signal.

Finally, the signal application also has a timeout button that adds sigstop to the application, essentially freezing the application. However, if LLDB is attached to the signals application (and is done by default, When you build and run signals through Xcode, calling Sigstop allows you to check the thread's state of this ng in Xcode with LLDB.

Make sure the iphone 7 Simulator is selected. Build and run the app. Once the project is up and running, locate and pause the debugger in the Xcode console.

Page43image20376.png

Continue to run Xcode and watch the simulator. When the debugger pauses and then resumes execution, a new row of data is added to the UITableView. This is a data added by the signals monitor to the Sigstop event of the UNIX signal. When the thread is stopped, Any new signals will not be processed immediately, as it can be assumed that the program has been stopped.
Xcode Breakpoint

Before you finish your study, the breakpoint on the LLDB console will be a bright spot, and it is well worth replacing the breakpoints you learned Xode.
Symbolic breakpoints is a very good debugging feature in Xcode. It allows you to set breakpoints at certain symbol points in your application. A very simple example is-[nsobject init], with the NSObject instance Init method.
The symbolic breakpoint can be used flexibly in Xcode, and once you create a breakpoint, you do not have to re-enter it the next time you start the application.
Now you will use the symbolic breakpoint to display all instances of the nsobject that were created.
If the app is running then kill the app's process. Then switch to the breakpoint navigation bar. In the lower left corner, click the + button and select the Symbolic breakpoint option.

Page44image11344.png

A pop-up window appears. In the symbol section of the pop-up window, enter:-[nsobject init]. Under Action, select the Add action and select Debugger Command in the drop-down option, and then enter the PO [$arg 1 class] in the input box. .
Finally, select automatically continue after evaluating actions. Your pop-up window should look like this:
Page44image11776.png

Build and run the app. When the signals program runs, Xcode will initialize all the class names in the console output, and you'll see a lot more.
Here you set a-[nsobject init] breakpoint that fires every time a call is made. When a breakpoint is triggered, LLDB runs an instruction and automatically lets the application continue execution.
Note: In the tenth chapter "Assembly, registers and calling convention" you will learn that if you use and manipulate registers properly, but now simply know the $arg1 synonyms in the register, you $rdi can simply think of it as a call initan instance of the class of the method.
If you complete the extract operation to see all the class names, then delete the breakpoint using the right-click option in the breakpoint navigation bar and select Delete Breakpoint.
In addition to symbolic breakpoints, Xcode supports several other types of error breakpoints. One of them is called exception breakpoint. Sometimes your program throws some errors that can cause crashes. Your first reaction should be to enable the exception Breakpoint. Xcode will automatically navigate to the offending line of code, which can be a great help in capturing crashes.
Finally, there is a breakpoint type that is Swift Error breakpoint. This type of breakpoint is essentially in the Swift_ A breakpoint is created in the Willthrow method and triggered when Swift throws an exception. This is a very good option that we can use when we are using APIs that are error-prone. It allows you to quickly diagnose problems without making judgments about the right and wrong of the code.

LLDB Breakpoint Syntax

Now that you have mastered the course of debugging crash features in Xcode, it's time to learn how to create breakpoints through the LLDB console. In order to create useful breakpoints, you need to learn how to query what you are looking for.
The image command is an extremely useful tool for viewing internal details and is critical for setting breakpoints.
There are two key configurations in this book when searching for code. The first one is:

(lldb) Image Lookup-n "-[uiviewcontroller viewdidload]"
This command extracts the load address of the-[uiviewcontroller viewdidload] function. The-n parameter tells Lldb to find the symbol or function name. The output might look like this:

1 match found in/applications/xcode.app/contents/developer/platforms/
iphonesimulator.platform/developer/sdks/iphonesimulator.sdk//system/
Library/frameworks/uikit.framework/uikit:
ADDRESS:UIKIT[0X00000000001C67C8] (UIKit. TEXT. Text +
1854120)
Summary:uikit '-[uiviewcontroller Viewdidload]
Another command that is similar and very useful is:

(lldb) Image Lookup-rn test
This life is used to find the word test and is case-sensitive. If the lowercase word test is found in any function in any module that is loaded in the current executable (for example: UIKit, Foundation, Core Data, and so on), the command is output.

Note: Use the option when you want to extract the parameters of the match to the content -n (if your query contains spaces, you need to enclose them in quotation marks). -n Can only help you to extract the exact parameters of the breakpoint to be matched, especially when dealing with swift, and the -rn options are often used in this book, because you will soon find a nice regular expression that can reduce a lot of input.

Properties of the Objective-c

Learning how to query the loaded code in code is the ultimate goal of learning how to create breakpoints.
Whether the objective-c or swift code has a specified property signature when it is created by the compiler, we need to use a different breakpoint policy.
For example, in the signals project, the following Objective-c class declares a property:

@interface Testclass:nsobject
@property (nonatomic, strong) NSString *name;br/> @end

The getter looks like this:

-[testclass Name]
The setter method looks like this:

-[testclass SetName:]
Build and run the app, and then pause the debugger. Next, type the following command in LLDB to verify that these methods are present:

(lldb) Image Lookup-n "-[testclass name]"
In the console you will see the following output:

1 match found in/users/derekselander/library/developer/xcode/
deriveddata/signals-bqrjxlceauwfuihjesxmgfodimef/build/products/debug-
Iphonesimulator/signals.app/signals:
ADDRESS:SIGNALS[0X0000000100001470] (signals. TEXT. Text + 0)
Summary:signals '-[testclass name] at testclass.h:28
LLDB will extract information about the functions contained in the executable file. The code looks a little scary, but there's some useful information inside.
These outputs tell you that LLDB can find implementations of these functions in the signals executable. and the exact offset in the __text segment is 0X0000000100001470.LLDB also tells us this method lives in the 28th line of the TestClass.h file .
You can also view setter methods in the following ways:

(lldb) Image Lookup-n "-[testclass SetName:]"
You should get the same output as before, this time showing the name of the property setter method implementation and implementation of the address.

Swift Properties

The syntax for declaring attributes in Swift is somewhat different. Take a look at the Swifttestclass.swift file and you'll find the following code:

Class Swifttestclass:nsobject {
var name:string!
}
Make sure the signals project is running and paused in LLDB. You can press COMMAND + K to quickly empty the LLDB console.
Enter the following command in the LLDB console:

(lldb) Image Lookup-rn Signals.SwiftTestClass.name.setter
You will get some output similar to the following:

2 matches found in/users/derekselander/library/developer/xcode/
deriveddata/signals-bqrjxlceauwfuihjesxmgfodimef/build/products/debug-
Iphonesimulator/signals.app/signals:
ADDRESS:SIGNALS[0X000000010000ABA0] (signals. TEXT. Text +
38704)
Summary:signals @objc Signals.SwiftTestClass.name.setter :<br/>Swift.ImplicitlyUnwrappedOptional&lt;Swift.String&gt; at SwiftTestClass.swift<br/>Address: Signals[0x000000010000ac60] (Signals.__TEXT.__text + 38896)<br/>Summary: Signals Signals.SwiftTestClass.name.setter:
Swift.implicitlyunwrappedoptional<swift.string> at Swifttestclass.swift
Find the word summary in the output. Here are two interesting things to watch out for.
First, two symbols were found. The first and second have the same name; however, the first one has a @objc prefix. This is the compiler plus the specific function to be used as a bridging function. This helps in the mixing of swift and objective-c.
Second, do you see how long the function name is? To create a valid Swift breakpoint, you need a full name.

If you want to set a breakpoint in this setter method, you need to do this in the following way:

(LLDB) b Signals.SwiftTestClass.name.setter:
Swift.implicitlyunwrappedoptional<swift.string>
Using regular expressions can reduce the number of inputs.
Regardless of the length of the SWIFT function name you generate, note the form of Swift's properties. In the signature of the property name function, the word setter immediately follows the property. Maybe the Getter method also has the same format?
Try to capture the getter and setter methods of the Name property of the Swifttestclass class, and at the same time use the following regular expression to query:

(lldb) Image Lookup-rn Signals.SwiftTestClass.name
This command uses regular expressions to query and extract everything in Signals.SwiftTestClass.name.
Since this is a regular expression, it is a wildcard character and is used to match the point syntax in the function signature order.
You'll get some reasonable output, but every time you see summary in the output of the console. You'll find that the output matches the getter, (Signals.SwiftTestClass.name.getter), Setter, ( Signals.SwiftTestClass.name.setter), @objc the corresponding bridge, and a method that contains Materializeforset, which you will learn later.
Here is a sample of the Swift attribute function name:

ModuleName.Classname.PropertyName. (Getter|setter)
The ability to extract methods, find samples, and narrow your search is a great way to create smart breakpoints in your code to unlock swift/objective-c language mysteries.

At last... Creating breakpoints

Now that you know how to query the existing functions and methods in your code, it's time to create breakpoints on those methods.
If your signals project is running, stop and restart the program, then click the Pause button to stop the application and go to the LLDB console.
There are several different ways to create breakpoints. The simplest way is to enter the lowercase letter B followed by the function name. This is very simple in objective-c and C, because its name is very short and easy to enter (for example,-[nsobject init]). and in C + + and swift It's very complicated, because the compiler returns you a fairly long name for the function.
Since Uikit is mostly done with objective-c (at least when writing this book), try creating a breakpoint with the B parameter, like this:

(LLDB) b-[uiviewcontroller Viewdidload]
You will see the following output:

Breakpoint 1:where = UIKit '-[uiviewcontroller viewdidload], address =
0x0000000102bbd788
Whenever you create a valid breakpoint, the console will output some information about the breakpoint.
In this particular case, this breakpoint is created as Breakpoint 1, because this is the first breakpoint created in this particular debugging session. When you create more breakpoints, the breakpoint ID will continue to grow.
Continue running the debugger once you continue to execute a new sigstop will be displayed. Click on the cell to enter the details Uiviewcontroller. The program should pause when the detail view controller calls Viewdidload.

Note: Like many shortcut commands, it b is an abbreviation for a long word in the LLDB command. You can run the Help B command yourself to see how it helps and learn its cool tricks.
In addition to the B command, there is a long breakpoint set command, which has many options available. You'll use it in a few chapters later. Many commands are branches of the breakpoint set command.

Regular breakpoints and ranges

Another extremely useful command is the regular expression breakpoint Rbreak is breakpoint set-r%1. You can use smart regular expression breakpoints to quickly create breakpoints in many places where you want to stop.
Let's look back at the very long previous example of the Swift property name function, unlike the following input:

(LLDB) b Breakpoints.SwiftTestClass.name.setter:
Swift.implicitlyunwrappedoptional<swift.string>
You can enter:

(LLDB) RB SwiftTestClass.name.setter
Although the above command is shorter, there is also a annoying place. This breakpoint also captures the setter method of the Name property of the Objective-c Bridge, which is forced to stop two times when this method is called.
You can add a parameter ^ (@) to this breakpoint. *, the essence of this parameter is to say "filter out functions starting with @xxx". In the next few chapters, you will build a command that performs regular searches to automatically filter out these bridging functions.
From now on you only have to deal with two breakpoints. Another more concise way to do this is the following:

(LLDB) RB Name.setter
This creates a breakpoint in any place that contains name.setter. This is where you know there's no other place in the project. The Swift property is known as the name of the line. Otherwise, you will create a breakpoint at each location.
Now try to create a breakpoint in each of the Objective-c instance methods in Uiviewcontroller. We can enter the following command in the LLDB:

(LLDB) RB '-[uiviewcontroller\ '
A backslash is an escape character used to indicate the original character that you want to search for in the regular expression. So the result is that this instruction will stop at the place where each string contains a-[uiviewcontroller followed by a space.
Wait a minute... What is it like in the categories of objective-c? They provide a form of (-|+) [ClassName (CategoryName) method]. You can rewrite the regular expression in the form of a containing categories.
Enter the following command in the LLDB session and confirm with input y in the prompt:

(lldb) Breakpoint Delete
This command removes all breakpoints that you have set.
Then enter the following:

(LLDB) RB '-[uiviewcontroller ((\w+))? \ '
This command provides a parenthesis option that contains one or more characters before the Uiviewcontroller of the breakpoint, preceded by a space.
A regular expression breakpoint lets you capture a wide breakpoint with an expression.
You can use the-F option to specify a breakpoint in a specific file.

(LLDB) RB. -F Detailviewcontroller.swift
This is useful when you are debugging detailviewcontroller.swift. It will be in this file all properties of Getters/setters, Blocks/closures, Extensions/categories, and Functions/methods out to lay a breakpoint. The-f option is used to limit the range.
If you are completely insane or want to torture yourself, you can specify a range as simple as the following:

(LLDB) RB.
This creates a breakpoint in all places ... Yes, it's everywhere! This creates breakpoints in all the code for the Signals project, all Uikit code and all the foundation code, all the code that runs the loop. As a result, you need to enter continue in the debugger to continue execution.
There is another way to specify the scope of the search. You can limit the scope to a single library with the-s option:

(LLDB) RB. -S Commons
This sets a breakpoint in every place in the Commons Library, and Commons is a dynamic library included in the Signals project.
You can also create breakpoints in each of the Uikit functions in the same way:

(LLDB) RB. -S UIKit
This is obviously crazy. There are about 66,189 Uikit in the iOS10.0 system. How do you stop at Uikit only when you trigger the breakpoint for the first time? The-o option provides a solution. It creates a breakpoint of type one-shot. This breakpoint is automatically deleted once it is triggered. Therefore only one time is triggered.
To see the effect of this method, you can enter the following command in the LLDB session:

(lldb) Breakpoint Delete
(LLDB) RB. -S Uikit-o
Note: Be patient when LLDB executes these commands, because LLDB creates a large number of breakpoints. And make sure you're using an emulator, otherwise you'll be waiting for a very long time.
Next, let the debugger continue and click on a cell in TableView. The debugger stops at the first call of the Uikit method. Finally, continue to run the debugger, and this breakpoint will not be triggered again.

modifying and deleting breakpoints

Now that you have a basic understanding of how to create breakpoints, you may also want to know how you can change them. What do you do when you want to modify, delete, or temporarily deactivate a breakpoint? What do you do when you want a breakpoint to execute a specific command the next time it is triggered?
First, you need to know how to tag one or a set of breakpoints. You can also use the-n option to name a breakpoint when you create a breakpoint ... Tagging with numbers may not really work for you.
Build and run the app to empty the Lldb session. Next, pause the debugger and enter a command in the LLDB session:

(LLDB) B main
You may see the following output:

Breakpoint 1:20 locations.
It means that you create breakpoints in 20 different parts of the module that match the main one.
In this case, the ID of this breakpoint is 1 because it is the first breakpoint that you created. To see the details of this breakpoint, you can use the breakpoint List command. Enter the following:

(LLDB) Breakpoint List 1
It should output something like the following:

1:name = ' main ', locations = 0, resolved =.
1.1:where = Breakpointsmain + 22 at AppDelegate.swift:12, address =<br/>0x00000001057676e6, resolved, hit count = 0<br/>1.2: where = Foundation-[nsthread main], address = 0x000000010584d182,
Resolved, Hit count = 0
1.3:where = Foundation-[NSBlockOperation main], address =<br/>0x000000010585df4a, resolved, hit count = 0<br/>1.4: where = Foundation-[nsfilesystemitemremoveoperation main],
Address = 0X00000001058990FF, resolved, Hit count = 0
1.5:where = Foundation-[NSFilesystemItemMoveOperation main], address<br/>= 0x0000000105899c23, resolved, hit count = 0<br/>1.6: where = Foundation-[nsinvocationoperation main], address =
0X00000001058C4FB9, Resolved, Hit count = 0
1.7:where = Foundation-[NSDirectoryTraversalOperation main], address<br/>= 0x000000010590a87f, resolved, hit count = 0<br/>1.8: where = Foundation-[nsoperation main], address =
0X000000010595209C, Resolved, Hit count = 0
1.9:where = UIKit-[UIStatusBarServerThread main], address =<br/>0x00000001068b84f0, resolved, hit count = 0<br/>1.10: where = UIKit-[_uidocumentactivityitemprovider main], address =
0X000000010691898C, Resolved, Hit count = 0
1.11:where = UIKit-[_UIDocumentActivityDownloadOperation main],<br/>address = 0x0000000106975d51, resolved, hit count = 0<br/>1.12: where = UIKit-[_uigetassetthread main], address =
0X000000010698EF4D, Resolved, Hit count = 0
1.13:where = UIKit-[UIWebPDFSearchOperation main], address =<br/>0x0000000106ae7c99, resolved, hit count = 0<br/>1.14: where = UIKit-[uiactivityitemprovider main], address =
0x0000000106c4e525, Resolved, Hit count = 0
1.15:where = mobilecoreservices-[LSOpenOperation main], address =<br/>0x000000010879703c, resolved, hit count = 0<br/>1.16: where = ImageIOMain, address = 0x000000010c87535d, Resolved, hit
Count = 0
1.17:where = Appsupport-[_CPPowerAssertionThread main], address =<br/>0x000000010ed95f03, resolved, hit count = 0<br/>1.18: where = AppSupport-[cpdistributedmessagingasyncoperation main],
Address = 0x000000010ed9ba53, resolved, Hit count = 0
1.19:where = JavaScriptCoreWTF::RunLoop::main(), address =<br/>0x0000000111c68af0, resolved, hit count = 0<br/>1.20: where = ConstantClassesMain, address = 0X0000000114329CD2,
Resolved, Hit count = 0
This shows the details of the breakpoint, including all the locations that contain the word main.
An introduction to this information is shown by entering the following:

(lldb) Breakpoint list 1-b
This will output some concise and more visual information. If you have an ID for a breakpoint, and this ID contains multiple breakpoints, this concise sign is a good solution.
If you want to see all the breakpoints in Lldb, simply enter the following:

(LLDB) Breakpoint list
You can also nominate multiple breakpoint IDs and ranges:

(LLDB) Breakpoint List 1 3
(lldb) Breakpoint list 1-3
Deleting all breakpoints with the breakpoint Delete command is a heavyweight operation. You can simply use the ID of the breakpoint to delete a breakpoint or a collection of breakpoints:
You can delete a breakpoint by specifying the breakpoint ID:

(lldb) Breakpoint Delete 1
However, the "main" breakpoint contains 20 breakpoints. You can also delete a breakpoint by following this general method:

(lldb) Breakpoint Delete 1.1
This removes the first self-breakpoint from a 1 breakpoint.

Why are we learning this?

You've learned a lot in this section. Breakpoints are a big topic and are a major art for debugging experts to quickly discover and find physical nature. You've also learned how to use regular expressions to search for code. Now it's time to comb through the syntax of regular expressions, and you'll use a lot of regular expressions later in the book.
Explore https://docs.python.org/2/library/re.html to learn regular expressions. And try to find out how to create a case-insensitive regular expression.
Now you're just out of your mind about how the compiler generated objective-c and Swift's functions. Try to figure out how to create a breakpoint in Objective-c's blocks or Swift's closures. If you do, Try to design a breakpoint that stops only in the Commonsframework objective-c blocks of the signals project. These are the skills you need to create more complex breakpoints in the future.

Advanced+apple+debugging (4)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.