Advanced+apple+debugging (14)

Source: Internet
Author: User
Tags python list

As the last chapter in this section, you will go through the same steps, and I understand how the mallocstacklogging environment variables usually get stack records when an object is created.
From here, you will create a custom LLDB command that can give you a stack record that an object has been created or destroyed in memory--even after the stack record has left the debugger for a long time.
Knowing where an object in your program is creating a stack record is not only good for reverse engineering, but also helpful in your daily debugging work. When a process crashes, know the history of that piece of memory and any allocation that occurred before your process is over. Or deallocation events is extremely important.
This is another example of the script using the logic associated with the stack frame, but this chapter will focus on finding circular references, learning, and then implementing a very powerful custom command.

Setting Up Scripts

In this chapter you have a set of scripts to use (and implement). Let's take a look at how you use them:
? msl.py: This is a command script that you will use in this chapter (mallocstacklogging abbreviation). Here is a basic range of logic.
? lookup.py: Wait a minute-you've created this command, right? Yes, but I'll give you my own. Added a set of additional options in the ugly generation of the Look Up command version. You will use one of these commands to filter out the module that you are searching for in a process.
? sbt.py: This command will trace the unsigned symbol and symbolize it. You created this script in the previous chapters and you will often use it at the end of this chapter. If you skipped the previous section, you can find it in the Resources folder of this chapter.
? search.py: This command enumerates every object in the heap and searches for a specific subclass. This is a very handy command to quickly grab a reference to an instance of a particular class.

Note: These scripts are from HTTPS://GITHUB.COM/DEREKSELANDER/LLDB. If I need a tool I don't have, I'll build it and paste it on the website above. Download these scripts for books related to other lldb scripts.
Now go to the usual settings section. All of the Python files in this chapter can be found in the starter folder and then copied to the ~/lldb directory. I assume you have set up the lldbinit.py file, if not you can in the 22nd chapter "SB Examples, Improvedlookup." To find the setting method in the
Start a lldb session in the terminal and then use the Help command to ensure that each script is loaded successfully:

(LLDB) Help MSL
(LLDB) Help lookup
(LLDB) Help SBT
(LLDB) Help Search
mallocstacklogging explanation

If you are unfamiliar with the mallocstacklogging environment variable, I will explain it and illustrate his typical usage.
When the mallocstacklogging environment variable is set to true and passed to a process, it will monitor the allocation and release of memory in the heap. Clean and beautiful!
The Shades of Ray project contained in the Starter folder in this chapter has some additional logic. Open this project.
Before you run him, you need to modify its scheme in order to achieve your goal. Select the shades of Ray scheme (make sure the word "stripped" is not in the scheme name), and then press? + Shift + < to edit this scheme.
Select Run, then select Diagnostics, then select malloc Stack, and then select All Allocation andfree.

Picture. png

After you have enabled this environment variable, build the shades of Ray program and run it on the iphone 7 plus simulator.
If the mallocstacklogging environment variable is enabled, you will see some output similar to the following in the LLD console:
Shadesofray (12911,0X104E663C0) Malloc:stack logs being written into/
Tmp/stack-logs.12911.10d42a000.shadesofray.gjehfy.index
Shadesofray (12911,0x104e663c0) malloc:recording malloc and VM allocation
Stacks to disk using standard recorder
Shadesofray (12911,0x104e663c0) malloc:process 12673 no longer exists,
stack logs deleted from/tmp/stack-logs.
12673.11b51d000. ShadesOfRay.GVo3li.index
Don't care about the details of the output; Simply find out which part of the output shows that the mallocstacklogging is in effect.
When the app is running, click the Generate a ray button at the bottom.

Picture. png

When a new Ray is created (that is, you see a new, handsome, abnormal Ray Wenderlich instance appearing in the emulator), perform the following steps:
Select Debug Memory Graph located at the top of the LLDB console in Xcode.
Select Show the Debug Navigator in the left panel.
At the bottom of the left panel, select Show only content from workspace.
Select the Rayview Reference.
In the Panel on the right side of Xcode, make sure show the Memory Inspector is selected.
Picture. png

