This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Linker generates wrong call from thumb to arm in blx instruction

Version 11.2-2022.02 of the GNU Toolchain contains a bug in the encoding of calls using blx instruction from thumb to arm instructions. When the size of the jump is exactly 16MB + 2, the jump is encoded as a jump of 2 instead of indirect jump. Next code reveals this error.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
__attribute__((target("arm"))) int __attribute__ ((noinline)) f();
#define DIRECT_CALL \
asm ("NOP");
#define ERROR_CALL \
DIRECT_CALL \
asm ("NOP"); \
asm ("NOP"); \
asm ("NOP"); \
asm ("NOP");
#define INDIRECT_CALL \
ERROR_CALL \
asm ("NOP"); \
asm ("NOP"); \
asm ("NOP");
__attribute__((target("thumb"))) int main()
{
asm ("NOP");
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

To reproduce the error the example must be compiled using 

arm-none-eabi-g++ -std=gnu++17 -mcpu=cortex-a9 -mfpu=vfpv3 -fdata-sections -ffunction-sections -mfloat-abi=hard -O3 -save-temps=obj -fverbose-asm --specs=nosys.specs $TEST_FILE

and the result must be disassembled using 

arm-none-eabi-objdump -d a.out > a.s

In the resulting a.s the first call to function f() is encoded as:

8036: f000 e800 blx 8038 <main+0x8>

just a jump of offset 2 from address 8036. This is wrong.

The test has been compiled with AArch32 bare-metal target (arm-none-eabi)

0