A large part of diagnosing Hopper issues is trying new things. I always encourage calculated change to see how change may affect your Hopper outcomes. Often however, what you think might be an updated executable is actually just a rebuilt version of the prior one with an updated timestamp which is not helpful.

 So how do you know that your changes made it into the new binary?

 Microsoft provides a utility called dumpbin that can tell you exactly what is in each binary. If you can read and understand ARM assembly then the process is easy – you simply look for your change in the output and if its present then you are done. If not, your change got lost somewhere during the build or sysgen and you need more investigation. If you cannot read and understand ARM assembly, you are still in luck since you can focus on finding change – simply compare the old version with the new binary to determine the difference.  For example, we needed to make a change to Hopper that dealt with how we handled the CEFlushDBVol() function call – this is what the assembler looked like before we made the change:

 Dumpbin /disasm hopper.exe > oldHopper.out

 

  00036DE4: EB002851 bl        SetLastError

  00036DE8: E3A00000 mov       r0, #0

  00036DEC: EB00284C bl        CeFlushDBVol     << Call that we change here

  00036DF0: E3500000 cmp       r0, #0

  00036DF4: 1A000004 bne       00036E0C

  00036DF8: EB002804 bl        GetLastError

  00036DFC: E59F1044 ldr       r1, [pc, #0x44]

  00036E00: E1A02000 mov       r2, r0

  00036E04: E5950000 ldr       r0, [r5]

  00036E08: EBFFFB4D bl        00035B44

  00036E0C: E5869000 str       r9, [r6]

  00036E10: EA000000 b         00036E18

 

And then we perform the same check on the new binary with our changes (in this case a check to see if CeFlushDBVol() failed with ERROR_OUT_OF_MEMORY):

Dumpbin /disasm hopper.exe > newHopper.out

 

  0004F898: EB00254A bl          SetLastError

  0004F89C: E3A00000 mov         r0, #0

  0004F8A0: EB002584 bl          CeFlushDBVol   << Here is the same call

  0004F8A4: E3500000 cmp         r0, #0         << Checking return same as above

  0004F8A8: 1A000009 bne         0004F8D4

  0004F8AC: EB0024C1 bl          GetLastError   

  0004F8B0: E1A02000 mov         r2, r0

  0004F8B4: E5950000 ldr         r0, [r5]

  0004F8B8: E3520008 cmp         r2, #8         << Compare for out of memory error   

  0004F8BC: 1A000002 bne         0004F8CC

  0004F8C0: E59F1040 ldr         r1, [pc, #0x40]

  0004F8C4: EBFFF43E bl          0004C9C4

  0004F8C8: EA000001 b           0004F8D4

 

Notice how there is no check for error code #8 in the first disassembler output? Since it shows up in the latest binary we can be certain that the change made it into the latest revision. Warning: This is not a perfect solution since the code optimizer can move code which might obscure your changes. You can always turn off the optimizing to increase your chances of finding this scenario with the /Od flag.