Linker script understanding: KEEP doesn't do what I expect

8 views
Skip to first unread message

Johnathan Van Why

unread,
Jan 6, 2021, 9:00:21 PM1/6/21
to Tock Embedded OS Development Discussion
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
Reply all
Reply to author
Forward
0 new messages