hifive1 icon indicating copy to clipboard operation
hifive1 copied to clipboard

Modify the Linker Script

Open dkhayes117 opened this issue 4 years ago • 21 comments

Is it possible to modify the linker script on my project? I want to keep all machine mode and user mode functions separated in memory. I thought that I might can build the machine code and the user code separately, then change the linker script somehow to load them into separate memory locations. Then I can use the PMP to sandbox my user mode operation.

dkhayes117 avatar Sep 23 '20 02:09 dkhayes117

Definitely! You can copy the linker script from the corresponding riscv-rt source tree into your project under a different name and use it in .cargo/config instead of one provided by riscv-rt.

Disasm avatar Sep 23 '20 09:09 Disasm

So this line "-C", "link-arg=-Thifive1-link.x" would change to "-C", "link-arg=-newlink.x" if newlink.x was in my project tree ?

dkhayes117 avatar Sep 23 '20 13:09 dkhayes117

Change it to:

"-C", "link-arg=-Thifive1-memory.x",
"-C", "link-arg=-Tnewlink.x"

(you also need to include memory definitions before the linker script)

Disasm avatar Sep 23 '20 13:09 Disasm

Will I need to modify the memory-hifive1-revb.x too, or just the linker?

dkhayes117 avatar Sep 23 '20 14:09 dkhayes117

Only if you need a different memory layout or you do not have a bootloader.

Disasm avatar Sep 23 '20 14:09 Disasm

Are the region alias' sensitive to renaming? For example, keeping U and M level code separate wouldn't I need to have a .textM and a .textU etc?

Maybe I can build and run my M level code with one linker and memory file (original). Then once completed, build and run the U level code with a modified linker and memory file that has different memory addresses. Or should this be a single process with some kind of compile time flags/switches?

dkhayes117 avatar Sep 23 '20 14:09 dkhayes117

Region aliases are different things, they were added to prevent hardcoding FLASH everywhere and to allow some flexibility. If you have different .textX section names, you can try to group them in the linker script in a way you want.

Disasm avatar Sep 23 '20 14:09 Disasm

I've never done this before, obviously. How completely nuts does this look?

INCLUDE memory-fe310.x MEMORY { MFLASH ORIGIN = 0x20000000, LENGTH = 2M UFLASH ORIGIN = 0x20200000, LENGTH = 2M MRAM ORIGIN = 0x80000000, LENGTH = 8K URAM ORIGIN = 0x80002000, LENGTH = 8K }

REGION_ALIAS("REGION_MTEXT", MFLASH); REGION_ALIAS("REGION_MRODATA", MFLASH); REGION_ALIAS("REGION_MDATA", MRAM); REGION_ALIAS("REGION_MBSS", MRAM); REGION_ALIAS("REGION_MHEAP", MRAM); REGION_ALIAS("REGION_MSTACK", MRAM);

REGION_ALIAS("REGION_UTEXT", UFLASH); REGION_ALIAS("REGION_URODATA", UFLASH); REGION_ALIAS("REGION_UDATA", URAM); REGION_ALIAS("REGION_UBSS", URAM); REGION_ALIAS("REGION_UHEAP", URAM); REGION_ALIAS("REGION_USTACK", URAM);

/Skip first 64k allocated for bootloader/ _stext = 0x20010000;

dkhayes117 avatar Sep 23 '20 14:09 dkhayes117

You don't need the first INCLUDE as you defined your own RAM regions, but other things look sane

Disasm avatar Sep 23 '20 14:09 Disasm

Wow, really? LOL, cool. Obviously, I can tweak the region sizes a bit to not waste space, just divided everything in half to start. I will get rid of the include line.

Next, I need to modify the link.x file to handle these regions, correct?

dkhayes117 avatar Sep 23 '20 15:09 dkhayes117

Correct. Or you can create two different memory.x files, one for M-mode and one for U-mode and use them to link two different binaries with the same (possibly modified) link.x file.

Disasm avatar Sep 23 '20 15:09 Disasm

Right, that makes sense. If I did that, then I wouldn't need the change the region names just the memory boundaries. I would also have to $cargo run twice this way. Once to load m-mode stuff, and once to load the u-mode stuff?

dkhayes117 avatar Sep 23 '20 15:09 dkhayes117

Yes, you're right.

Disasm avatar Sep 23 '20 15:09 Disasm

I really appreciate your help!

dkhayes117 avatar Sep 23 '20 15:09 dkhayes117

One more thought. I plan on entering the user mode memory section by setting the stack pointer address and changing to u mode. When I write my user mode code, I don't need an #[entry] attribute point included, just in the machine mode code. That should allow the machine code to be called on start up, then I will use the mret process to move into the user mode portion from m-mode. Should that work?

dkhayes117 avatar Sep 23 '20 18:09 dkhayes117

Probably you need to write your own startup code for the user mode and place it somewhere (beginning of the user mode .text as an option). In any case, you need to have something, that will be KEEPed while linking, otherwise you likely end up with an empty user mode binary.

Disasm avatar Sep 23 '20 22:09 Disasm

I see what you are saying. Do you have any suggestions for the memory definition file. When I try to build with the extra -C argument, it says that "RAM" is already defined. The ram is being defined somewhere else during linking. I think it might be in the hifive/build.rs file. It seems to be pointing to the default memory file. Not sure how to modify this without changing the repo file.

dkhayes117 avatar Sep 23 '20 23:09 dkhayes117

Nope, the problem is the quickstart template is adding the -Thifive1-link.x argument which calls the hifive-memory.x file then link.x linker. I think I can just do this "-C", "link-arg=-Tnew-memory.x", "-C", "link-arg=-Tlink.x"

dkhayes117 avatar Sep 24 '20 19:09 dkhayes117

This seems to be working, but the ram doesn't start at the origin I define, it always puts it at 0x80000000.

dkhayes117 avatar Sep 25 '20 02:09 dkhayes117

Strange, try to rebuild the project. Sometimes these script files don't get updated and linker uses the old version.

Disasm avatar Sep 25 '20 10:09 Disasm

Yahoo! That worked. I ran cargo clean then cargo build --workspace

dkhayes117 avatar Sep 25 '20 16:09 dkhayes117