After you have finished the above operation, you will get the exact stack record where the Rayview instance is created, through the BackTrace section in Xcode. How cool is that?! These memory debugging features created by Xcode's author (and many of these modules) make our life easier!
XXX Program

You know, you can grab a stack record of an object initialization, but you'll do better than Apple.
Your command will be able to open the mallocstacklogging function via Lldb, which means that you no longer need to have an environment variable. There are some additional benefits, that is, if you forget to open the variable when you are debugging, you do not need to restart your process.
So how do you figure out how the Mallocstacklogging function works? When I feel no clue about navigating the internal code, I go into a fairly loose process and then modify the query content to make the decision based on the query's schema or output:
? I'll look for the process I'm attaching to that will be executed I can safely assume some of the logical blocking points that I'm interested in. If I knew I could replicate something I was interested in, I would force those events to happen while monitoring them.
? When monitoring our perceptual code, I use different tools like LLDB or dtrace (what you'll learn in the next chapter) to find the module of the code I'm interested in. Again, these modules may be a dynamic library, a framework, nsbundle or something derived from them.
? If I find the module I am interested in, I will extract all the code from this module and then use the different custom scripts I want to use such as lookup.py to do the filtering.
? If I find a function that seems to be relevant to what I am interested in, I will first Google this function. I often find you on the https://opensource.apple.com/some extremely useful advice on how I use what I find.
? Through Apple's Open source website search, I can also find a lot of content related to the part of the code that I'm interested in. Sometimes the code that gives me the idea of how to build arguments to functions is in a C + + file, perhaps I can find the description of the code in the header file or the purpose of the code.
? If I can't find a document on Google, I'll set a breakpoint on the code I'm interested in and see if I can trigger the code naturally. Once the breakpoint is triggered, I will look at the stack frame and register at the same time to see the type of parameters passed in and the context in which it resides.

Capture getenv

Mallocstacklogging is an environment variable that is passed to the process. This means that it is possible to use the C function getenv to check if this parameter is used and whether it will perform additional logic.
When the process starts, you need to extract all the subkeys that were queried with getenv. You will be executed with the 15th chapter "Hooking & executing codewith by creating a symbolic breakpoint to extract the incoming char* parameters when the getenv is invoked" Dlopen & Dlsym "the same operation.
In Xcode, create a symbolic breakpoint with the following logic:

? Symbol:getenv
? Action:po (char *) $arg 1
? Automatically continue after evaluating actions: YES!
Picture. png

Love to build and run this program when the mallocstacklogging variable is still checked. From the output, you can see where the process started, and here is the code to find the presence of mallocstacklogging.
Picture. png

Modify your symbolic breakpoint to fetch only the stack record when the program finds the mallocstacklogging environment variable:
? Symbol:getenv
? Condition: ((int) strcmp ("Mallocstacklogging", $arg 1) = = 0)
? Action:bt
? Automatically continue after evaluating actions: YES!
Picture. png

Once you have modified the symbol breakpoint, rerun the app.
In the console you will get some information about the stack record. Find the contents of the top stack frame:

  • Frame #0:0x0000000112b4da26 libsystem_c.dylib getenv<br/>frame #1:0x0000000112c7dd53<br/> Libsystem_malloc.dylib _malloc_initialize + 466
    Frame #2:0x0000000112ddcac1 libsystem_platform.dylib _os_once + 36<br/>frame #3:0x0000000112c7d849<br/>libsystem_malloc.dylib Default_zone_ malloc +
    Frame #4:0x0000000112c7d259
    libsystem_malloc.dylib malloc_zone_malloc + 103<br/>frame # 5:0x0000000112c7f44a libsystem_malloc.dylib malloc +
    Frame #6:0x0000000112aa2947 libdyld.dylib TLV _load_notification +<br/>286<br/>frame #7:0x000000010e0f68a9 dyld_sim Dyld::registerAddCallback (void
    () (Mach_header const , long)) + 134
    Frame #8:0x0000000112aa1a0d
    Libdyld.dylib _dyld_ Register_func_for_add_image + 61<br/>frame #9:0x0000000112aa1be7 libdyld.dylib _dyld_initializer + 47
    Very interesting ... Find the first stack frame:

    Frame #1:0x0000000112c7dd53 libsystem_malloc.dylib ' _malloc_initialize +
    466
    If I were an Apple author, I would probably check for a conditional environment variable to see if my code would work properly when it was initialized. These stack frames seem to do the same thing, plus the module name, libsystem_ Malloc.dylib looks like a library that implements the malloc stack log-related logic. That's it, right? maybe yes. It's worth checking out? absolutely worth it!
    Go deep inside the module and see what it gives you.
    Use the new, improved lookup command you think of to explore all the methods implemented in the Libsystem_malloc.dylib module that can be executed in your process.
    Pause your app in the debugger, and then enter the following command in the LLDB console:

