-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix flash address on ARM #39
Conversation
I'm now realizing that the difference between RISC-V and ARM is because of the linker. I had I still think this is worth addressing, at least for the sake of specifying whether the header flash start points at some ELF symbol, some ELF segment in particular, or just a conceptually executable place. |
A few comments:
To me, this suggests that elf2tab should be able to process any elf regardless of the ordering of sections/headers at the beginning of flash. Looking at the elf2tab code, I believe this is correct, since the init_fn_offset field that actually needs to correspond to the entry point is found by iterating through sections. I think the fixed_address_flash address is truly just the address of the first executable section in flash |
If the flash address is defined as pointing to the first executable segment (you wrote section, but the qoute you provided says segment), then the correct solution would be to enforce the placement of this segment in the linker matching the .start symbol. I currently don't know how to do that, it seems that flash segment is considered all executable including the header with gnu ld. |
Sorry, I meant segment as you said. When I say "first executable segment" I mean "the executable segment that is at the lowest flash address", not "the executable segment that must be executed first". It is possible I am missing something here though, I am not as familiar with the operation of elf2tab as some other contributors |
I might have not been very clear about what is happening here, so I'll try to improve on the comparison. In both cases (linkers), elf2tab correctly found the first executable flash segment. The problem stems from the fact that it uses the segment address directly to calculate the entry point (by adding some offset). This exposes a difference between the linkers: one of them includes the tab header in the executable segment, the other doesn't. Because that, adding the offset to the segment start gives different results and blows up on one. I feebly tried to make gnu ld change its behaviour and to move the segment start to a later point, but got nowhere. Instead, I decided to challenge the assumption in elf2tab that the executable segment neatly corresponds to the .start section. With this patch, it looks for the .start section directly. However, this comes with another assumption that I wasn't able to verify: that the flash start address isn't actually used to copy the data to flash. If it is, then it's possible that earlier segments not containing .start might get skipped. |
Thank you for this explanation, I think I am coming closer to understanding this. One additional question: What segment is the tbf header section placed when using GNU ld? I am wondering if we should just be tweaking the logic here: https://github.com/tock/elf2tab/blob/master/src/main.rs#L288 such that whatever segment the tbf_header is ending up in is considered as a valid starting point for flash. (We might also need to adjust the logic for setting It seems that this quote from that file:
is incorrect, if GNU ld is not marking the segment containing the .tbf_header as executable |
The tbf section is placed in the executablt flash segment with GNU ld, and IIRC, it's in a non-executable segment in rust-lld. I'm not sure if the tbf header actually gets flashed together, so I can't say if the quote is correct. If the tbf header is flashed, then the quote is wrong, because that header is not marked executable (rt_header is). |
I finally got around to actually testing this on hardware and confirming it works fine with rust-lld as well. @dcz-self if you can rebase this I am happy to approve and merge it. Sorry this took so long! |
ELF files for Arm contain one executable section, which concides with FLASH in the board layout: LOAD off 0x00010000 vaddr 0x00030000 paddr 0x00030000 align 2**16 filesz 0x00000118 memsz 0x00000118 flags rwx This doesn't take into account the header size, confusing Tock when attempting to load: NRF52 HW INFO: Variant: AAC0, Part: N52840, Package: QI, Ram: K256, Flash: K1024 Error loading processes! App flash does not match requested address. Actual:0x30048, Expected:0x30000 This change finds the flash address based on the .start section instead of taking the address of the first executable segment.
Thanks for reviewing, I now rebased. |
ELF files for Arm contain one executable section,
which concides with FLASH in the board layout:
This doesn't take into account the header size, confusing Tock when attempting to load:
NRF52 HW INFO: Variant: AAC0, Part: N52840, Package: QI, Ram: K256, Flash: K1024
Error loading processes!
App flash does not match requested address. Actual:0x30048, Expected:0x30000
This change finds the flash address based on the .start section
instead of taking the address of the first executable segment.
Note that this may break if .start is not the first section. However, I don't have any better idea, given ARM's output. RISC-V has sections already aligned to .start:
However, I have no idea what causes this, or how to make the ARM target follow this too.
Note that this change is not enough to make a working executable. It seems to load, but I don't detect any signs of life in LEDs or rtt.