Advanced+apple+debugging (15)

Source: Internet
Author: User
Tags uicontrol

You never heard of dtrace?!. This is horrible! DTrace is a tool that lets you view your code in a dynamic or static way.
Http://dtrace.org/guide/preface.html
You can create a dtrace probes to compile into your code (in a static way), or you can check the code that has been compiled and run (in a dynamic way). DTrace is a multipurpose tool that has several functions: it can be a profiler, a parser, a debugger, or anything you want. When I had no clue where to start, I often used dtrace to specify a broad search network in the code I wanted to explore.

Oh, my God! It's time to learn DTrace! DTrace (probably) is the coolest tool you've ever heard of. With DTrace, you can use a thing called probe to intercept a function or a set of functions. From here, you can perform a custom action to query the information for the specified process, or the system-level information on your computer (and detect multiple users)!
If you've ever used a instruments application, it's a powerful, low-level feature that surprises you with the powerful DTrace implementation.
In this chapter, you'll see a very small section describing how powerful DTrace is in tracking objective-c code in already compiled applications. Use DTrace to observe the iOS framework (such as Uikit) It gives you incredible insight into how authors design their code within the framework.

Bad news

Let's start with the bad news, because from now on there are exciting and cool features behind us. Here are a few things to keep in mind about DTrace:
? In order to use dtrace normally you need to disable rootless mode. Do you remember a long time ago in the first chapter I reminded you to disable rootless in order to implement certain features? In order for Lldb to be attached to any process on your MacOS pc, if system Integrity Protection is enabled, DTrace will not work properly. If you skipped chapter one, now go back to disabling rootless.
? DTrace is not made for iOS devices. Although the instruments application is implemented with DTrace, there are many features. However, it is not possible to run custom scripts on your iOS device provider. This means that you can only run preset limited features on your iOS device vendor. You can still run the scripts you want to run on the iOS emulator (or other apps on your MacOS pc), whether you're the code that owns the programs or not.
? DTrace has a steep learning curve. DTrace needs you to know what you're doing and what you're looking for. Its documentation assumes that you already know the most basic terminology of the DTrace component. In this chapter you will learn the most basic concepts, and if you want to introduce all aspects of DTrace, you can write a separate book, which is beyond the scope of what I'm trying to teach you.
In fact, these need to be known in advance, if you are interested in DTrace, then you can look at this book http://www.brendangregg.com/dtracebook/index.html. It focuses on a broad topic but may not be suitable for Apple's debug/reverse engineering strategy, but it teaches you how to use DTrace.
Now that I've told you the bad news, it's time to talk about some happy topics.

The right jump

I'm not going to chase you away in nasty jargon. No one will spend time on that. Instead, you'll get your hands dirty first and then figure out what you'll do later.
Launch the iOS 7 Plus simulator. After the emulator is started, create a new terminal window. Enter the following in the terminal:

sudo dtrace-n ' objc$target:*viewcontroller::entry '-P pgrep Springboard
No, this will not secretly destroy your computer, Here you need to use sudo because DTrace is extremely powerful and can query other users ' information on your computer. This means that you need root privileges to use it. The
This dtrace command has two options, the name option (-N) and the PID option (-P), which we'll discuss later. Make sure that you quote the query statement in single quotation marks is not working. Note that the Pgrep springboard is preceded by a grave accent instead of a single quotation mark. br> If your input is correct, in the terminal you will see output similar to the following:

Dtrace:description ' objc$target: viewcontroller::entry ' matched 28076
Probes
Navigate the emulator while watching the terminal window.
This prints out each OBJECTIVE-C class name that ends with "Viewcontroller". Because we leave the function options blank (don't worry-we'll discuss the term in the next section), which will match each of the objective-c methods in the Objective-c class ending with Viewcontroller.
If you're tired of looking at what's popping up, press CTRL + C to kill the terminal window that is running the DTrace script.
go back to your terminal and enter the following:
This time there are some minor changes:
? query
Viewcontroller has been changed to Uiviewcontroller.
? What about the-viewwillappear in the query statement? has been added to the location of the function. Again, we'll discuss the terminology later. But now all you need to know is to replace every method that matches any class that contains the "Viewcontroller" string, and the new DTrace script will only match-[uiviewcontroller Viewwillappear:]. ? In DTrace identifies a wildcard, which is used to split viewwillappear:.
? Finally, you add a bunch of curly braces to a function called Ustack ().-[uiviewcontroller Viewwillappear:] This logic is called every time the trigger is triggered. Ustack () is a function within DTrace that extracts the user's stack record when a function is triggered (in this case, springboard).
? Notice that you move from the end of entry to the single quotation mark that moves to the end of the curly brace
If you typed it correctly, you will get the following output:

