When running llvm-objdump -macho -rebase on a binary that I presume to be
fully valid (published in the app store), the output was:
llvm-objdump: '/path/to/Some.app/Some': truncated or malformed object (for REBASE_OPCODE_ADD_ADDR_IMM_SCALED bad segOffset, too large for opcode at: 0x123)
The state and sequence is:
- Handling REBASE_OPCODE_ADD_ADDR_IMM_SCALED
- Precondition: RebaseEntryCheckSegAndOffset
- The opcode is applied and SegmentOffset is incremented accordingly
- Postcondition RebaseEntryCheckSegAndOffset
The precondition in step 2 fails. The reason is the index,offset pair points
exactly to the end of a section, but the check is called with endInvalid = true
which makes the check reject offsets pointing to the end of a section. Given
that this check happens before applying the opcode, and the opcode
produces a valid offset that passes the check in step 4, it seems erroneous
to fail the precondition.
This fix is to pass false for endInvalid in the precondition in step 2.
Note that this is the only check that with endInvalid = false. Why is it valid for the offset to point to the end of a section here and only here? Could it be that the precondition and postcondition of this opcode are flipped? In other words, why is it valid for SegmentOffset to point to the end of a section after applying the opcode, but not before applying the opcode? Shouldn't it be the other way around?