https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91297

            Bug ID: 91297
           Summary: ARM Cortex M0+ gets hard fault due to unexpected
                    pointer content
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: murat.ursavas at gmail dot com
  Target Milestone: ---

Hello,

I'm not sure I can label this issue as a bug. Let me share my findings and let
you decide what it is.

The library I was using for three years was working just fine. Then I decided
to switch manufacturers and core (from Cortex M3 to Cortex M0+) things started
to get weird. The library is now triggering a hard fault, without a proper
reason.

Hard faults are generally triggered while trying to access a nullptr or some
non-existing regions. Thus the main causes are generally dangling pointers.
I've checked this for it but no, everything is looking fine.

Here's the minimum reproducible example.

*****
#include <cstdint>
int main(void)
{
        uint8_t foo[15];
        void *buffer = foo;
        uint16_t calculated = 1234;
        uint16_t length = sizeof(foo);

        uint16_t *obtained =
reinterpret_cast<uint16_t*>(&(reinterpret_cast<uint8_t*>(buffer)[length - 2]));
        if(calculated == *obtained)
        {
                return 0;
        }
        else
        {
                return -1;
        }
}
*****

The disasembly generated for this simple main is here:
(g++ Compiler options: -mcpu=cortex-m0plus -std=gnu++14 -g3 -O0
-ffunction-sections -fdata-sections -fno-exceptions -fno-rtti
-fno-threadsafe-statics -fno-use-cxa-atexit -Wall -fstack-usage
--specs=nano.specs -mfloat-abi=soft -mthumb)

Some irrelevant include and define options have been removed.

*****
main():
08000108:   push    {r7, lr}
0800010a:   sub     sp, #32
0800010c:   add     r7, sp, #0
 6              void *buffer = foo;
0800010e:   adds    r3, r7, #4
08000110:   str     r3, [r7, #28]
 7              uint16_t calculated = 1234;
08000112:   movs    r1, #26
08000114:   adds    r3, r7, r1
08000116:   ldr     r2, [pc, #52]   ; (0x800014c <main()+68>)
08000118:   strh    r2, [r3, #0]
 8              uint16_t length = sizeof(foo);
0800011a:   movs    r0, #24
0800011c:   adds    r3, r7, r0
0800011e:   movs    r2, #15
08000120:   strh    r2, [r3, #0]
10              uint16_t *obtained =
reinterpret_cast<uint16_t*>(&(reinterpret_cast<uint8_t*>(buffer)[length - 2]));
08000122:   adds    r3, r7, r0
08000124:   ldrh    r3, [r3, #0]
08000126:   subs    r3, #2
08000128:   ldr     r2, [r7, #28]
0800012a:   adds    r3, r2, r3
0800012c:   str     r3, [r7, #20]
11              if(calculated == *obtained)
0800012e:   ldr     r3, [r7, #20]
08000130:   ldrh    r3, [r3, #0]   ;<<<<<< Hard Fault triggering line
08000132:   adds    r2, r7, r1
08000134:   ldrh    r2, [r2, #0]
08000136:   cmp     r2, r3
08000138:   bne.n   0x800013e <main()+54>
13                      return 0;
0800013a:   movs    r3, #0
0800013c:   b.n     0x8000142 <main()+58>
17                      return -1;
0800013e:   movs    r3, #1
08000140:   negs    r3, r3
19        }
*****

I've commented which line is triggering the hard fault. 

Here's the register contents just before running that line at instruction
level:

*****
r0      0x18 (Hex)      
r1      0x1a (Hex)      
r2      0x200007d8 (Hex)        
r3      0x200007e5 (Hex)        
r4      0xffffffff (Hex)        
r5      0xffffffff (Hex)        
r6      0xffffffff (Hex)        
r7      0x200007d4 (Hex)        
r8      0xffffffff (Hex)        
r9      0xffffffff (Hex)        
r10     0xffffffff (Hex)        
r11     0xffffffff (Hex)        
r12     0xffffffff (Hex)        
sp      0x200007d4 (Hex)        
lr      0x8000253 (Hex) 
pc      0x8000130 (Hex) 
xpsr    0x1000000 (Hex) 
PRIMASK 0x0 (Hex)       
BASEPRI 0x0 (Hex)       
FAULTMASK       0x0 (Hex)       
CONTROL 0x0 (Hex)       
MSP     0x200007d4 (Hex)        
PSP     0xfffffffc (Hex)        

*****

r3 is correctly carrying the 'obtained' variables pointing address and it's
valid on STM32L011K4. But running it triggers hard fault exception.

So from my point of view the generated object code by the G++ compiler is fine.
But I'll be glad if you can check my analysis and help me for finding the root
cause.

Right now I'm suspecting from a weird core errata.

Regards,

Reply via email to