rp2: Link with nano.specs, add linker cref table#19299
Conversation
Useful to see why particular symbols have been pulled in. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Reduces binary, static RAM, and (probably) runtime memory usage. Signed-off-by: Angus Gratton <angus@redyak.com.au>
|
Code size report: |
|
Thanks for doing this. I like the idea, and on RPI_PICO_W it saves 1624 bytes of flash and 960 bytes of RAM. But... the
I guess that's the cause of the crashes? I tried adding I'd be interested to know exactly what mbedTLS is pulling in from libc that doesn't work with newlib-nano... it's a bit scary that we don't fully understand the dependencies here, especially since ports like stm32 work just fine with @Gadgetoid I'm surprised you didn't see failures with your firmware when using |
Oh wow, sorry! I didn't realise those tests weren't part of the default run-tests.py coverage! I wonder if it's to do with linker placement instead of the actual features, there might be something that's now reading from cached flash. I'll do a bit of spelunking and try to figure this out. |
You mentioned you ran the tests on RPI_PICO2, which won't be able to run the network tests anyway. Eventually octoprobe will help here, by just running all tests regardless. But also probably we should think about merging #16112; I use it all the time now (and is how I tested this PR). |
Summary
Passes
--specs=nano.specson the linker command line for rp2, meaning newlib-nano is used instead of regular newlib. As mentioned by @Gadgetoid in #11143. This reduces both the binary size and (significantly) the static RAM usage. Should also save some RAM at runtime, particularly the stack footprint of libc printf.Includes a commit to add the
--creflinker argument, which adds a cross-reference table in the linker map file. This is useful to figure out how/why certain symbols are linked.The specific libc pieces which are linked in the default rp2 build seem to be malloc/free/realloc and some printf support.
pico_utilqueue.c and time.c, and operator new & delete (unclear why these are pulled in at all!) Can find via__wrap_freein the cross-reference table. This feels like with a small amount of work it could be removed, maybe...? Particularly as the default rp2 build has no C heap available.shared/readline, andshared/netutils. Can find via__wrap_snprintfin the cross-reference table. This feels like it'd be harder to remove the dependency for.I don't think any of these use cases require "full" newlib support.
The best description I know for gcc specs and nano vs normal newlib is https://metebalci.com/blog/demystifying-arm-gnu-toolchain-specs-nano-and-nosys/
Testing
Trade-offs and Alternatives
Generative AI
I did not use generative AI tools when creating this PR.