Skip to content

boards/rp23xx: copy .got into RAM at boot in the memmap linker scripts#19401

Merged
acassis merged 1 commit into
apache:masterfrom
ricardgb:rp23xx-got-ram
Jul 11, 2026
Merged

boards/rp23xx: copy .got into RAM at boot in the memmap linker scripts#19401
acassis merged 1 commit into
apache:masterfrom
ricardgb:rp23xx-got-ram

Conversation

@ricardgb

Copy link
Copy Markdown
Contributor

Summary

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().

This is not hypothetical — a -fPIC static library is enough. In my case a NuttX
app linking a -fPIC liboqs.a (whose SHA3 dispatch reads its function pointers
through the GOT) wedged the board deterministically on its first crypto call.

The fix folds *(.got)/*(.got.plt) into the .data{} section, before _edata,
in all three boot-mode scripts (memmap_default / memmap_copy_to_ram /
memmap_no_flash) for every rp23xx board, so the GOT is initialised in RAM by the
standard startup copy.

Impact

  • Fixes a boot-time hardfault for any -fPIC library linked into an rp23xx app.
  • No effect on non-PIC images — the GOT is empty, so the added sections copy
    zero bytes.
  • Applies uniformly to raspberrypi-pico-2, xiao-rp2350 and
    pimoroni-pico-2-plus.

Testing

Reproduced and fixed on a Raspberry Pi Pico 2 W. With the original scripts, an app
linking a -fPIC liboqs.a hardfaulted on its first hardware crypto call (traced
to a NULL GOT-indirected dispatch pointer; the ELF showed .got landing exactly at
_edata, i.e. outside the copied range). After folding .got into .data, the
GOT is populated in RAM and the same app runs correctly.


Disclosure: this change was prepared by an AI agent (Claude Code) at the direction
of the author, who root-caused and tested it on hardware before submission.

🤖 Generated with Claude Code

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 <noreply@anthropic.com>
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
@github-actions github-actions Bot added Size: S The size of the change in this PR is small Board: arm labels Jul 11, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@acassis acassis merged commit 05df45d into apache:master Jul 11, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Board: arm Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants