Comment 0 for bug 1973371

Revision history for this message
visda vokhshoori (visda) wrote :

hello,

Can you please confirm this is a bug?
If yes, is the local fix supplied acceptable?

Regards,
Visda

Source:
I have used the compiler explore to compiler the source
https://godbolt.org

The source file is:
#include <stdint.h>
#include <stddef.h>

typedef void (*funcptr_void) (void) __attribute__((cmse_nonsecure_call));
typedef uint32_t TC_COMPARE_STATUS;
funcptr_void secure_tc0_match0_interrupt_callback = NULL;
funcptr_void secure_tc0_overflow_interrupt_callback = NULL;

static void tc0_compare_handler (TC_COMPARE_STATUS status, uintptr_t context)
{
   if (status & ((0x1U) << (4U)))
        secure_tc0_match0_interrupt_callback ();

   else if (status & ((0x1U) << (0U)))
        secure_tc0_overflow_interrupt_callback ();

    else
    {

        while (1);

    }
}

int main ( void )
{
    uint32_t msp_ns = *((uint32_t *)(0x40000));
    volatile funcptr_void NonSecure_ResetHandler;

     TC0_CompareCallbackRegister (tc0_compare_handler, 0);

    if (msp_ns != 0xFFFFFFFF)
    {

        __TZ_set_MSP_NS(msp_ns);

        NonSecure_ResetHandler = (funcptr_void)(*((uint32_t *)((0x40000) + 4U)));

        NonSecure_ResetHandler();
    }

    while (1);

    return (1);
}

Compiler options; -fcrossjumping -mcmse -march=armv8-m.main -mfloat-abit=soft
Compiler version; ARM GCC 10.2.1 (none)
Compiler output; 1 with message message
<source>: In function 'main':
during RTL pass: mach
<source>: In function 'tc0_compare_handler':
<source>:23:1: internal compiler error: Segmentation fault
   23 | }
      | ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
Compiler returned: 1

Problem description:

In the example source provided, there are two cmse_nonsecure calls, guarded by a condition. Although the RTL of the calls generated look the same, but they are calls to different function, and hence crossjumping should not unify them.
The code generated after cross jumping pass looks really wrong. However, doesn't segfault.
The segfault occurs in RTL pass mach. where arm backend calls this function: cmse_nonsecure_call_clear_caller_saved(). the call stack at the time of segfault is;

(gdb) where
#0 0x000000000129eed1 in cmse_nonsecure_call_clear_caller_saved () at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/config/arm/arm.c:17830
#1 0x00000000012a00e3 in arm_reorg () at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/config/arm/arm.c:18189
#2 0x0000000000e14e4b in (anonymous namespace)::pass_machine_reorg::execute (this=0x24339d0)
    at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/reorg.c:3979
#3 0x0000000000d76479 in execute_one_pass (pass=0x24339d0) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/passes.c:2497
#4 0x0000000000d767de in execute_pass_list_1 (pass=0x24339d0) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/passes.c:2586
#5 0x0000000000d7680f in execute_pass_list_1 (pass=0x24337f0) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/passes.c:2587
#6 0x0000000000d7680f in execute_pass_list_1 (pass=0x2431bb0) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/passes.c:2587
#7 0x0000000000d76867 in execute_pass_list (fn=0x7ffff717b420, pass=0x242df80) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/passes.c:2597
#8 0x000000000096457d in cgraph_node::expand (this=0x7ffff717e2e0) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/cgraphunit.c:2139
#9 0x0000000000964a38 in expand_all_functions () at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/cgraphunit.c:2275
#10 0x0000000000965548 in symbol_table::compile (this=0x7ffff7248000) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/cgraphunit.c:2624
#11 0x00000000009657e0 in symbol_table::finalize_compilation_unit (this=0x7ffff7248000)
    at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/cgraphunit.c:2717
#12 0x0000000000ea343e in compile_file () at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/toplev.c:492
#13 0x0000000000ea5e9f in do_compile () at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/toplev.c:2189
#14 0x0000000000ea61a1 in toplev::main (this=0x7fffffffdac6, argc=23, argv=0x7fffffffdbc8)
    at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/toplev.c:2324
#15 0x00000000018e1ac7 in main (argc=23, argv=0x7fffffffdbc8) at /home/parallels/xc32-src/xc32-gcc/gcc/gcc/main.c:39

The statement it is on at the time of crash is:
fntype = TREE_TYPE (MEM_EXPR (address));
 the address is in r4. which is not live, REG_DEAD, in the following RTL expression.
r4 is set in this basic block's predecessor, below
(insn:TI 13 71 81 3 (set (reg:SI 4 r4)
(mem/f/c:SI (reg/f:SI 3 r3 [117]) [1 secure_tc0_match0_interrupt_callback+0 S4 A32])) "../src/main.c":102 878 {*thumb2_movsi_insn}
(expr_list:REG_DEAD (reg/f:SI 3 r3 [117])
(nil)))

My local fix is to define
#undef TARGET_CANNOT_MODIFY_JUMPS_P
#define TARGET_CANNOT_MODIFY_JUMPS_P arm_cannot_modify_jumps_p
and return true if use_cmse==true.