user3728060
user3728060

Reputation: 21

Why this branch instruction of ARM doesn't work

Now I am writing a library to mock the trivial function for C/C++. It is used like this: MOCK(mocked, substitute) If you call the mocked function, the substitute function will be called instead.

I modify the attribute of code page and inject the jump code into the function to implement it. I have implemented it for x86 CPU and I want to port it to ARM CPU. But I have a problem when I inject binary code.

For example, the address of substitute function is 0x91f1, and the address of function to mock is 0x91d1. So I want to inject the ARM branch code into 0x91d1 to jump to the substitute function.

According to the document online, the relative address is

(0x91f1 - (0x91d1 + 8)) / 4 = 6

so the binary instruction is:

0xea000006

Because my arm emulator(I use Android arm v7 emulator) is little endian, so the binary code to inject is:

0x060000ea

But when I executed the mocked function after injecting branch code, segment fault occurred. I don't know why the branch instruction is wrong. I have not learned ARM architecture so I don't know whether the branch instruction of ARM has some limits.

Upvotes: 2

Views: 1625

Answers (2)

auselen
auselen

Reputation: 28087

Addresses you are branching to is odd numbered, meaning they are in Thumb mode.

There is an obvious problem with your approach.

If target is in Thumb mode, you either need to be in Thumb mode at the point you are branching from or you need to use a bx (Branch and Exchange) instruction.

Your functions are in Thumb mode (+1 at the target) but you are using ARM mode branch coding (B A1 coding?), so obviously either you are not in Thumb mode or you are using ARM mode instruction in Thumb mode.

Upvotes: 1

Thomas Matthews
Thomas Matthews

Reputation: 57688

The ARM family allows loading of registers with values. One of those registers is the PC (Program Counter).

Some alternatives:

  1. You could use a function to load the PC register with the destination address (absolute).
  2. Add the PC register with an offset.
  3. Use a multiply-and-add instruction with the PC register.
  4. Push the destination register onto the stack and pop into PC register.

These choices plus modifying the destination of the branch instructions are all different options at are not "best". Pick one that suits you best and is easiest to maintain.

Upvotes: 0

Related Questions