So let’s say an integrator tells you that he’s using the iOS library version 1.10.10, and he found the crash:

Fatal Exception: NSInvalidArgumentException 
*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]

And the Crash log looks like this:

9  libobjc.A.dylib                0x39a6ada3 objc_exception_throw + 250
10 CoreFoundation                 0x2eddd413 -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 530
11 CoreFoundation                 0x2eddd1db +[NSDictionary dictionaryWithObjects:forKeys:count:] + 50
12 payleven-iPad                  0x00422699 -[ADYTransactionProcessor setFailureInfoFromResponse:] (ADYTransactionProcessor.m:732)

So we see the problem is in file ADYTransactionProcessor on line 732. So you go to your source code, you look the tag 1.10.10 and you look on that line, and guess what do you see - the code is not there, and you already included the check for that error.

Well, maybe when you made a build something BAD happened, and the old file got in? How can we tell this?

There is a way! Reverse engineering!

So we download the compiled library, same thet the integrator is using, and we extract the symbol from it:

lipo -info AToolkit
lipo AToolkit -thin armv7 -output a7
ar -t a7
ar -xv a7 ADYTransactionProcessor.o
lldb ADYTransactionProcessor.o

Now we check the crashed address 0x00422699:

(lldb)image lookup --address 0x00422699

Nothing. To find out where the function is:

(lldb) image lookup -n setFailureInfoFromResponse:
1 match found in ADYTransactionProcessor.o:
Address: ADYTransactionProcessor.o[0x00004068] (ADYTransactionProcessor.o.__TEXT.__text + 16488)

BTW, we could also lookup the line number, knowing what function should be there. For example, in 1.10.10, the line number 1320 should be in function numericState, while in the other version, it could be statusIsFinal:

(lldb) image lookup -l 1320 -f ADYTransactionProcessor.m
1 match found in ADYTransactionProcessor.m:1320
Summary: ADYTransactionProcessor.o`-[ADYStatusTenderResponse numericState]

UPDATE: As noted by a friend, another way to get the info about the address is:

atos -arch armv7 -o ADYTransactionProcessor.o 0x00004068
-[ADYTransactionProcessor setFailureInfoFromResponse:] (in ADYTransactionProcessor.o) (ADYTransactionProcessor.m:659)