Karolis Milieška
Karolis Milieška

Reputation: 655

ARM GCC hardfault when using -O2

When using ARM GCC g++ compiler with optimization level -O2 (and up) this code:

void foo(void)
{
    DBB("@0x%08X: 0x%08X", 1, *((uint32_t *)1));
    DBB("@0x%08X: 0x%08X", 0, *((uint32_t *)0));
}

Compiles to:

0800abb0 <_Z3foov>:
 800abb0:   b508        push    {r3, lr}
 800abb2:   2301        movs    r3, #1
 800abb4:   4619        mov r1, r3
 800abb6:   681a        ldr r2, [r3, #0]
 800abb8:   4802        ldr r0, [pc, #8]    ; (800abc4 <_Z3foov+0x14>)
 800abba:   f007 fa83   bl  80120c4 <debug_print_blocking>
 800abbe:   2300        movs    r3, #0
 800abc0:   681b        ldr r3, [r3, #0]
 800abc2:   deff        udf #255    ; 0xff
 800abc4:   08022704    stmdaeq r2, {r2, r8, r9, sl, sp}

And this gives me hardfault at undefined instruction @0x0800abc2. Also, if there is more code after that, it is not compiled into final binary.

The question is why compiler generates it like that, why undefined istruction?

By the way, it works fine for stuff like this:

...
uint32_t num = 2;
num -= 2;
DBB("@0x%08X: 0x%08X", 0, *((uint32_t *)num));
...

Compiler version:

arm-none-eabi-g++.exe (GNU Tools for ARM Embedded Processors 6-2017-q2-update) 6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437]

Upvotes: 2

Views: 619

Answers (1)

Sean Houlihane
Sean Houlihane

Reputation: 1789

You can disable this (and verify this answer) by using -fno-delete-null-pointer-checks

The pointer you are passing has a value which matches the null pointer, and the compiler can see that from static analysis, so it faults (because that is the defined behaviour).

In your second example, the static analysis doesn't identify a NULL.

Upvotes: 2

Related Questions