Dtrace:description ' objc$target:uiviewcontroller:-viewwillappear?:entry ' matched 1 probe
Browse Springboard. Swipe up, swipe down, scroll to the left to click the Edit button as you need to trigger the Uiviewcontroller viewwillappear:.
When the Uiviewcontroller viewwillappear: Trigger, the stack record will be printed in the terminal.
Note the stack records that have no actual function names but only modules and addresses.

Picture. png
This is the symbol table that tells us that there is no debug information or that does not directly refer to these function names.
If you're tired of browsing through all the Viewwillappear: Stack records in the springboard process, kill the DTrace script again.
Right now... Do you remember the complete theory of objc_msgsend using registers and the first parameter would be an instance (or a class) of a class objective-c?
For example, when Objc_msgsend executes, the declaration of the function will look like this:

Objc_msgsend (Self_or_class, SEL, ...);
You can grab the first parameter of the ARG0 parameter (that is, an instance of Uiviewcontroller) in DTrace. Unfortunately, you can only get references to pointers-you can't run any objective-c code, such as [arg0 title].
Add the following line of code to the front of the Ustack () function in your dtrace script:

printf ("\nuiviewcontroller is:0x%p\n", arg0);
Your DTrace one-line instruction will look like this:

sudo dtrace-n ' objc$target:uiviewcontroller:-viewwillappear?:entry
{printf ("\nuiviewcontroller is:0x%p\n", arg0); Ustack ();} ' -Ppgrep SpringBoard
Before you print out the stack record correctly, you have printed a reference in addition to calling Viewwillappear: Uiviewcontroller.
If you copy the address of a pointer to the DTrace output and attach the Lldb to the springboard, you will find that it aspires to a valid Uiviewcontroller (if it has not been destroyed).

Note: It is easy to get pointers from arg0, but getting other information (such as the class name) is a tricky process. You can no longer execute any objective-c/Swift code in a DTrace script that belongs to a user process (such as springboard). All you can do is move forward in memory with the reference you already have. In the final chapter, you will be able to get the class name from the arg0 parameter of the call that actually gets objective-c in the streamlined binary, with no debug information at all!
Let's take another example of DTrace.
Kill all DTrace scripts and create a script that aggregates all the unique classes that you can execute when you browse Springboard:

sudo dtrace-n ' objc$target:::entry {@[probemod] = count ()} '-PpgrepSpringBoard
Browse springboard again. You don't get any output, but when you use the CTRL + C terminal script, you get a list of classes that execute a method at that time. This is called aggregations is what you will learn later.

Picture. png
As you can see in my output, springboard calls 187,075 NSObject implementations during the DTrace single-line command.
It is important to differentiate between the fact that they are very similar to an instance of a subclass of NSObject calling the NSObject implementation method (for example, the subclass of this nsobject does not override any of these methods). For example, call-[uiviewcontroller class] will be counted as nsobject by forward invocation to the total number of executed methods because Uiviewcontroller does not override Objective-c method, class, or Uiviewcontroller parent class, Uiresponder.

DTrace Professional Terminology

Now that you've got some dtrace single-line commands dirty, it's time to learn the jargon so you can really figure out what these scripts are doing.
Let's look at one more DTrace probe. You can put a probe. These is considered a query. Probe can be an event for a particular process that DTrace detects or a global process for your computer.
Consider the following line of DTrace single-line commands:

Dtrace-n ' objc$target:nsobject:-description:entry/arg0 = 0/
{@[probemod] = count ():} '-P pgrep Springboa Rd
I'm going to ask a useful question in this script that will detect the description method NSObject implemented in the process named Springboard. Besides, this is to say that at the beginning of the description, The logic that executes the number of calls to this method.
This dtrace single-line command can be further disassembled as the following term:
? Probe Description: A group of items wrapped around 0 or more probes. This consists of each colon separated by a provider, module, function, and name. Optimizing the item between any colons will cause the probe description to contain all the matches. You can use the or? operator for these matches. The wildcard character that will be used as a single characters will match anything.
? Provider: Think of Provider as a set of code or normal functionality. In this chapter, you will primarily use OBJC Provider to track calls to Objective-c methods. OBJC provider to group all OBJECTIVE-C codes. You'll be browsing these providers later.