(LLDB) lookup. -M Libsystem_malloc.dylib
On iOS 10.3, I found 292 and. I could have added comments for all of these methods, but as a debugger I was getting lazy. We still value capturing which functions contain the word log (in order to find logging) and see what results we will get. Enter the following in LLDB:

(LLDB) lookup (? i) log-m Libsystem_malloc.dylib
In the libsystem_malloc.dylib module I searched for 46 functions that contain the word log and are case-sensitive.
These quantities are acceptable in cluttered content.
Are there any interesting things in these functions? Of course. Here's a function that I think is more interesting:

Create_log_file
Open_log_file_from_directory
__mach_stack_logging_get_frames
Turn_off_stack_logging
Turn_on_stack_logging
Of the 5 most interesting functions I've chosen, the turn_on_stack_logging function and the __mach_stack_logging_get_frames function seem to be the most worth seeing.
You have found the modules of interest, as well as some functions worthy of further study. It's time to search Google and see what information you can find.

The JIT function in Google

Google any content that contains turn_on_stack_logging. This search looks like this:

Picture. png
When I wrote this book, I found three results from Google.
This function is not famous and is not often discussed after leaving the Apple circle. In fact, I'm pretty sure that most of Apple's iOS developers don't know about this function because when it comes to writing apps.
This information belongs to the C developers at the bottom of Apple that we are very respectful of.
From Google's search results, from Https://opensource.apple.com/source/libmalloc/libmalloc-116/private/stack_ Find the following code in the header file found in the logging.h.auto.html Web site:

typedef enum {
Stack_logging_mode_none = 0,
Stack_logging_mode_all,
Stack_logging_mode_malloc,
STACK_LOGGING_MODE_VM,
Stack_logging_mode_lite
} Stack_logging_mode_type;
extern boolean_t turn_on_stack_logging (stack_logging_mode_type mode);
These are very useful information. The Turn_on_stack_logging function expects to pass in a parameter of type int (the enumerated type of C). The Stack_logging_mode_type enumeration tells you that if you want the Stack_logging_mode_all option, its value will be 1.
You're going to run a project that turns off the stack frame log environment variable, do an experiment, execute the above function through LLDB, and see if Xcode will record the stack of objects that were assigned to you after calling the Turn_on_stack_logging function.
Before you do, you first need to browse another function __mach_stack_logging_get_frames.

Explore __mach_stack_logging_get_frames

Fortunately, because of your efforts to explore, the __mach_stack_logging_get_frames function can also be found in the same header file. The declaration of this function looks like this:

extern kern_return_t mach_stack_logging_get_frames (
task_t task,
mach_vm_address_t address,
mach_vm_address_t Stack_frames_buffer,
uint32_t max_stack_frames,
uint32_t
count);
/ Gets The last allocation record (malloc, realloc, or free) about
Address
/
This is a good starting point, but if there are parameters you can not 100% What are these parameters for? For example, what is a task_t task? This is the most basic parameter that indicates which process you want the function to execute on. But what if you don't know about this?
using Google and searching for any files that contain
mach_stack_logging_get_frames can be of great help when you are unsure of these things.
in Google's search results, HTTPS://LLVM.ORG/SVN/LLVM-PROJECT/LLDB/TRUNK/EXAMPLES/DARWIN/HEAP_FIND/HEAP/HEAP_ Find.cpp This site provides the interpretation of the first parameter of this function.
This file contains the following code:

