Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 714
Allen Bauer Avatar asked May 27 '12 21:05

Allen Bauer


People also ask

Is there a debug mode for iPhone?

Navigate to Settings and enable Debug Mode At the bottom, toggle the switch to enable Debug mode.

What is debug symbols in iOS?

Debug Symbols are additional information about your source code that are used to help debugging. See also this wikipedia article about debug symbols. They will not be submitted to the appstore as they are only part of debug-build while you only submit a release-build to the appstore.


2 Answers

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).

  1. Create a new like-named empty Xcode project. Build and run it on the device.
  2. Locate the output bundle's .app folder.
  3. Copy the above raw iOS executable over the existing one in the .app bundle's folder.
  4. The application will now have an invalid signature and cannot be deployed and run.
  5. Run codesign against the app bundle (you can find out the command-line by running xcodebuild on the above Xcode project).
  6. 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).
  7. Add a symbolic breakpoint (I used GDB instead of LLDB) and enter the address as '*0x00001234' as the symbol.
  8. 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.

like image 173
Allen Bauer Avatar answered Oct 16 '22 20:10

Allen Bauer


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...

like image 32
Kendall Helmstetter Gelner Avatar answered Oct 16 '22 20:10

Kendall Helmstetter Gelner