Note: Keywords $target is a special keyword that matches the PID provided to DTrace. Some providers (such as OBJC) expect you to provide this content. Will $ Target imagines a placeholder for the actual PID of the objective-c in a particular process. If you refer to the $target placeholder, you must indicate the PID of the target process with the-p or-c option in your DTrace command. Typically this can be done with a -p PID When you know the specific PID, or by using the -P ' pgrep nameofprocess ' . The terminal command pgrep will look at the PID of the process named nameofprocess and then return to the PID and apply it to the $target variable.
? Module: In OBJC Provider, the module section is where you specify the name of the class you want to observe. Using the OBJC provider is a bit unique in this scenario because normally the module references a code base. In fact, in some providers, there is not a bit of module content! However, the author of OBJC provider chooses to use the module to refer to the Objective-c class name. In this example, the module is nsobject.
? Function: is a probe description section that can indicate the name of the functions you wish to observe. In this example, the function is-description. The author of OBJC provider uses + or-to determine whether the OBJECTIVE-C function is a class method or an instance method (as you would expect!). If you change the function to +description, it will query for any probes substitution using + [nsobject description].

? Name: This usually indicates the position of the probe for a function. Typically, there is the entry name and the name of the return point for the function entry and exit. In addition, inside OBJC provider, you can also specify any assembly instruction offset to create the probe! In this example, the name is the function entry, or the starting position of the function.
? Predicate: Executes a conditional expression if the action to be performed is optional. Imagine predicate as a condition in an if statement. The operation will only be executed if predicate is true. If you omit the conditional sentence, the operation will be performed on the probe every time. In this example, the conditional sentence is/arg0! = 0/, which means that the content behind the conditional sentence will only be executed if the arg0 is not nil.
? Action: If the probe matches the description of the probe and the conditional sentence is true, the operation is executed. Actions can be as simple as printing something, or perform more advanced functions. In this example, the operation is @[probemod] = count (); The code.
When all these parts are combined, DTrace is the form of dtraceclause. These optional conditional clauses and the optional DONG constitute the probe description.
Simply put, a dtrace clause should look like this:

Provider:module:function:name/predicate/{Action}
DTrace "one-liners" can consist of a number of subordinate clauses that can detect different items, judge different conditions in a conditional sentence, and perform different logical operations.
Here is an example:

Dtrace-n ' objc$target:nsview:-init: Entry '-Ppgrep -x Xcode
We have a probe description that contains the NSView module Objc$target:nsview:-init
: Entry,-init*a is the function part and entry is the name with no conditional and optional action. DTrace produces the default output for tracked information (that is, the-Q option that you might ignore). The default output shows only the function and name. For example, if you are tracking-[nsobject init] without ignoring the default DTrace operation, the content of your dtrace output should look like this:

Dtrace:description ' objc$target:nsobject:-init:entry ' matched 1 probe
CPU ID Function:name
2 512130-init:entry
2 512130-init:entry
2 512130-init:entry
2 512130-init:entry
As can be seen from the output,-[nsobject Init] was called four times during the process being traced. You can tell DTrace that the print function outputs a different format by using the-Q option.
What does the-n parameter mean? The-n parameter indicates the DTrace name in the form Provider:module:function:name, Module:function:name, or Function:name. In addition, the name option can take an optional probe clause, W but enclose the single-line command script with the-n parameter.
Do you understand? No? We will use a useful dtrace option to solidify the knowledge and terminology you have just learned.

Learning the monitor probe

There is a very good option in DTrace-L, the-L can list all the probes that probe description matches. When you use the-l option, DTrace will simply list the probe without performing any action, and DTrace will not execute whether or not you use the operation.
This makes the-l a good tool to learn what is feasible and what is not.
Let's take a look at the probe description when compiling the DTrace script and specify its scope. Consider the following instruction, but do not perform:

sudo dtrace-ln ' objc$target::: '-Ppgrep -x Finder
This creates a probe description in each method of each Objective-c class in the Finder and at each assembly instruction. This is a very bad note for DTrace scripts and may not work on your computer because the number of triggers is too many.