task_t task = Mach_task_self ();
/ omitted code .... /
stack_entry->address = addr;
Stack_entry->type_flags = Stack_logging_type_alloc;
stack_entry->argument = 0;
Stack_entry->num_frames = 0;
Stack_entry->frames[0] = 0;
Err = __mach_stack_logging_get_frames (Task,
(mach_vm_address_t) addr,
Stack_entry->frames,
Max_frames,
&stack_entry->num_frames);
if (err = = 0 && stack_entry->num_frames > 0) {
Terminate the frames with zero if there are
if (Stack_entry->num_frames < max_frames)
Stack_entry->frames[stack_entry->num_frames] = 0;
} else {
G_malloc_stack_history.clear ();
}
} }
The task_t parameter in the Mach_task_self function in the Libsystem_kernel.dylib library makes it easy to get to the task that represents the current process.

Test these functions

In order to prevent you from shedding boring tears, I have implemented the __mach_stack_logging_get_frames logic in the app.

Picture. png

I hope your application is still running. If it is not running, re-enable the app to run in a state where mallocstacklogging is still enabled.
It's always a good idea to compile the JIT code that proves your concept first in Xcode, and if it works, then transfer it to your LLDB script. If you try to write the POC JIT script directly in Lldb, you will become disgusted with your life. Trust me.
In Xcode, locate the Stack_logger.cpp file. __mach_stack_logging_get_frames is written in C + +, so you need to execute it in C + + code.
The only functions in this file are trace_address:
void trace_address (mach_vm_address_t addr) {
typedef struct LLDBSTACKADDRESS {
mach_vm_address_taddresses;
uint32_t count = 0;
} lldbstackaddress; 1
Lldbstackaddress stackaddress; 2
Unused mach_vm_address_t address = (mach_vm_address_t) addr;
Unused task_t task = Mach_taskself; 3
Stackaddress.addresses = (mach_vm_address_t
) calloc (100,
sizeof (mach_vm_address_t)); 4
__mach_stack_logging_get_frames (Task,
Address
Stackaddress.addresses,
100,
&stackaddress.count); 5
for (int i = 0; i < Stackaddress.count; i++) {
printf ("[%d]%llu\n", I, stackaddress.addresses[i]);
}
Free (stackaddress.addresses); 7
}
It's time to dismantle!

As you know, Lldb only lets you return an object when it executes. However, as your own creative version of the string theory, you can create a C struct that contains any type that you want to return.
Use this function to declare an instance of the struct described above.
Remember what Mach_task_self quoted earlier? The global variable mach_task_self_ is the return value when you call Mach_task_self.
Because you're manipulating the underlying stuff, there's no arc to help you allocate items in the heap. You are allocating 100 mach_vm_address_t of space that are sufficient to handle any stack record.
Then execute the __mach_stack_logging_get_frames. If there is any available stack record information, the lldbstackaddress structure will be added to the addresses array.
Print out all the addresses we found.
Finally, the mach_vm_address_t you created was released.
LLDB Test

Make sure the app is still running, then click the Generate a ray! button. Pause execution and enter the following command into LLDB:

(LLDB) Search Rayview-b
The search script enumerates all the objects contained in the heap. This command captures all Rayview instances that are still present.
The-B option will give you the--brief function, releasing the description or Debugdescription method of the class. You will get a variable that records the number of times that Ray Wenderlich is connected to your emulator.
There are three magical ray Wenderlich faces in my simulator, so my output is as follows:

(LLDB) Search Rayview-b
Rayview [0x00007fa838414330]
Rayview
[0x00007fa8384125f0]
Rayview * [0x00007fa83860c000]
Grab any of the above addresses and execute them in the Trace_address function:

(LLDB) Po trace_address (0x00007fa838414330)
Your output should look something like this:

[0] 4533269637
[1] 4460190625
[2] 4460232164
[3] 4454012240
[4] 4478307618
[5] 4482741703
[6] 4478307618
[7] 4479898204
[8] 4479898999
[9] 4479899371
...
Here is the actual address of the code that was executed when the object was created. Verify with the image Lookup command that the first address stores the code in memory:

