Programatically generate stack trace in Objective C - ios

I am interested in getting a readable stack-trace when my iPhone/iPad crashes. I would like to send this information to our server once it is trapped. I know there are tools like Crashlytics that do this very well, but we would like to stay away from any 3rd party tools if at all possible. The only way I know to get this info is to manually do it by retrieving the and then have that file symbolicated on a Mac before it can be analyzed. Even doing this can be troublesome if you don't have a copy of the original application binary and the .dSYM file that was generated when that binary was built. I believe Crashlytics does this somehow without the actual binary or the .dSYM file which leads me to believe that a simple stack trace can be generate programmatically. Has anyone done this or have any pointers as to how I could do this within Objective C so that I could send that information to our servers for Error reporting?
Is it at all possible to get a create a readable stack-trace within Objective C on my iOS device without having to first send that file to a Mac with both the actual binary or the .dSYM file?

Just use
[NSThread callStackSymbols]

Related

Transfer file from iOS app to computer while debugging

For a native iOS application we are integrating a C++ library which is writing some logs to disk to json file.
During debugging, we would like to access to this logs, but currently we can only do it by downloading the whole app container to the macOS machine and searching for the file there.
Since this a very time consuming operation we were hoping that there would be some solution that would allows us to get this file quickly. I did take a look to the lldb commands, but none of them seem to let you extract a file from the phone.
Is there anyway to do this in a quick way?
Thank you
Couple options...
1 - Add debug-only code in your app to share the log file (via AirDrop would probably be a good option).
or
2 - During debug, set these two keys (in project settings / info) to Yes:
Application supports iTunes file sharing
Supports opening documents in place
Once you've done that, you can open / copy files from your app's Documents directory (assuming that's where the logs are being written) from Finder on your Mac.

How to decompile iOS apps?

I want to see the code of an iOS app.
The app I downloaded is .deb.
First question: Is it possible to install .deb file on iOS or I downloaded a wrong file?
After unpacking the .deb file, I got some files, including .nib, .storyboard and some other files.
My main question is, How to decompile these .nib files?
I tried to decompile these files using NibToXibConverter, but I didn't succeed.
Answer to your first question:
I think you downloaded the wrong file. .deb files for iOS are common for jailbreak community and not for apps, I think all of the Cydia stuffs are packed into .deb's. If your app is especially made for the jailbreak scene then you may try to install it using Cydia's auto install feature on a jailbroken device.
Answer to your main question:
This is general info about decompiling and modifying iOS apps (not specific for nibs, but you may still find it useful).
iOS apps are distibuted in .ipa archives, which are ordinary zip archives. They contain, usually one executable in the form of Mach-O file, and resources like .plist, sounds, images - every resource you include in your xcode project. Decompiling the executable file is only possible on jailbroken iDevice, because it is encrypted especially for the current device and the magic key to decrypt the binary is burned inside the device CPU and as far as I know there is no software way to read that key. The encryption system here is called FairPlay.
Briefly described, one way to decrypt that binary is to have the app installed on a jailbroken device, and launch it from command line using a debugger (gdb) which you can download from Cydia. You have to set a breakpoint somewhere, and when your code execution pauses at the breakpoint, you are doing a memory dump of the device ram - and that is your decrypted bin.
So when you have the decrypted binary, you can run one tool called "class-dump", and get the information for declared classes and their methods if the app is written in Objective C. Once you know this information you can alter the implementation of given method from some class used in your app using "Cydia Subtstrate" a.k.a "Mobile Substrate". In fact that is the way all of the jailbroken iOS tweaks are made. Basically you are hooking a method call, and when that method get invoked, it uses your implementation. Furthermore your implementation can call the original implementation, and that is really useful if you want to make some small code addition.
I am not sure whether those things possible in Swift, but if you are dealing with a Hybrid app like the ones done with cordova, phonegap, etc., then you can see all of its javascript source because it is persisted as a resource inside the "ipa" file. In addition you can alter that javascript code directly if you have a jailbroken device and find where the app is installed on file system (usually /var/containers/Bundle/Application/uuid_for_your_app/). However, I think there is no way to get that patched version and redistribute it (correct me if I'm wrong).

Symbolicate crash report without the app binary

I'm investigating how to create a server side iOS crash report symbolication server like Crashlitics or Crittercism or HokeyApp, from I can see, they only ask the user to upload the .dSYM file then they are able to symbolicate the crash report, I'm wondering how they archive it? Apple's standard symbolicatecrash command needs the app binary and the .dSYM file being provided together:
Symbolication - resolving stack trace addresses to source code methods and lines - requires the application binary that was uploaded to the App Store and the .dSYM file that was generated when that binary was built. This must be an exact match - otherwise, the report cannot be fully symbolicated. It is essential that you keep each build distributed to users (regardless of the details of that distribution) with its .dSYM file.
Any one knows the detail? Thanks.
Symbolication is the process of translating stack traces into a human-readable form by mapping hexadecimal addresses to function names using symbol file. In other words, Symbolication can be defined as the process of de-obfuscating code symbols with debug symbols removed to both reduce package size and make it harder to reverse engineer. Apteligent automatically symbolicates crashes once you have uploaded your app’s symbol file.
For Apple applications, stack traces are reported in hexidecimal characters. Symbolication allows developers to convert these hex strings into human-readable text.
For more information please refer to and http://support.crittercism.com/articles/knowledge_base/How-does-iOS-Symbolication-work and https://www.apteligent.com/developer-resources/symbolicating-an-ios-crash-report/

NSLog not printing messages to console after packaging the static library to a framework

I have a static library which I use this iOS Framework Script to generate a .framework file and distribute to developers.
But, currently there is an issue appeared that it only happens when packaging and using the .framework in a client application! When using the static library by the way it works perfect, NSLog and the problem I have it's not reproducing.
What I want to ask is, why I lost my NSLog messages? Does this have to do with debug/release scheme configuration? The framework script does not seem to remove with any configuration in the command line the debug logging, I don't remember anyway if in release it removes the NSLogs?!
Any thoughts how to make my debug NSLog messages appear again, maybe a setting that I switched values and now banging my head to find and resolve the issue?
I found the proper way to use log messages with level as instructed by Apple using the ASL (Apple Logging System).
https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/LoggingErrorsAndWarnings.html#//apple_ref/doc/uid/10000172i-SW8-SW1
That said using this great wrapper by Mike Weller did the job and I can control better the logging to console plus I finally have console output from my static framework.

Debug iOS application on device without symbols

I need to debug the startup for an ios application on an actual device... and by start up I mean the very first instruction that is is executed when the OS hands control over to the app. Not "main". Also, this application doesn't have any symbols (ie. the debug information isn't available.. yet). I don't care if I have to debug at the CPU instruction level. I know how to do that (done it for over 30 years). I want the debugger to stop when control is about to transfer to the app. When I use the Attach|by Name command and run, it just says "Finished running".
Oh, and this application was not built in XCode. It is, however an application I built, signed and provisioned and moved to the device. The application does run since I can see the console output. Just in case you're thinking I'm some hacker trying to debug someone's application.
How's that for a tall order? I'll bet nobody can answer this... I've not been able to find any information on how I could do this with an XCode-built project. I wonder if it is simply not possible or "allowed" by the Apple overlords?
What do you say, Stack Overflow gods?
UPDATE: I should clarify something. This application is not built with any commercially available or open-source tool. I work with a tools vendor creating compilers, frameworks, and IDEs. IOW, you cannot get this tool... yet. In the process of bootstrapping a new tool chain, one regularly must resort to some very low-level raw debugging. Especially if there are bugs in the code generated by the tools.
I'm going to answer my own question because I think I've stumbled upon a solution. If anyone has anything more elegant and simple than this, please answer as well. On to the steps:
Starting with a raw monolithic iOS executable (not a bundled .app, but the actual binary mach-o file that is the machine code).
Create a new like-named empty Xcode project. Build and run it on the device.
Locate the output bundle's .app folder.
Copy the above raw iOS executable over the existing one in the .app bundle's folder.
The application will now have an invalid signature and cannot be deployed and run.
Run codesign against the app bundle (you can find out the command-line by running xcodebuild on the above Xcode project).
In the bundle's .app folder, run otool -h -l on the binary image. Locate the LC_UNIXTHREAD load command and find the value associated with the 'pc' register. This is address where the os loader will jump to your application. If this address is odd, then these are Thumb instructions otherwise it will be ARM (I think that's how it works).
Add a symbolic breakpoint (I used GDB instead of LLDB) and enter the address as '*0x00001234' as the symbol.
Select Product|Perform Action|Run Without Building.
Assuming that GDB is able to evaluate the breakpoint expression and set the break point, and you've selected Product|Debug Workflow|Show Disassembly When Debugging, the process should break at the very first instruction to be executed in the application.
You can now single step the instructions and use the GDB console to get/set register values.
Your question does not make sense - main is the entry point into the application. It is the first code that should be encountered, unless possibly you have initialize() overridden for some classes (but even then I think main would get hit before the runtime).
I think you are seeing some kind of odd error on launch and you think you want to set a breakpoint on entry to catch it, but far more likely what would help you is to describe the problem on launch and let one of the 4000 people who have seen and fixed the same crash help you...
However, if you really want to use GDB to break on an application with no symbols (but that you launch from XCode) you can have GDB break on an assembly address as per:
How to break on assembly instruction at a given address in gdb?
To find the address of main (or other methods) you can use tool or atos, some examples in this question:
Matching up offsets in iOS crash dump to disassembled binary
ADDITION:
If for some reason XCode cannot launch your application for debugging, you could also jailbreak and install GDB on the device itself which would give complete control over debugging. If XCode can launch you application I see no reason why being able to break at an arbitrary memory address does not give you the ability you seek...
One solution for applications with webviews is to run them in the iOS Simulator, and connect to that with the remote-debugger in macOS Safari. This is off-topic but maybe the one or other could benefit.
http://hiediutley.com/2011/11/22/debugging-ios-apps-using-safari-web-inspector/
Or use NetCat for iOS... not the most perfect solution, but at least you see what's going on.

Resources