Where to find the risc-v default linker script?

I installed the risc-v toolchain on my Mac mini. I wrote a simple assembly code & assembled my asm file (riscv64-unknown-elf-as -march=rv32imac -mno-arch-attr asm.S -o asm.o)

I see the .o file created properly. Now is there any default linker file that I can pick and edit?

Found sample scripts here: freedom-e-sdk/bsp/sifive-hifive1-revb at master · sifive/freedom-e-sdk · GitHub

Good links you found. Might also like a few notes I put together on the same subject:
Demystifying OpenOCD … and the smallest toolchain in the world
Have a look at the sample .mk mske file and associated .lds linker scripts (for target memory layout),

The ld program puts all the relocatable object files together into a single .elf file format.

$(RISCVGNU)-ld start.o foo.o bar.o baz.o ... -T fe310-g002-rom.lds -o my-prog.elf -Map my-prog.map -b elf32-littleriscv

where RISCVGNU is either
RISCVGNU ?= riscv32-unknown-elf
or, lately,
RISCVGNU ?= riscv64-unknown-elf
which in case of the latter requires linker option -b elf32-littleriscv

Optionally, you can make a program listing of exactly what is being put where, and why.

$(RISCVGNU)-objdump -D my-prog.elf > my-prog.lst

Optionally, you can convert the .elf file format to Intel hex;

$(RISCVGNU)-objcopy my-prog.elf -O ihex my-prog.hex

or, optionally, you can convert the .elf file format to binary. The choice (elf, hex, bin) is up to which loader program you will use.

$(RISCVGNU)-objcopy my-prog.elf -O binary my-prog.bin

Which loader program and hardware interface connection do you use? If OpenOCD with jtag, you may also find my suggestions in the .cfg file very helpful.

First, thank you very much. your response saved a lot of time. I borrowed your linkerscript fe310-ram.lds and generated a very basic elf to test if toolchain, openocd, gdb all works fine with my hifive1-revb board.
my entry.s file

.section .text
.global main

addi t0, a0, 100; # loop counter t0 = 100

beq t0, x0, loop_end; # exit loop if counter expires
addi t0, t0, -1; # decrement counter
j loop_start;
addi t1, x0, 0; # dummy instruction

I generated elf with your ram ld file and got the elf as below:

$riscv64-unknown-elf-objdump -D entry.elf

entry.elf: file format elf32-littleriscv

Disassembly of section .text:

80000000 :
80000000: 06450293 addi t0,a0,100

80000004 <loop_start>:
80000004: 00028463 beqz t0,8000000c <loop_end>
80000008: 12fd addi t0,t0,-1
8000000a: bfed j 80000004 <loop_start>

8000000c <loop_end>:
8000000c: 4301 li t1,0

Now, I am just planning to load this directly in RAM (0x80000000) and see if I can keep a breakpoint in main using gdb and step-in. Do think find anything fatal that might permanently damage my board? it should n’t, but I am new to risc-v hence seek experts opinion. I dont have any startup code (no interrupt mapping, but this loop code dont need anything).

I ask as I am bit paranoid as I have just one board :slight_smile:

Most welcome @bsvtgc Vincent, glad it helps. Great little code example and disassembly you’ve tested. Sure, nothing bad will happen, especially if it only loads to ram – power off, reset, or unplug and it’s back to “normal”. I do this all the time.

After, or in place of your “dummy” instruction, you might want to put a forever loop with

j . ;# or, jal x0, .

so that the core stops in its tracks and doesn’t try to execute unknown code at unknown places.

I’ve never had a HiFive board, and have never used the Freedom GUI toolchain package, so I am not much the expert there but am confident nothing bad will happen. I have and use the LoFive board; and for debugger interfaces both the Raspberry Pi (bitbang jtag) and the FTDI FT(2)232H chip (Olimex, etc).

You might wish to revise your openocd “.cfg” file with some of my suggestions. The HiFive has a built-in J-Link USB device, so only “interface” (or, lately, called “adapter”) section is probably different.

As long as you use load_image and not flash write_image (or equiv. flash submodules) then you’ll be fine and not touch the rom chip contents.

Let me repeat this critical point: For ram-only work, comment out, or remove, any and all lines beginning with “flash”, such as

# flash bank ...
# flash protect ...
# flash erase ...
# flash write_image ...

or even the helper script, if it exists in your .cfg,

# program ...

A handy openocd reference is OpenOCD Command Reference in case you’re interested.

I have encapsulated all necessary steps into a single [tcl] procedure, asic_ram_load, which you would invoke like so:

openocd -f fe310-g002.cfg -c "adapter speed 2000" -c init -c "asic_ram_load my_prog" -c shutdown -c exit

where my_prog is whatever is the name of your binary file. Change lines 150 and 151 if you don’t put the “-ram” suffix on your filename, or use another format beside “bin”.

I am not sure how the jlink chip on the HiFive board (schematic, sheet 4, U3-64, PTD7) handles reset; thus, you might only want to take my high level procedures in the “APPLICATIONS” section at the bottom. Further work to check and revise lines 78-81 whether jlink uses trst, srst, or some other hardware signal. For now, keeping all the command handlers as-is, un-overridden, gives benefit of doubt.

You might like to keep hardware interface specific stuff (such as the adapter driver jlink statement; see tips on HiFive connection for suggestions) in another config file. If so, you would invoke like so:

openocd -f hifive-rev-b.cfg -f fe310-g002.cfg ...

Just make sure that the first .cfg file doesn’t have any init statement; it should be put in only at the right sequence, such as at the command line:

  1. hardware-specific-interface-stuff
  2. target-specific-stuff
  3. speed
  4. init
  5. high-level-application-command
  6. shutdown
  7. exit
    For interactive gdb sessions, omit 6 and 7.

@pds when I tried with your “openocd config and command”

openocd -f demo.cfg -c “adapter speed 2000” -c init -c “asic_ram_load my_prog” -c shutdown -c exit

with hifive1-revb board connected, it threw up the following error.

Error: Debug adapter doesn’t support any transports?
**demo.cfg:22: Error: **
in procedure 'script’

However, when I took another config file from GitHub and slightly modified based on your inputs (removed anything related with flash) it came to the following:

adapter speed 4000
adapter driver jlink
transport select jtag
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000913


target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 0x4000 -work-area-backup 0

riscv set_enable_virt2phys off
riscv set_enable_virtual off
jlink jtag 3


with openocd & gdb up, I found a bug on first line of my code :slight_smile:
addi t0, a0, 100; # loop counter t0 = 100 => addi t0, x0, 100;

I really appreciate your help with all the details you put in your message. Thanks !!

I really like the way your openocd config is written, clean and customizable. But I am not an expert on openocd. do you think the transport protocol should be mentioned somewhere in .cfg file or through command to be used for hifive1-revb board. I read hifive1-revb is quite different from hifive1.