(lldb) Image Lookup-a 4533269637
You will get more information about this function:

ADDRESS:LIBSYSTEM_MALLOC.DYLIB[0X000000000000F485]
(Libsystem_malloc.dylib. TEXT. Text + 56217)
Summary:libsystem_malloc.dylib ' Calloc + 30
There is more than one way to view the contents of a memory address. Copy the address of the third frame after it is accommodated use sbaddress to remove the information from this address:

(lldb) script print lldb. Sbaddress (4454012240, Lldb.target)
You'll get the 3rd frame in the stack, like this:

Shadesofray '-[viewcontroller generaterayviewtapped:] + atviewcontroller.m:38
Browse c arrays with Lldb.value

You will again use the Lldb.value class to parse the C struct that is returned when the function is executed.
Set a GUI structure where the trace_address function ends:

Picture. png

Perform the same function with LLDB, but respect the breakpoint, and remember to replace the address with your Rayview instance with the following:

(LLDB) e-lobjc++-o-i0--trace_address (0x00007fa838414330)
Execution will stop at the last line of trace_address. You understand this operation. Grab a reference to the lldbstackaddress C struct, stackaddress.

(lldb) script print lldb.frame.FindVariable (' stackaddress ')
If successful, you will get the stackaddress variable in the form of:

(lldbstackaddress) stackaddress = {
Addresses = 0x00007fa838515cd0
Count = 25}
Assign the return value of the Lldb.value function to a reference:

(lldb) Script a = Lldb.value (lldb.frame.FindVariable (' stackaddress '))
Make sure that a is a valid value:

(lldb) script print a
Now you can simply refer to the variables declared in the Lldb.value function lldbstackaddress the struct body. Enter the following in LLDB:

(lldb) script print A.count
You will get the number of stack frames:

(uint32_t) Count = 25
What is the addresses array in the lldbstackaddress structure?

(lldb) script print a.addresses[0]
That is the memory address of the first frame. Generaterayviewtapped in the third frame: what is a function like?

(lldb) script print a.addresses[3]
You will get some output similar to the following:

(mach_vm_address_t) [3] = 4454012240
Do you see how these tools are grouped together? Start by finding the blocking point you're interested in, browse through the code in the module, re-search for useful information on the https://opensource.apple.com/website, and first validate your idea in Xcode before writing the Lldb Python code. There is a lot of power underneath the lid.
Don't slow down-it's time to implement the command!

To pass a number into the stack frame

The msl.py script in the starter directory of this chapter is used to record the malloc log. You have installed scripts scripts in the previous "Setting upthe msl.py" section.
Unfortunately, the script can do very little now, because it doesn't produce any output. It's time to change it.
Open the ~/lldb/msl.py with your favorite editor. Locate the Handle_command command and add the following code:

Command_args = shlex.split (command)
Parser = Generateoptionparser ()
Try
(options, args) = Parser.parse_args (Command_args)
Except
Result. SetError (Parser.usage)
Return
Cleancommand = Args[0]
Process = Debugger. Getselectedtarget (). GetProcess ()
frame = process. Getselectedthread (). Getselectedframe ()
target = debugger. Getselectedtarget ()
These logic should not be unfamiliar to you, as it is the necessary preamble to the starting part of the command. The only interesting point is that you choose to ignore the posix=false parameters that are sometimes used in shlex.spli. There is no need to provide this parameter because this command does not handle any wacky backslash and dash characters. This means that the output parsed from the options and the args variable will be clearer.
Now that you have the most basic script, you just need to complete the rest of the script correctly as follows:

