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>

Tags:

C

Gcc

Assembly

Arm