Closed rhulme closed 2 years ago
I've noticed this as well. Haven't looked at what causes the problem (linker or elf2uf2), but everything seems fine as long as 64k aligned offsets are used:
FLASH(rx) : ORIGIN = 0x10000000 + 64k, LENGTH = 2048k - 64k
FLASH(rx) : ORIGIN = 0x10000000 + 128k, LENGTH = 2048k - 128k
...
Still not entirely sure whether this is a problem with the program headers in the ELF image (although I tend to think it is) but I found this page: https://stackoverflow.com/questions/33005638/how-to-change-alignment-of-code-segment-in-elf
The alignment (as seen in the output from objdump) is set to 64k (2^16). Why the offset within the ELF image needs to be the same as the alignment on the target, I'm not sure but using the suggestion of
-Wl,-z,max-page-size=4096
as additional linker flags seems to produce a better looking ELF image:
Program Header: LOAD off 0x00001000 vaddr 0x10001000 paddr 0x10001000 align 2**12 filesz 0x00009914 memsz 0x00009914 flags rwx LOAD off 0x0000b0c0 vaddr 0x200000c0 paddr 0x1000a914 align 2**12 filesz 0x00000dc4 memsz 0x00000dc4 flags rwx LOAD off 0x00000e88 vaddr 0x20000e88 paddr 0x20000e88 align 2**12 filesz 0x00000000 memsz 0x000012d0 flags rw-
Would make sense for the SDK to set that as a default?
Why the offset within the ELF image needs to be the same as the alignment on the target, I'm not sure
Using the picotool program, you can flash ELF, BIN or UF2 files to the RP2040, so in that case I guess it makes sense for the alignment in the ELF to match the alignment of the target? (unless I've misunderstood your question)
I guess it makes sense for the alignment in the ELF to match the alignment of the target? (unless I've misunderstood your question)
That's possible, although probably more in the context of meatier systems that want to be able to mmap the image into the address space rather than a tool that's trying to extract the raw binary payload, which can then be stored in flash.
Even so, with a 64k alignment, I would have expected ld to pad to 64k (as it normally does), then pad to whatever the start address was (4k in this case) and then write the payload rather than cause the ELF header to be included in the theoretical payload. I suppose that's more of a philosophical question.
Either way, in the context of the Pico, a 64k alignment means unnecessarily wasting a stupid amount of space to be able to have a flashloader that isn't going to be clobbered and made unbootable by someone writing the application file using picotool or the bootrom (in the case that the flashloader is ok but the main application isn't).
-Wl,-z,max-page-size=4096
Would make sense for the SDK to set that as a default?
I think this is probably reasonable. I assume other than this issue it also makes the ELF file smaller on disk, but not much else. I guess LD is thinking about targets which physically map the ELF file into RAM, so it figures if you start in the middle of a page it should pad the page with zeroes.
elf2uf2 is pretty much doing the right thing based on what it sees (this part of the ELF file is mapped into this part of memory) - so i'd probably not try to "fix" that.
I'd be curious to see what this does to the BIN/HEX files though
I'd be curious to see what this does to the BIN/HEX files though
With my program it makes no difference whatsoever, which is what I would normally expect. The setting isn't altering the alignment of sections (as far as I can tell), more how the blocks within the ELF image are aligned.
I don't quite know why the data (actually the code) referred to in the first program header is forced to be aligned on a 64k boundary within the file but the second one (which is effectively the .data segment) is not (see my original post - the second block is at offset 0x000100c0 in the image but the memory alignment is still 64k).
When objdump is used to extract the binary data, whatever it's doing is obviously more involved than just reading the program headers.
merged into develop
Following the suggestion in #545 I have been working on a small flashloader. I copied memmap_default.ld to my project, moved the start address of my main application to start 4k later:
FLASH(rx) : ORIGIN = 0x10000000 + 4k, LENGTH = 2048k - 4k
and used
pico_set_linker_script
to force that script to be used.The generated UF2 file still starts a 0x10000000 and on closer inspection contains the first raw 4k of the ELF file.
Looking at the ELF file, the first program header apparently starts at offset 0 in the file (also with the "wrong" address in memory), which is what elf2uf2 is parsing:
The file offset of the sections is correct:
Normally, the first program header starts at offset 0x10000:
I'm not yet clued up enough to know whether elf2uf2 needs to be more sophisticated or there has been an issue with the generation of the elf file itself but something is not right.