no-op instructions for ARM
At http://www.credil.org/ we had to deal with some code that was not yet
GPL compliant, fixing bugs (removing features!) from a .so file that we
had. We had some of the source code, but not enough to recompile it.
We needed to disable certain calls, so we disassembled the object file
with objdump -d. We then reviewed the code, looked for the calls
we wanted to remove, which are "bl" instructions.
../../prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-objdump -d libmyso.so >libmyso.S
All branch instructions are conditional, but one valid condition is "branch
always" (and link, which means it's a subroutine). See:
http://www.peter-cockerell.net/aalp and
http://www.peter-cockerell.net/aalp/html/frames.html, section C which is at:
http://www.peter-cockerell.net/aalp/html/app-c.html
Just look, if we change 'e' to 'f', it becomes Branch Never! We tried that.
Oops, this doesn't work. Peter Cockerell's book (from 1987) documents ARMv3,
and we are up to ARMv9. It seems that his bit pattern now means to branch,
and change to THUMB mode... The clue that this is what happens is that
when we disassembled the result we saw "blx", but the real clue was that the
offset was no longer "place", instead was "place+2". Thumb instructions are
16-bit big.
See http://www.keil.com/support/man/docs/armasm/armasm_cihfddaf.htm
for details of BLX.
So, how to create a NOP? We didn't see an official one.
Some googling revealed that "MOV R0 R0" is a good choice.
http://www.keil.com/support/man/docs/armasm/armasm_cjafcggi.htm
To assemble this:
First nibble is 0b1110 (15, 0xE) for "Always".
Second nibble is 0b0001 (1, 0x1), for 00, Immediate bit = 0, first bit of
opcode is 1. (The Opcode is 0b1101 (14, 0xD) for MOV)
Third nibble is 0b1010 (10, 0xA), three bits of opcode, S bit set to 0.
Fourth nibble is 0x0000 (R0), and Fifth nibble is 0x0000 (R0).
The last 12 bits are 0.
The result is: 0b1110 0001 1010 0000 0000 0000 0000 0000.
Or 0xE1A00000.
We didn't realize that the Android phones are in big-endian mode, so when we
searched for the right instructions to change, we did not find them.
When you objdump a .so file, it's mapped directly, so the offsets that
objdump products are actual file offsets.
Syndicated 2010-01-06 03:11:00 from Michael's musings