#1
Script = Generatescript (Cleancommand, Options)
#2
Sbval = frame. EvaluateExpression (script, Generateoptions ())
#3
If sbval.error.fail:
result. Appendmessage (str (sbval.error))
return
val = lldb.value (sbval)
addresses = []
#4
for I in range ( val.count.sbvalue.unsigned):
address = val.addresses[i].sbvalue.unsigned
Sbaddr = target. Resolveloadaddress (address)
LoadAddr = sbaddr. Getloadaddress (target)
Addresses.append (loadaddr)
#5
retstring = processstacktracestringfromaddresses (
addresses,
target)
#6
freeexpr = ' Free (' +str (val.addresses.sbvalue.unsigned) + ') '
frame. EvaluateExpression (freeexpr, Generateoptions ())
result. Appendmessage (retstring)
Here are a few interesting points:

I used the Generatescript function, which returns a string that has the same coarse code as the Trace_address function.
Execute this code. You know Zhejiang returned to a sbvalue.
Be wise to check if evaluateexpression fails. If it fails, extract the error message and exit as soon as possible.
This for loop iterates through the memory addresses in the Val object, which outputs the script's code and places them in the address list.
Now that the address has been placed in a list, you can use that list to predefine the function that will be processed. This returns the stack record string that will be output.
Finally, you manually allocate memory, I believe you are a good memory management can receive and always in the back empty allocated memory. You've written down most of the memory leak scripts, but now you need to learn more advanced knowledge, it's time to do something right and free the memory allocated before.
Go back to Xcode's LLDB console and reload the script:
(LLDB) Reload_script
If you have not encountered any errors, use the LLDB Search command to fetch a Rayview reference:

(LLDB) Search Rayview-b
Just to introduce, there is another way to do this. Search for subclasses in all Shadesofray modules:

(lldb) Search Uiview-m shadesofray-b
If you have a Rayview subclass reference, run your newly created MSL command on this reference as follows:

(LLDB) MSL 0x00007fa838414330
In Xcode you will get the desired output!

Frame #0:0x11197d485 libsystem_malloc.dylib calloc + 30<br/>frame #1 : 0x10d3cbba1 libobjc.A.dylib class_createinstance + 85
Frame #2:0x10d3d5de4 LIBOBJC. A.dylib _objc_rootAlloc + 42<br/>frame #3 : 0x10cde7550 ShadesOfRay -[viewcontroller
Generaterayviewtapped:] + 64
Frame #4:0x10e512d22 UIKit '-[uiapplication
SendAction:to:from:forEvent:] + 83
Cheer Up! You have created a script that can track the stack record of an object. Now it's time to give the script some cool options to upgrade the code!

Stack record for Swift objects

Well--I know you want me to talk some swift code. You will also learn a swift example.
The shades of Rayapp contains a swift module, named Someswiftmodule. In this module there is a Someswiftcode class with a unique static variable.
The code in Someswiftcode.swift is very simple:

Public final class Someswiftcode {
Private init () {}
static Let shared = Someswiftcode ()
}
You will use LLDB to invoke this method and check the stack record for this well-established location.
First, you need to import your Swift module! In LLD do not enter the following content:

(LLDB) E-lswift-o--Import Someswiftmodule
You will not get any output after the command of the polygon has been successfully run.
In Lldb, you can access this static variable with the following command:

(LLDB) E-lswift-o--someswiftcode.shared
You will get the memory address of this object:

<SomeSwiftCode:0x600000033640>
Now you're going to pass this memory address to the MSL command. Simply copying and pasting from the output is simply too simple. Replace and search for Swiftobject subclasses with the search command:

(LLDB) Search Swiftobject
You will get some output similar to the following:

<__nsarraym 0x6000004578b0> (
Someswiftmodule.someswiftcode
)
Again, Swift tries to hide the pointer in the description. That's part of Swift magic.
At the end of the search command, use the--brief (-B) option to grab that instance and ignore the description method of the object.

(LLDB) Search Swiftobject-b
This will fetch the scrambled names, but in memory they are the same references.

_ttc15someswiftmodule13someswiftcode * [0x0000600000033640]
Pass this address to the MSL command:

(LLDB) MSL 0x0000600000033640
You will get the expected stack record.

Picture. png
The frame of the marker clearly indicates where you call this static variable in the LLDB. Your may be different from mine.
Let's go to the last topic I want to discuss briefly: how to compile these scripts when you create features in a LLDB script so that you "don't need to repeat what you've done".

