How to manually symbolize [NSThread callStackSymbols] (get start address for atos) (iOS)

Goal:

I want to symbolize the "output" [NSThread callStackSymbols] .

Side notes:

I know how to do this with crash logs. However, I need to research some problems when I would like to look at the call stack. Unfortunately, these days all the images of the <redacted> structure. Causing the failure at the right points (or at the end - see the end of my question) is actually not acceptable, but if I cannot find another solution, this will be the way to go.

I need to run my tests on the device, so I can not use Simulator.

Current approach:

When I call this:

 NSLog(@"call stack:\n%@", [NSThread callStackSymbols]); 

I get this output:

 2015-12-08 15:04:03.888 Conversion[76776:4410388] call stack: ( 0 Conversion 0x000694b5 -[ViewController viewDidLoad] + 128 1 UIKit 0x27259f55 <redacted> + 1028 ... 9 UIKit 0x274f67a7 <redacted> + 134 10 FrontBoardServices 0x2b358ca5 <redacted> + 232 11 FrontBoardServices 0x2b358f91 <redacted> + 44 12 CoreFoundation 0x230e87c7 <redacted> + 14 ... 16 CoreFoundation 0x23038ecd CFRunLoopRunInMode + 108 17 UIKit 0x272c7607 <redacted> + 526 18 UIKit 0x272c22dd UIApplicationMain + 144 19 Conversion 0x000767b5 main + 108 20 libdyld.dylib 0x34f34873 <redacted> + 2 ) 

(The "Transform" in this release is an app.)

Now I can use this command to "symbolize" the addresses:

 xcrun atos -o /path/to/Conversion.app -arch arm64 -l 0x0??? 

Start like this (of course, with the correct value for -l ), I can enter addresses like 0x000694b5 , and it will spit out something like -[ViewController viewDidLoad] + 128 . Of course, the problem is the starting address (the value of the -l option).

When I have a crash log, I can get them. However, I would like to leave without a crash.

Questions:

Q1: Can I determine the start address at runtime and possibly include it in the log output so that I can pass it to the atos -l parameter?

EDIT: it looks like this is possible: (thanks to NSProgrammer for the answer to https://stackoverflow.com/a/4646252/ )

 #import <mach-o/dyld.h> ... intptr_t slide = _dyld_get_image_vmaddr_slide(0); const struct mach_header * load_addr = _dyld_get_image_header(0); NSLog(@"slide %lx load addr %lx", (long)slide, (long)load_addr); 

/ EDIT

(Since I'm interested in calls to the framework method, I certainly need the starting addresses of the frameworks. Often the application’s starting address (randomization), I don’t know if the starting addresses of the structure are randomized.)

Q2: Are there other methods for exploring methods in the call stack? (breakpoints are also pretty awkward in my scenario.)

EDIT:

Q3: How can I symbolize the addresses of frameworks? For example, where can I find dSYM (or something else) for UIKit?

(For example, I have something: ~/Library/Developer/Xcode/iOS\ DeviceSupport/9.1\ \(13B143\)/Symbols/System/Library/Frameworks/UIKit.framework/ . I will take a closer look here.)

/ EDIT

Possible solution:

One way could be to save the output of the log to a file, and at the end of the tests, a failure in the application. Thus, the start address will also be displayed in the failure log with information from the call stack from the logs, which I should be able to symbolize the output of callStackSymbols . I will try the following.

+5
source share
2 answers

Adding log fragments to the crash log has worked well so far, so I will add this as an answer for now. (Better answers are definitely welcome :-))

Preparations:

Add a callStackSymbols entry to the appropriate places in the source code:

 NSLog(@"call stack:\n%@", [NSThread callStackSymbols]); 

Make the application crash (for example, when a certain screen opens):

 strcpy(0, "000"); 

Redirect log output to file:

 FILE *logfile = freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr); 

Execution:

In Xcode, run the application once so that it is installed on the device, and then stop it. Then run the application directly on the device, so that Xcode will not catch a glitch.

Use the application so that the call log is logged (can be many times).

Ultimately crash the application (in my case, open a specific screen that causes a bad strcpy file).

Receiving files:

In Xcode, open “Window → Devices”, select the device, select the application, and load the application container so that the log file can be extracted.

On the same screen, open the device log and export the fault log.

In Xcode, open Window → Projects, select the project and show the derived data folder in Finder (a small arrow to the right of the derived data path). In the folder with the derived data, go to "Build / Products / Debug-iphoneos /" and copy MyApp.app and MyApp.app.dSYM.

Adjust the crash log:

For me, this worked to add additional stream sections right in front of the "Binary Images:". Therefore, find the location "Binary Images:". Insert the line "Thread 9999:". Copy and paste the dump stack calls and delete the leading columns of spaces so that they look like this:

 2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree ( Thread 9999: 0 MyApp 0x00000001001d95f8 -[MyClass myMethod:] + 100 1 UIKit 0x000000018a5fc2ac <redacted> + 172 2 UIKit 0x000000018a5d5ca4 <redacted> + 88 3 UIKit 0x000000018a5d5b8c <redacted> + 460 4 UIKit 0x000000018a5d5cc0 <redacted> + 116 5 UIKit 0x000000018a5d5b8c <redacted> + 460 6 UIKit 0x000000018a5d5cc0 <redacted> + 116 7 UIKit 0x000000018a5d5b8c <redacted> + 460 8 UIKit 0x000000018a8e85ac <redacted> + 460 9 UIKit 0x000000018a5d4abc <redacted> + 96 10 UIKit 0x000000018a935b7c <redacted> + 344 11 UIKit 0x000000018a9306f8 <redacted> + 124 12 UIKit 0x000000018aa584d8 <redacted> + 44 13 UIKit 0x000000018a933d9c <redacted> + 188 14 UIKit 0x000000018a70b668 <redacted> + 116 15 UIKit 0x000000018a70b454 <redacted> + 252 16 UIKit 0x000000018a70af38 <redacted> + 1404 17 UIKit 0x000000018a70a9a8 <redacted> + 124 18 UIKit 0x000000018a616d3c <redacted> + 312 19 UIKit 0x000000018a616bc4 <redacted> + 108 20 QuartzCore 0x0000000189dddc2c <redacted> + 284 21 libdispatch.dylib 0x000000019a3a96a8 <redacted> + 16 22 libdispatch.dylib 0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844 23 CoreFoundation 0x00000001850001f8 <redacted> + 12 24 CoreFoundation 0x0000000184ffe060 <redacted> + 1628 25 CoreFoundation 0x0000000184f2cca0 CFRunLoopRunSpecific + 384 26 GraphicsServices 0x000000018ff94088 GSEventRunModal + 180 27 UIKit 0x000000018a644ffc UIApplicationMain + 204 28 MyApp 0x0000000100093918 main + 124 29 libdyld.dylib 0x000000019a3da8b8 <redacted> + 4 Binary Images: ... 

The line "Thread 9999:" allows the symbolicatecrash script to display the following lines. I chose 9999, so I know that these were my added sections.

Run the symbolism:

Find the symbolicatecrash script:

 $ find /Applications/Xcode.app -name symbolicatecrash -type f /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash $ 

The symbology command looks something like this:

 $ symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

You need to set DEVELOPER_DIR and add the path to the script, so in the end it looks like this:

 $ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

Or wrapped up for better enjoyment:

 $ DEVELOPER_DIR='/Applications/Xcode.app/Contents/Developer' ... /Applications/Xcode.app/Contents/SharedFrameworks/ ... DTDeviceKitBase.framework/Versions/A/Resources/ ... symbolicatecrash myapp.crash MyApp.app.dSYM > myapp-sym.crash 

Result:

Symbolized fragments now look like this:

 2015-12-09 15:28:58.971 MyApp[21376:3050653] call tree ( Thread 9999: 0 MyApp 0x00000001001d95f8 -[MyClass myMethod:] (MyFile.m:15) 1 UIKit 0x000000018a5fc2ac -[UIScrollView _willMoveToWindow:] + 172 2 UIKit 0x000000018a5d5ca4 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 88 3 UIKit 0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 4 UIKit 0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116 5 UIKit 0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 6 UIKit 0x000000018a5d5cc0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 116 7 UIKit 0x000000018a5d5b8c -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 460 8 UIKit 0x000000018a8e85ac __UIViewWillBeRemovedFromSuperview + 460 9 UIKit 0x000000018a5d4abc -[UIView(Hierarchy) removeFromSuperview] + 96 10 UIKit 0x000000018a935b7c __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke596 + 344 11 UIKit 0x000000018a9306f8 -[UIPresentationController transitionDidFinish:] + 124 12 UIKit 0x000000018aa584d8 -[_UICurrentContextPresentationController transitionDidFinish:] + 44 13 UIKit 0x000000018a933d9c __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188 14 UIKit 0x000000018a70b668 -[_UIViewControllerTransitionContext completeTransition:] + 116 15 UIKit 0x000000018a70b454 -[UITransitionView notifyDidCompleteTransition:] + 252 16 UIKit 0x000000018a70af38 -[UITransitionView _didCompleteTransition:] + 1404 17 UIKit 0x000000018a70a9a8 -[UITransitionView _transitionDidStop:finished:] + 124 18 UIKit 0x000000018a616d3c -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312 19 UIKit 0x000000018a616bc4 -[UIViewAnimationState animationDidStop:finished:] + 108 20 QuartzCore 0x0000000189dddc2c CA::Layer::run_animation_callbacks(void*) + 284 21 libdispatch.dylib 0x000000019a3a96a8 _dispatch_client_callout + 16 22 libdispatch.dylib 0x000000019a3aedb0 _dispatch_main_queue_callback_4CF + 1844 23 CoreFoundation 0x00000001850001f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 24 CoreFoundation 0x0000000184ffe060 __CFRunLoopRun + 1628 25 CoreFoundation 0x0000000184f2cca0 CFRunLoopRunSpecific + 384 26 GraphicsServices 0x000000018ff94088 GSEventRunModal + 180 27 UIKit 0x000000018a644ffc UIApplicationMain + 204 28 MyApp 0x0000000100093918 main (main.m:16) 29 libdyld.dylib 0x000000019a3da8b8 <redacted> + 4 Binary Images: ... 

If I find an easier approach, this will be the way to go now for me. It may be useful to create a script that pulls call stacks from the log file, removes leading spaces and inserts them into the fault log.

+3
source

SYMBOLICATECRASH

Apple sends a script with Xcode, which speeds up the process of symbolizing the complete crash report. If you have dSYM, a binary application, and a crash report, this is probably the easiest way to label. You do not need to worry about any of the addresses - this script will analyze the entire crash dump file and use ATOS to resolve all addresses to characters for you.

Find in your system "symbolicatecrash":

 cd /Applications/Xcode.app find . -name symbolicatecrash 

Export DEVELOPER_DIR environment variable if it does not exist

 export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer" 

Copy the binary .app file, the crash report, and the .dSYM file to a temporary folder (e.g. ~ / tmp). Run the script, as in our example below:

 /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash -v ApteligentExampleApp.crash ApteligentExampleApp.app.dSYM/ 

If all goes well, the script should symbolize your entire crash file and display the result in a terminal window. This script does not do anything that you could not do manually using ATOS or another tool, but it will help you faster.

Source

0
source

Source: https://habr.com/ru/post/1237660/


All Articles