I'm working on the linker script for libtock-rs and I'm encountering unexpected behavior by the linker. In particular, the KEEP directive doesn't seem to do anything. I could use some help identifying why my expectation doesn't match LD's behavior.
I have the following RISC-V library in asm_riscv32.s:
.section .start
.globl start
start:
auipc a0, 0
I also have an empty main.s, and the following layout_generic.ld:
MEMORY {
FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x0005FFC0
}
/*ENTRY(start)*/
SECTIONS {
.text :
{
KEEP(*(.start))
*(.text)
*(.rodata*)
*(.ARM.extab*)
} > FLASH =0xFF
/DISCARD/ :
{
*(.ARM.exidx* .eh_frame .gnu.linkonce.armexidx.*)
}
}
I use the following commands to build the library and an executable from the above sources:
riscv64-linux-gnu-as -march=rv32imc asm_riscv32.s -o riscv32.o
riscv64-linux-gnu-ar cr libriscv32.a riscv32.o
riscv64-linux-gnu-as -march=rv32imc main.s -o main.o
riscv32-unknown-elf-ld -o binary -L . -l riscv32 -T layout_generic.ld main.o
When I disassemble the resulting binary using objdump, its .text section is empty. However, if I uncomment the ENTRY(start) expression in the linker script, my start function appears.
I was under the impression that my start function should always appear in the output binary regardless of whether the linker sees it as the entry point, because I include it in a KEEP directive. It doesn't always appear, and I suspect I have a conceptual misunderstanding here. Does anyone see why my expectation doesn't match reality?
Thanks for any help,
Johnathan