GCC arm instruction mode when compiling in thumb mode
As suggested by old_timer in a comment, the problem was that the assembly source code did not include .type asm_maxfilter, %function
before the label. The working assembly code begins as follows:
.arm
.section .text
.align 4
.globl asm_maxfilter
.type asm_maxfilter, %function
asm_maxfilter:
@ Store register states in stack. They must be restored before returning
push { r4, lr }
@ Reset counter
mov r3, #0
...
If the situation was reversed (ARM mode program using a thumb function), then instead of .type asm_maxfilter, %function
the type should have been .thumb_func
.
As per Jester's response, I noticed that the C code object file indeed has a R_ARM_THM_CALL
relocation segment, but without using the .type
macro, the branch instruction was not replaced by a bx
instruction.
If one implements an ARM function in a C file by using __attribute__((target("arm")))
without external assembly, ie:
#include <stdio.h>
#include <stdlib.h>
__attribute__((target("arm")))
void foo(int a) {
int b = 6*a;
fprintf(stderr, "%d\n", b*5);
}
int main(int argc, char** argv) {
int asd = atoi(argv[1]);
foo(asd);
return 0;
}
Then one can obseve a blx
instruction being correctly used in the generated binary. The problem I had is only a concern if one uses assembly code in a separate file that does not pass through a compiler.
The linker should take care of that automatically. If you objdump -dr
the object file, you should see a bl
with an R_ARM_THM_CALL
relocation, such as:
10: f7ff fffe bl 0 <asm_maxfilter>
10: R_ARM_THM_CALL asm_maxfilter
The linker will see that asm_maxfilter
is an arm function and turn the bl
into blx
, so the final executable may look like:
8360: f000 e808 blx 8374 <asm_maxfilter>