pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

elf2uf2 incorrectly detects binaries using LMAs

Open silversquirl opened this issue 3 years ago • 6 comments

When trying to convert a binary, I got this strange error:

ERROR: Memory segment 10000000->10000100 is outside of valid address range for device

Running with -v outputs Detected RAM binary, despite my binary storing all sections in flash.

I'm using LMAs in my linker script to indicate that sections are stored in flash, but copied to sram before execution. It seems like elf2uf2 incorrectly detects this as being a RAM binary, since the entry address points to SRAM.

silversquirl avatar Dec 28 '21 03:12 silversquirl

It is the executing programs' job to copy any code/data from flash to RAM at startup (otherwise you couldn't run from a binary already stored in flash). This is why elf2uf2 chooses the binary type based on where the entry point is. If the entry point is in RAM, then the binary can't be run from flash on boot.

kilograham avatar Dec 28 '21 14:12 kilograham

The bootrom copies the boot stage2 from flash to ram. The boot stage2 copies the rest of the code from flash to ram. Where exactly should my entrypoint be?

silversquirl avatar Dec 28 '21 17:12 silversquirl

boot stage2 does not copy the rest of the code to RAM, it sets up flash for XIP and then juimps to the entry point in flash. in the SDK this is _entry_point in crt0.S (which then copies .data segment into RAM). With the SDK you can use a copy_to_ram binary (pico_set_binary_type(TARGET copy_to_ram)) which uses a similar LMA based linker script, and almost everything is copied to RAM, and main is entered there.

If you are doing your own thing, it remains your own responsibility to do the copy after the boot stage 2 enters your binary (at the address in the vector table). alternatively you could make your own bootstage2 that did the copy.

Note this is not magic, the ELF has the physical/virtual mappings but that is lost in the (flash) binary unless you maintain it somewhere yourself.

kilograham avatar Dec 29 '21 14:12 kilograham

My boot stage2 does the copy. This means my entrypoint is not running off flash through XIP, so it really should have an LMA. Because elf2uf2 doesn't handle this case, I have to resort to this hack:

ENTRY(_start_lma)
_start_lma = _start - ADDR(.text) + LOADADDR(.text);

Maybe there's something I'm missing that lets me do this cleanly, but it seems to me like elf2uf2 should do detection based on the LMA of the entrypoint, not the VMA.

silversquirl avatar Dec 30 '21 02:12 silversquirl

ok, yeah this is not a scenario we'd considered (until i mentioned it above, and indeed that is what you are doing). If it doesn't break the myriad of other supported scenarios, then we can make the change

kilograham avatar Dec 30 '21 02:12 kilograham

This was a bit confusing to think about, but I agree that we should always detect binary type based on the LMA of the entry point.

We hadn't encountered this case before because the VMA and LMA of the entry point are usually equivalent, since we assume we run without a loader (and use VMA/LMA really to refer to the dst/src of initialised RAM sections loaded by crt0)

We have something similar to your boot2-loader with PICO_COPY_TO_RAM, where crt0 runs from flash, but everything else (by default) is loaded to SRAM by crt0.

Wren6991 avatar Apr 29 '22 19:04 Wren6991

can you please attach an ELF with the problem

kilograham avatar Jan 20 '23 21:01 kilograham

merged into develop

kilograham avatar Jan 27 '23 14:01 kilograham