platformio / platform-atmelsam

Atmel SAM: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/atmelsam
Apache License 2.0
78 stars 105 forks source link

toolchain-gccarmnoneeabi@1.90301.200702 fails with a segmentation fault on Asahi Linux #223

Open aykevl opened 2 months ago

aykevl commented 2 months ago

I have the following in my platformio.ini:

[env:adafruit_circuitplayground_m0]
platform = atmelsam
board = adafruit_circuitplayground_m0
framework = arduino

Unfortunately this results in a segmentation fault (error -11 is a segmentation fault):

$ pio run -j1 -v
Processing adafruit_circuitplayground_m0 (platform: atmelsam; board: adafruit_circuitplayground_m0; framework: arduino)
---------------------------------------------------------------------------------------------------------------
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_circuitplayground_m0.html
PLATFORM: Atmel SAM (8.2.1) > Adafruit Circuit Playground Express
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: 
 - framework-arduino-samd-adafruit @ 1.7.13 
 - framework-cmsis @ 2.50400.181126 (5.4.0) 
 - framework-cmsis-atmel @ 1.2.2 
 - toolchain-gccarmnoneeabi @ 1.90301.200702 (9.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 11 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
arm-none-eabi-g++ -o .pio/build/adafruit_circuitplayground_m0/src/main.cpp.o -c -fno-rtti -fno-exceptions -std=gnu++11 -fno-threadsafe-statics -mcpu=cortex-m0plus -mthumb -Os -ffunction-sections -fdata-sections -Wall -nostdlib --param max-inline-insns-single=500 -Wno-expansion-to-defined -DPLATFORMIO=60114 -D__SAMD21G18A__ -DCRYSTALLESS -DARM_MATH_CM0PLUS -DARDUINO_SAMD_ZERO -DADAFRUIT_CIRCUITPLAYGROUND_M0 -DARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS -DARDUINO=10805 -DF_CPU=48000000L -DUSBCON -DUSB_VID=0x239A -DUSB_PID=0x8018 "-DUSB_PRODUCT=\"Circuit Playground Expresso\"" -DUSB_MANUFACTURER=\"Adafruit\" -DARDUINO_ARCH_SAMD -DUSB_CONFIG_POWER=100 -DARDUINO_SAMD_ADAFRUIT -Iinclude -Isrc -I/home/ayke/.platformio/packages/framework-cmsis/CMSIS/Core/Include -I/home/ayke/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL -I/home/ayke/.platformio/packages/framework-arduino-samd-adafruit/cores/arduino -I/home/ayke/.platformio/packages/framework-arduino-samd-adafruit/libraries/Adafruit_TinyUSB_Arduino/src/arduino -I/home/ayke/.platformio/packages/framework-cmsis/CMSIS/DSP/Include -I/home/ayke/.platformio/packages/framework-arduino-samd-adafruit/variants/circuitplay src/main.cpp
*** [.pio/build/adafruit_circuitplayground_m0/src/main.cpp.o] Error -11
========================================= [FAILED] Took 0.49 seconds =========================================

Testing the compiler manually makes it more clear:

$ ~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-g++ --version
fish: Job 1, '~/.platformio/packages/toolchai…' terminated by signal SIGSEGV (Address boundary error)

I tracked it down to a page alignment issue in the binary. When I read the program headers, I get the following:

$ readelf --program-headers ~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-g++

Elf file type is EXEC (Executable file)
Entry point 0x402c80
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x00000000003ff040 0x00000000003ff040 0x000268 0x000268 R   0x8
  GNU_STACK      0x001000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  LOAD           0x000000 0x00000000003ff000 0x00000000003ff000 0x001000 0x001000 RW  0x1000
  DYNAMIC        0x0002a8 0x00000000003ff2a8 0x00000000003ff2a8 0x000200 0x000200 RW  0x8
  LOAD           0x001000 0x0000000000400000 0x0000000000400000 0x0ca4e4 0x0ca4e4 R E 0x1000
  NOTE           0x00128c 0x000000000040028c 0x000000000040028c 0x000044 0x000044 R   0x4
  INTERP         0x001570 0x0000000000400570 0x0000000000400570 0x00001b 0x00001b R   0x1
      [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
  GNU_EH_FRAME   0x0be928 0x00000000004bd928 0x00000000004bd928 0x0018f4 0x0018f4 R   0x4
  LOAD           0x0cc130 0x00000000004db130 0x00000000004db130 0x002e68 0x0056e0 RW  0x1000
  TLS            0x0cc130 0x00000000004db130 0x00000000004db130 0x000000 0x000010 R   0x8
  GNU_RELRO      0x0cc130 0x00000000004db130 0x00000000004db130 0x001ed0 0x001ed0 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     
   02     .dynamic .dynstr 
   03     .dynamic 
   04     .gnu.hash .interp .note.ABI-tag .note.gnu.build-id .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table 
   05     
   06     .interp 
   07     .eh_frame_hdr 
   08     .init_array .fini_array .data.rel.ro .got .got.plt .data .bss 
   09     .tbss 
   10     .init_array .fini_array .data.rel.ro .got 
   None   .dynsym .comment .symtab .strtab .shstrtab 

In particular, this LOAD header assumes a 4kB page system (the virtual address is aligned to 4kB and the alignment itself says 0x1000 which is 4kB):

  LOAD           0x000000 0x00000000003ff000 0x00000000003ff000 0x001000 0x001000 RW  0x1000

My system is Asahi Linux (Linux on ARM Macbooks) which use 16kB pages, not 4kB. So of course trying to map files on 4kB boundaries is going to fail. In fact, aarch64 systems can have up to 64kB page sizes.

Bumping the toolchain version up to 1.100301.220327 fixes the issue:

[env:adafruit_circuitplayground_m0]
platform = atmelsam
board = adafruit_circuitplayground_m0
framework = arduino
platform_packages = toolchain-gccarmnoneeabi@~1.100301.220327

And indeed, checking readelf --program-headers shows that the new arm-none-eabi-g++ binary uses 64kB page alignment.

I think this bug can be fixed in two ways: either by bumping up the GCC version to at least 1.100301.220327 or by rebuilding the older version in a way that fixes the alignment issue.