Run Python code only

Stop running this app! In the scheme list, choose stripped Shades of ray this scheme.
Make sure that the mallocstacklogging environment variable is not checked in stripped shades of Ray's scheme.

Picture. png

Well, Ray agrees.
It's time to try out the turn_on_stack_logging function. Build and run the application. As you can find in the previous chapters, the stripped shades of Ray scheme will streamline the contents of the executable so there is no debugging information available here. Remember those descriptions when you use the MSL command.
If the application is running, click the Generate a ray! button to create a new Rayview instance. Because mallocstacklogging is disabled, let's see what happens ...
Pause execution and enter the following in LLDB to search for all rayviews:
(LLDB) Search Rayview-b
You will get some output similar to the following:

Rayview * [0x00007fc23eb00620]
Take a look at whether the MSL uses this address:

(LLDB) MSL 0x00007fc23eb00620
There's nothing. As we expected, because that environment variable was not applied to the process. Time to look back and see what Turn_on_stack_logging did. Enter the following in the LLDB:

(LLDB) Po turn_on_stack_logging (1)
You will get some similar output after you apply the mallocstacklogging environment variable to your process:

Picture. png
Continue and click on the button at the bottom to create another Rayview instance.
If you have finished the above operation, pause execution and search all Rayview instances again.
This time you will get a new address. If you want to enable the stack logging, you will get this record.
Copy the new address and apply it to the MSL command:

(LLDB) MSL 0x00007f8250f0a170
This will give the stack record!

Picture. png

It's a surprise! You can enable the malloc log before you will be monitoring any allocation or deallocation events without restarting your process.
Wait a minute, wait a few seconds .... Here is a shortened symbol.
Picture. png

Ray doesn't like a function that's not streamlined.
If you can recall the previous chapter, you previously created an SBT command that symbolized the stack record. In the sbt.py script, you create a processstacktracestringfromaddresses function with a numeric array and a sbtarget parameter. This function returns a string with the potential to symbolize the stack record.
You have completed the most difficult part of the function, so why not include this feature in the msl.py script optional execution?
Go to the topmost position of the msl.py function and add the following import statement:
Import SBT
In the Handle_command function of the msl.py file, locate the following code:

RetString = Sbt.processstacktracestringfromaddresses (
Addresses
Target
Replace the above code with the following code:

If options.resymbolicate:
RetString = Sbt.processstacktracestringfromaddresses (
Addresses
Target
Else
RetString = Processstacktracestringfromaddresses (
Addresses
Target
Your condition is to check the Options.resymbolicate option. If true, then the logic of invoking the SBT module looks at whether it can generate a string of the re-symbolized function.
Because you write that function as a property and work with a python list of numbers, you can easily pass this information from your MSL script.
Before you test this code, there is a last paragraph that needs to be implemented. You need to create a shortcut command to enable turn_on_stack_logging.
Skip to the __lldb_init_module function (the function is still in the msl.py) file and add the following line of code:

Debugger. Handlecommand (' command alias enable_logging expression-lobjc-o--extern void turn_on_stack_logging (int); turn_on_ Stack_logging (1); ')
This line of command declares a shortcut command to open the malloc stack log.
"Yes!" It's done! Go back to Xcode and reload your code:

(LLDB) Reload_script
Use the--resymbolicate option on the previous Rayview to view fully symbolized stack records.

(LLDB) MSL 0x00007f8250f0a170-r
Picture. png

In the face of such a beautiful stack record I am so happy to cry! Finally, I can breathe!

Why are we learning this?

Hopefully, the full implementation of this attention, the re-search and the useful implementations that have been validated, can even inspire you to create your own scripts. Many of the powerful features in your [I|mac|tv|watch]os device are also hidden in many of the frameworks.
All you need to do is find these hidden treasures and develop them into crazy business debugging tools, or refer them to reverse engineering to better understand what's going on.
Here's a list of directories worth browsing in your actual iOS device:
? /developer/
? /usr/lib/
? /system/library/privateframeworks/
Go ahead and make our dreams come true!

Advanced+apple+debugging (14)

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.