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,