From 05df45dfeeac98849940dc4995e9fdbe2077ebdc Mon Sep 17 00:00:00 2001 From: Ricard Rosson Date: Sat, 11 Jul 2026 12:26:06 +0100 Subject: [PATCH] boards/rp23xx: copy .got into RAM at boot in the memmap linker scripts The pico-sdk-derived rp23xx linker scripts place .got/.got.plt as orphan sections after the .data output section, so the boot-time .data copy (which runs to _edata) never copies the GOT into RAM. Any position- independent (-fPIC) object linked into an application then reads an uninitialised GOT full of NULLs: the first GOT-indirected access branches to 0 and the board hardfaults before main(). A PIC static library (for example liboqs, whose SHA3 dispatch reads its function pointers through the GOT) triggers this deterministically. Fold *(.got)/*(.got.plt) into the .data{} section, before _edata, in all three boot-mode scripts (memmap_default/copy_to_ram/no_flash) for every rp23xx board, so the GOT is initialised in RAM by the standard startup copy. No effect on non-PIC images (the GOT is empty). Reproduced and fixed on a Raspberry Pi Pico 2 W: an app linking a -fPIC liboqs.a wedged the board on its first crypto call before the change and runs correctly after it. Co-Authored-By: Claude Opus 4.8 Signed-off-by: Ricard Rosson --- .../pimoroni-pico-2-plus/scripts/memmap_copy_to_ram.ld | 10 ++++++++++ .../pimoroni-pico-2-plus/scripts/memmap_default.ld | 10 ++++++++++ .../pimoroni-pico-2-plus/scripts/memmap_no_flash.ld | 10 ++++++++++ .../raspberrypi-pico-2/scripts/memmap_copy_to_ram.ld | 10 ++++++++++ .../raspberrypi-pico-2/scripts/memmap_default.ld | 10 ++++++++++ .../raspberrypi-pico-2/scripts/memmap_no_flash.ld | 10 ++++++++++ .../rp23xx/xiao-rp2350/scripts/memmap_copy_to_ram.ld | 10 ++++++++++ .../arm/rp23xx/xiao-rp2350/scripts/memmap_default.ld | 10 ++++++++++ .../arm/rp23xx/xiao-rp2350/scripts/memmap_no_flash.ld | 10 ++++++++++ 9 files changed, 90 insertions(+) diff --git a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_copy_to_ram.ld b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_copy_to_ram.ld index 8be73dbc2b3..efb4a7d6d84 100644 --- a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_copy_to_ram.ld +++ b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_copy_to_ram.ld @@ -184,6 +184,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_default.ld b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_default.ld index b59a2ce94a2..7e833a433a2 100644 --- a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_default.ld +++ b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_default.ld @@ -211,6 +211,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_no_flash.ld b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_no_flash.ld index 81dea5b79d6..19dedcb0307 100644 --- a/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_no_flash.ld +++ b/boards/arm/rp23xx/pimoroni-pico-2-plus/scripts/memmap_no_flash.ld @@ -133,6 +133,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_copy_to_ram.ld b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_copy_to_ram.ld index a4f6a5aa329..d0e24362f70 100644 --- a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_copy_to_ram.ld +++ b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_copy_to_ram.ld @@ -184,6 +184,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_default.ld b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_default.ld index 63732249491..0dd692a659f 100644 --- a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_default.ld +++ b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_default.ld @@ -211,6 +211,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_no_flash.ld b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_no_flash.ld index 505f9333c7e..a13d8784209 100644 --- a/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_no_flash.ld +++ b/boards/arm/rp23xx/raspberrypi-pico-2/scripts/memmap_no_flash.ld @@ -133,6 +133,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_copy_to_ram.ld b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_copy_to_ram.ld index 35505dbdd0b..b29b3f3f96f 100644 --- a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_copy_to_ram.ld +++ b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_copy_to_ram.ld @@ -184,6 +184,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_default.ld b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_default.ld index c5a87098eb9..bac343540ee 100644 --- a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_default.ld +++ b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_default.ld @@ -211,6 +211,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4); diff --git a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_no_flash.ld b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_no_flash.ld index 0a5bedfe064..60cb3c9114e 100644 --- a/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_no_flash.ld +++ b/boards/arm/rp23xx/xiao-rp2350/scripts/memmap_no_flash.ld @@ -133,6 +133,16 @@ SECTIONS *(.data*) *(.sdata*) + /* GOT/PLT must live INSIDE the copied .data range so a flat + * -fPIC object (e.g. a PIC static library linked into an app) + * gets an initialised GOT in RAM at boot; otherwise an orphan + * .got lands after _edata, is never copied, and every GOT- + * indirected access reads a NULL pointer (hardfault). */ + . = ALIGN(4); + *(.got) + *(.got.plt) + *(.got*) + . = ALIGN(4); *(.after_data.*) . = ALIGN(4);