Note: I have already -x applied the option to the pgrep pgrep $target parameter because I might get multiple when using the query PIDs . The option means that it -x only Finder matches me exactly with the name. If there are multiple instances of a process. You can use the Pgrep or the option to get to the -o -n beginning of the process or the final process. If that sounds confusing to you, practice using pgrep commands to understand how it works without DTrace in the terminal.
Do not execute the above script because it will take a long time. However, execute the script below so you can understand what's going on.
Let's make this command a little bit leaner. In the terminal, enter the following command:

sudo dtrace-ln ' Objc$target:nsview:: '-Ppgrep -x Finder
Press ENTER, then enter your password.
This will list the probe of each individual method in all methods implemented by NSView and the assembly instructions for each method. Is still a scary way, at least this time after a few seconds will really print out the content.
How many probes are there? You can get the answer by grafting the output to the WC command:

sudo dtrace-ln ' Objc$target:nsview:: '-P pgrep -x Finder | grep wc-l
On my MacOS machine is the 10.12.4 system (when I was writing this book), and in the Finder process I got 46k NSView-related objective-c DTrace probes. Wow.
Further filtering these probe description:

sudo dtrace-ln ' objc$target:nsview:-initwithframe?: '-Ppgrep -xFinder
This filters out the probe description of each assembly instruction that executes-[nsview initWithFrame:] method, except for the entry and return points.
Notice how I use the? Instead of a colon to indicate objective-c selector (with parameters)?. This is because if I use a colon, dtrace will mistakenly assume that I have completed the function section and have started to indicate DTrace probe name. The function description begins with-Indicates that this is an instance method.
There is already too much output, I just want to set a probe that detects the starting position of the-[nsview initWithFrame:] Method without needing another probe.

sudo dtrace-ln ' objc$target:nsview:-initwithframe?:entry '-ppgrep -xFinder
This instruction means that only a probe is set at the starting position of the-[nsview initWithFrame:] And no probe is set elsewhere in the method.
Using the-l option is a good way to learn to specify the probe range in your dtrace operation. I recommend that you use the (reuse)-l option when learning dtrace.

A script to create a dtrace script

When using DTrace, you not only have to deal with steep learning curves, you also have to deal with some implicit errors that occur at build time or at run time (yes, they are at the same level of secrecy as those swfit compiler Errors).
In order to alleviate those build problems while learning DTrace, I created a tobjectivec.py (trace objective-c), a lldb Python script that can generate custom DTrace scripts for you.

Note: Oh yes, now is a good time to remind you to create DTrace scripts and DTrace single-line commands. With the increased complexity of logic in your DTrace scripts, using scripting becomes a better choice. Simple DTrace query, you can use a single-line command.
You can find the tobjectivec.py script in the starter directory of this chapter. I assume you've read the 22nd chapter, "SB Examples, improved Lookup" and already installed the lldbinit.py script and already put it in ~/ The Lldb folder. Assuming you've done that, all you have to do is copy/paste the tobjectivec.py script into your ~/lldb directory and it will start the next time the LLDB runs.
If you have not done so, go back to chapter 22nd and follow the instructions to install the lldbinit.py file. Tip, if you're very stubborn, I guess you can manually install ' tobjectivec.py by expanding the ~/.lldbinit file.

Browse DTrace through tobjectivec.py

It's time to start the whirlwind tour of DTrace in the Objective-c code.
There are allocator items that can be recycled in the Starter folder. Open the project, build, run, and pause the debugger.
After you pause the allocator project in the debugger, go to the LLDB console and enter the following:

(LLDB) Tobjectivec-g
Typically, the Tobjectivec script generates a script in your computer's/tmp/directory. However, the-G option means that you are debugging your script by displaying the output to lldb instead of generating a script in the/tmp/displays the output directory. With the-g (or--debug) option, your current script is displayed in the console.
This simply runs the tobjectivec.py script without any parameters, which results in a bit of output:

#!/usr/sbin/dtrace-s/ 1 /
#pragma D option quiet/ 2 /
Dtrace:::begin {printf ("Starting ... use Ctrl + C to stop\n");}/ 3 /
dtrace:::end {printf ("ending...\n");}
/ Script content below /
Objc$target:::entry/ 5 /
{
printf ("0x%016p%c[%s%s]\n", arg0, Probefunc[0], Probemod,
(string) &probefunc[1]); / 6 /
}
Let's break it down:

When executing a dtrace script, the first line needs to be that the #!/usr/sbin/dtrace-s script may not run correctly.
This line of code means that when a probe is triggered, neither the number of probes nor the default DTrace operation is performed. Instead, perform the operation that you assigned to DTrace.
This hi is One-third of the DTrace statement in this script. This is an actual probe in DTrace that detects an event ... For example, when a DTrace script starts. This means that when DTrace starts, it prints out a "starting ... use Ctrl + C to stop" string.
Here's another one. When the DTrace script finishes, it prints the dtrace statement "ending ...".
This is an interesting dtrace probe description. This means tracking all the objective-c code that you apply to the process ID on the script.
This statement prints out the operation of the OBJECTIVE-C instance that triggered the probe, followed by the objective-c-style output. Here, you can see that the Probefunc and module char representing the function char is used here. The Probemod. DTrace has several internal variables you can use, Probefunc and Probemod are just two of them. You also have Probeprov and probename to use. Remember that the module will represent the Objective-c method on behalf of the class name simultaneous function. The Probemod and probefunc combinations are used here and are perfectly displayed in the OBJECTIVE-C syntax you are familiar with.
Now that you understand the script, remove the-G option so that you no longer use the debug option. In Lldb:
(lldb) Tobjectivec
This time you'll get a different output:
Copied script to Clipboard. Paste in Terminal
The contents of your clipboard have been changed. Go back to your terminal and paste the contents of your clipboard. Here's what I pasted up on the Clipboard, but you might be a little bit out of it:

Sudo/tmp/lldb_dtrace_profile_objc.d-p 95129 2>/dev/null
Everything you've seen before has been placed in the/tmp/lldb_dtrace_profile_objc.d file. If you're stubborn and want to know what this script does, I recommend you first cat it and then make sure you know what it does.
This script provides the identity of the lldb attached process (so you do not need to enter Pgrep Allocator).
If you see a prompt to enter your password, enter your password to get root privileges:

$ sudo/tmp/lldb_dtrace_profile_objc.d-p 95129 2>/dev/null
Password:
Starting ... use Ctrl + C to stop
Wait until the DTrace script prompts you that it has started running.
Make sure that Xcode and Terminal are visible and enter the PO [NSObject class] in the console. Check the output of this method for a large number of OBJECTIVE-C messages.

Picture. png
This time you are ready for the things that will come. Continue execution with Lldb, like this:

(LLDB) Continue
Browse the Allocator app in the iOS simulator (click on the view, press? + Y to bring up the call status bar) and watch the DTrace terminal window.
It's scary, isn't it?
Too much content is being exported here. Let's filter out some of the jamming information by adding content to the module modifier.
Back in Xcode, pause the execution of the allocator process and go to lldb.
Generate a new one that only focuses on scripts that contain StatusBar in the Objective-c class name. Enter the following in the LLDB:

(lldb) tobjectivec-m StatusBar -G
This will run and then output the following condensed content:

Objc$target:StatusBar:: Entry
{
printf ("0x%016p%c[%s%s]\n", arg0, Probefunc[0], Probemod,
(string) &probefunc[1]);
}
Notice how the probe of the module section is changed. you can use it as your favorite in regular expressions. This means that we are querying a case-sensitive probe containing the StatusBar Objective-c class.
In Lldb, remove the-G option to copy the script to the Clipboard and rerun the command.
Jump to your terminal window. Kill the previous DTrace instance by pressing CTRL + C, and then paste your new script.

(lldb) tobjectivec-m StatusBar
Go back to Xcode and continue with the execution.
Go back to the simulator and press? + Y call up status bar or use? +← or? +→ rotation Simulator watch the DTrace terminal window at the same time.
You will get some output again.
You can use DTrace to trigger and practice quickly when you need to specify a wide net with minimum performance in your code.

Trace Debug Commands

When I perform simple debug commands, I often get insight into what's going on behind the phenomenon and the code behind them working for me.
Take a look at how many objective-c methods have been called with a simple nsstring to do the arguments.
Back in Lldb, enter the following:

(LLDB) Tobjectivec
Paste the contents into the terminal window, but do not continue to execute in LLDB. Instead, you only need to enter the following:

(LLDB) po @ "Hi this was a long string to avoid tagged pointers"
When you press ENTER, check the contents of the DTrace terminal window and see what is being output. You will get some output similar to the following:

Picture. png

We just output a simple nsstring and see how many objective-c methods are being called!
All the output here is the Swift-style code.
Use? + K Empty the contents of the terminal to ensure that the DTrace scripts in the terminal are still running. Go back to Lldb and enter the following:

(LLDB) Expression-l Swift-o-Class B {}; B ()
You can then use Swift's debugging environment to create a pure swift class and initialize it. The swift code of the call is observed when the class is created.
DTrace will extract the following:

0x00000001087541b8 +[swiftobject class]
0x0000000119149778 +[swiftobject Initialize]
0x0000000119149778 +[swiftobject class]
If you copy any one of the DTrace output addresses and then po it, you'll see a lot of objective-c methods called by this Swift class.
It's not as pure as you think, is it?

Track an Object

You can use DTrace to easily track a specific invocation of a reference method. Press CTRL + C to remove the previous DTrace script.
While the application is in a paused state, use LLDB to get the UIApplication app. Make sure you re-objective-c the stack frame.

(LLDB) PO Uiapp
You will get output similar to the following:

<UIApplication:0x7fa774600f90>
Copy this reference and then use this reference to create a judgment sentence that will stop only when the reference is a arg0 parameter, and the first parameter of Objc_msgsend is an instance of the class or the class itself.

(LLDB) Tobjectivec-g-P ' arg0 = = 0x7fa774600f90 '
After your script runs in the console you will get output similar to the following:

#!/usr/sbin/dtrace-s
#pragma D option quiet
Dtrace:::begin {printf ("Starting ... use Ctrl + C to stop\n");}
dtrace:::end {printf ("ending...\n");}
/ Script content below /
objc$target:::entry/arg0 = = 0x7fa774600f90/
{
printf ("0x%016p%c[%s%s]\n", arg0, Probefunc[0], Probemod,
(string) &probefunc[1]);
}
It looks good! Perform this command again after removing the-G option:

(lldb) tobjectivec-p ' arg0 = = 0x7fa774600f90 '
Continue executing in lldb, and then paste your script in the terminal.
In the simulator, press the Home button (? + Shift + H) or the call status bar (? + Y).
This extracts every Objective-c method called by the [UIApplication Sharedapplication] instance.
Oh, the output looks too much, right? Then count their numbers!
Back in Xcode, pause execution and return to LLDB:

(LLDB) Tobjectivec-g-P ' arg0 = = 0x7fa774600f90 '-a ' @[probefunc] =
Count () '
This will produce the following script:

#!/usr/sbin/dtrace-s
#pragma D option quiet
Dtrace:::begin {printf ("Starting ... use Ctrl + C to stop\n");}
dtrace:::end {printf ("ending...\n");}
/ Script content below /
objc$target:::entry/arg0 = = 0x7fa774600f90/
{
@[probefunc] = count ()
}
You know this exercise. Rerun the Tobjectivec command above without the-G option, then paste the contents of your clipboard into the terminal and continue execution in LLDB. No content is displayed in the terminal. But DTrace secretly counted every method that the UIApplication instance called.
A large number of methods that are moved in the emulator to get uiapplication calls. When you kill the DTrace script with Ctrl + C, DTrace extracts all the objective-c methods that are called by the UIApplication instance.

Other DTrace methods

Here are some other ways to try it out in your free time:
Trace all initialization methods for all objects:

(LLDB) tobjectivec-f? init*
Detect communication-related logic in the process (e.g., webviews, keyboards, etc.):

(LLDB) Tobjectivec-m nsxpc*
Print out the subclass of the Uicontrol that handles the start touch event on your iOS device:

(lldb) tobjectivec-m uicontrol-f-touchesbegan?withevent?
Why do we have to learn this?

This is just the tip of the iceberg of DTrace. There are many things that dtrace can do.
I recommend you take a look at the following websites they have a lot of great resources to learn about DTrace.
? https://www.bignerdranch.com/blog/hooked-on-dtrace-part-1/
? https://www.objc.io/issues/19-debugging/dtrace/
In the next chapter, you'll learn more about DTrace and explore and dissect swift code.

Advanced+apple+debugging (15)

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.