Search code examples
linkerriscvlinker-scripts

Why won't my linker put .rodata after .text?


I want to put my .text section at 0x80200000, but despite my every attempt, .rodata refuses to move out of my way, leaving .rodata at 0x80200000 instead:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .rodata       00000005  0000000080200000  0000000080200000  00001000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         0000002c  0000000080201006  0000000080201006  00001006  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .comment      00000093  0000000000000000  0000000000000000  00001032  2**0
                  CONTENTS, READONLY
  3 .riscv.attributes 00000047  0000000000000000  0000000000000000  000010c5  2**0
                  CONTENTS, READONLY

This is my latest linker script:

MEMORY {
  kernel_space (rwx) : ORIGIN = 0x80200000, LENGTH = 5K
  data_space (r) : ORIGIN = 0x80200002c, LENGTH = 1K
}

SECTIONS {
  .text : {
    *(.text*)
  } > kernel_space

  .rodata : {
    *(.rodata*)
  } > data_space
}

But it only led to an error. This is a snippet:

rust-lld: error: /home/cocytusdedi/Documents/Projects/Kadrix/target/riscv-unknown-kadrix/release/deps/kadrix-3a48b63578986e82.kadrix.8d3884c3841e14b8-cgu.0.rcgu.o:(function _start: .text._start+0x8): relocation R_RISCV_PCREL_HI20 out of range: 7872000 is not in [-524288, 524287]; references '.Lanon.fc0a1066aa4fa77f512f6c4b34f043aa.0'

As context, I'm using the rust-lld because I'm compiling Rust code with inline assembly, and I need to put the .text section at 0x80200000 because that's where OpenSBI on Qemu expects it to be. My reference is this blog post.


Solution

  • This worked:

    MEMORY {
      kernel_space (rwx) : ORIGIN = 0x80200000, LENGTH = 5K
    }
    
    SECTIONS {
      .text : {
        *(.text*)
      } > kernel_space
    }
    

    "Why did the previous one not work?" you ask? I don't know, all I know is I'm finally free of linker hell, and I'm happy.