Matching up offsets in iOS crash dump to disassembled binary

3.7k views Asked by At

I'm having trouble matching up the offsets in the stack traces of iOS crash dumps with offsets in the disassembly of the binary as output by otool.

Can anybody confirm how in principle I match these up. For example, if I get a line in the crash dump:

0 myapp  0x00005b0a  0x1000 + 19210

would I expect the offset of the offending instruction in the binary file to be 0x5b0a, 0x4b0a.... or something else?

In its decoding of the header information, otool also gives, for example, this information (the actual code starts at offset 0x0000224c in the file):

Section
  sectname __text
   segname __TEXT
      addr 0x0000224c
      size 0x00063ad2
    offset 4684
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
 reserved1 0
 reserved2 0

So, I wasn't 100% sure I was interpreting this correctly, but it seems to be saying that the code, at +0x224c in the file, ends up at offset 0x124c in memory, but then I wasn't exactly sure how this fitted in with, for example, the location 0x1000.

The problem I have is that given, say, the offset 0x5b0a, neither the instruction there nor at 0x4b0a nor at 0x6b0a makes sense as being the actual instruction in question (including that fact that e.g. locations further down the stack then don't point to branch instructions).

(I know that, at least on earlier incarnations of ARM, there was a discrepancy between the value of the PC and the corresponding memory address due to the instruction pipeline. I was assuming that such a difference would be taken into account in the offsets reported in the crash dump, or at any rate, I'd see the branch instruction in question a few instructions either side of the one pointed to if such a difference wasn't taken into account...)

Can anybody shed any light?

2

There are 2 answers

1
Evan On BEST ANSWER

Provided that myapp did not strip out symbols you'll be able to use atos.

You can always man atos for more details but this should be sufficient for your problem:

-o symbol_file # debugging information output by the compiler this may be a dSYM or the binary itself depending on who you saved symbol information
-l load address # the base address in the process space at which your library is loaded into the springboard process (Looks like 0x1000)
Also a list of addresses you wish to symbolicate

Usage:
    atos -o myapp -l 0x1000 0x00005b0a 0x0005bca ... etc

That output should be a list of symbol names to the terminal. Again, this requires that the myapp did not have symbols stripped out.

0
mathiash On

Add the virtual address of the __TEXT segment to the relative address given in the crash dump. The result is the address to look up in the disassembly. Here are the steps:

  1. Use otool -lv <application-binary> to dump the load commands from the application binary. Look for the load command for the __TEXT segment and the associated value for vmaddr, typically 0x1000. You don't need the information about the __text section that is shown above, just the information about the segment.

  2. In the crash dump, addresses in the call stack are given in the form 0x00124ff4 0xf4000 + 200692. The last part is an offset within the binary in decimal. Add this to the value obtained in step 1 and convert to hexadecimal. In this example, we would calculate 0x1000 + 200692 which is 0x31ff4 in hex.

  3. Use otool -tV <application-binary> to dump disassembly for the application binary. Locate the address obtained in step 2 (0x31ff4 in this example). For the topmost frame of the call stack this is where the application crashed. For all other levels, at the calculated address should be a branch instruction which corresponds to the next higher level in the stack.