Issue
In Cortex-M7, I have a function, compiled with -Os
, that is in the specific address, and I call it through the function pointer, like so (+1
is for thumb mode):
//Some code above...
memset(.....)
uint32_t (*caller)(uint32_t taskid, ...);
caller = (uint32_t(*)(uint32_t, ...))((uint32_t)0x08020000 + 1U);
for (size_t i = 0; i < 3; ++i) {
caller(i);
}
Function gets called 3
times and returns, but i
parameter inside the function is not 0,1,2
, but rather garbage,0,1
. This is not the case if I do not use -Os
compiler option.
Inspecting disassembly, it seems that for loop is unrolled, with movs r0, #1
and movs r0, #2
, and it was even re-ordered.
memset(shared_ram, 0x00, sizeof(*shared_ram));
8000968: 2000 movs r0, #0
caller(i);
800096a: 4d1a ldr r5, [pc, #104] ; (80009d4 <main+0xc0>)
memset(shared_ram, 0x00, sizeof(*shared_ram));
800096c: 6018 str r0, [r3, #0]
800096e: 6058 str r0, [r3, #4]
8000970: 6098 str r0, [r3, #8]
caller(i);
8000972: 47a8 blx r5
8000974: 2001 movs r0, #1
8000976: 47a8 blx r5
8000978: 2002 movs r0, #2
800097a: 47a8 blx r5
Is this a compiler bug?
Cortex-M7 cache is not enabled, if that matters.
Compilation flags:
-fdata-sections -ffunction-sections --specs=nano.specs -Wl,--gc-sections -g -mthumb -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -Og -g3 -ggdb -fno-eliminate-unused-debug-symbols -fdata-sections -ffunction-sections -Wall -Wextra -Wpedantic -Wno-unused-parameter -Os -std=gnu11
Solution
Problem is not linked to compiler (99.9% the case). My function included identical branches, therefore compiler chose default
way and didn't bother with variable value.
__attribute__((section(".security_secure_gate")))
uint32_t se_secure_gate(uint32_t id, ...) {
switch (id) {
case 0: {
__NOP();
break;
}
default: {
__NOP();
break;
}
}
return 0;
}
Answered By - unalignedmemoryaccess Answer Checked By - Willingham (WPSolving Volunteer)