link.x.in 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* # Developer notes
  2. - Symbols that start with a double underscore (__) are considered "private"
  3. - Symbols that start with a single underscore (_) are considered "semi-public"; they can be
  4. overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" {
  5. static mut _heap_size }`).
  6. - `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a
  7. symbol is not dropped if it appears in or near the front of the linker arguments and "it's not
  8. needed" by any of the preceding objects (linker arguments)
  9. - `PROVIDE` is used to provide default values that can be overridden by a user linker script
  10. - In this linker script, you may find symbols that look like `${...}` (e.g., `${ARCH_WIDTH}`).
  11. These are wildcards used by the `build.rs` script to adapt to different target particularities.
  12. Check `build.rs` for more details about these symbols.
  13. - On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and*
  14. the LMA of .data are all `${ARCH_WIDTH}`-byte aligned. These alignments are assumed by the RAM
  15. initialization routine. There's also a second benefit: `${ARCH_WIDTH}`-byte aligned boundaries
  16. means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
  17. */
  18. PROVIDE(_stext = ORIGIN(REGION_TEXT));
  19. PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
  20. PROVIDE(_max_hart_id = 0);
  21. PROVIDE(_hart_stack_size = 2K);
  22. PROVIDE(_heap_size = 0);
  23. /** EXCEPTION HANDLERS **/
  24. /* Default exception handler. The riscv-rt crate provides a weak alias of this function,
  25. which is a busy loop. Users can override this alias by defining the symbol themselves */
  26. EXTERN(ExceptionHandler);
  27. /* It is possible to define a special handler for each exception type.
  28. By default, all exceptions are handled by ExceptionHandler. However, users can
  29. override these alias by defining the symbol themselves */
  30. PROVIDE(InstructionMisaligned = ExceptionHandler);
  31. PROVIDE(InstructionFault = ExceptionHandler);
  32. PROVIDE(IllegalInstruction = ExceptionHandler);
  33. PROVIDE(Breakpoint = ExceptionHandler);
  34. PROVIDE(LoadMisaligned = ExceptionHandler);
  35. PROVIDE(LoadFault = ExceptionHandler);
  36. PROVIDE(StoreMisaligned = ExceptionHandler);
  37. PROVIDE(StoreFault = ExceptionHandler);;
  38. PROVIDE(UserEnvCall = ExceptionHandler);
  39. PROVIDE(SupervisorEnvCall = ExceptionHandler);
  40. PROVIDE(MachineEnvCall = ExceptionHandler);
  41. PROVIDE(InstructionPageFault = ExceptionHandler);
  42. PROVIDE(LoadPageFault = ExceptionHandler);
  43. PROVIDE(StorePageFault = ExceptionHandler);
  44. /** INTERRUPT HANDLERS **/
  45. /* Default interrupt handler. The riscv-rt crate provides a weak alias of this function,
  46. which is a busy loop. Users can override this alias by defining the symbol themselves */
  47. EXTERN(DefaultHandler);
  48. /* It is possible to define a special handler for each interrupt type.
  49. By default, all interrupts are handled by DefaultHandler. However, users can
  50. override these alias by defining the symbol themselves */
  51. PROVIDE(SupervisorSoft = DefaultHandler);
  52. PROVIDE(MachineSoft = DefaultHandler);
  53. PROVIDE(SupervisorTimer = DefaultHandler);
  54. PROVIDE(MachineTimer = DefaultHandler);
  55. PROVIDE(SupervisorExternal = DefaultHandler);
  56. PROVIDE(MachineExternal = DefaultHandler);
  57. SECTIONS
  58. {
  59. .text.dummy (NOLOAD) :
  60. {
  61. /* This section is intended to make _stext address work */
  62. . = ABSOLUTE(_stext);
  63. } > REGION_TEXT
  64. .text _stext :
  65. {
  66. /* Put reset handler first in .text section so it ends up as the entry */
  67. /* point of the program. */
  68. KEEP(*(.init));
  69. KEEP(*(.init.rust));
  70. . = ALIGN(4);
  71. KEEP(*(.init.trap));
  72. . = ALIGN(4);
  73. *(.trap);
  74. *(.trap.rust);
  75. *(.text.abort);
  76. *(.text .text.*);
  77. } > REGION_TEXT
  78. .rodata : ALIGN(4)
  79. {
  80. *(.srodata .srodata.*);
  81. *(.rodata .rodata.*);
  82. /* 4-byte align the end (VMA) of this section.
  83. This is required by LLD to ensure the LMA of the following .data
  84. section will have the correct alignment. */
  85. . = ALIGN(4);
  86. } > REGION_RODATA
  87. .data : ALIGN(${ARCH_WIDTH})
  88. {
  89. _sidata = LOADADDR(.data);
  90. _sdata = .;
  91. /* Must be called __global_pointer$ for linker relaxations to work. */
  92. PROVIDE(__global_pointer$ = . + 0x800);
  93. *(.sdata .sdata.* .sdata2 .sdata2.*);
  94. *(.data .data.*);
  95. . = ALIGN(${ARCH_WIDTH});
  96. _edata = .;
  97. } > REGION_DATA AT > REGION_RODATA
  98. .bss (NOLOAD) : ALIGN(${ARCH_WIDTH})
  99. {
  100. _sbss = .;
  101. *(.sbss .sbss.* .bss .bss.*);
  102. . = ALIGN(${ARCH_WIDTH});
  103. _ebss = .;
  104. } > REGION_BSS
  105. /* fictitious region that represents the memory available for the heap */
  106. .heap (NOLOAD) :
  107. {
  108. _sheap = .;
  109. . += _heap_size;
  110. . = ALIGN(4);
  111. _eheap = .;
  112. } > REGION_HEAP
  113. /* fictitious region that represents the memory available for the stack */
  114. .stack (NOLOAD) :
  115. {
  116. _estack = .;
  117. . = ABSOLUTE(_stack_start);
  118. _sstack = .;
  119. } > REGION_STACK
  120. /* fake output .got section */
  121. /* Dynamic relocations are unsupported. This section is only used to detect
  122. relocatable code in the input files and raise an error if relocatable code
  123. is found */
  124. .got (INFO) :
  125. {
  126. KEEP(*(.got .got.*));
  127. }
  128. .eh_frame (INFO) : { KEEP(*(.eh_frame)) }
  129. .eh_frame_hdr (INFO) : { *(.eh_frame_hdr) }
  130. }
  131. /* Do not exceed this mark in the error messages above | */
  132. ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
  133. ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
  134. ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
  135. ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
  136. ASSERT(ORIGIN(REGION_DATA) % ${ARCH_WIDTH} == 0, "
  137. ERROR(riscv-rt): the start of the REGION_DATA must be ${ARCH_WIDTH}-byte aligned");
  138. ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
  139. ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
  140. ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
  141. ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
  142. ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
  143. ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
  144. ASSERT(_stext % 4 == 0, "
  145. ERROR(riscv-rt): `_stext` must be 4-byte aligned");
  146. ASSERT(_sdata % ${ARCH_WIDTH} == 0 && _edata % ${ARCH_WIDTH} == 0, "
  147. BUG(riscv-rt): .data is not ${ARCH_WIDTH}-byte aligned");
  148. ASSERT(_sidata % ${ARCH_WIDTH} == 0, "
  149. BUG(riscv-rt): the LMA of .data is not ${ARCH_WIDTH}-byte aligned");
  150. ASSERT(_sbss % ${ARCH_WIDTH} == 0 && _ebss % ${ARCH_WIDTH} == 0, "
  151. BUG(riscv-rt): .bss is not ${ARCH_WIDTH}-byte aligned");
  152. ASSERT(_sheap % 4 == 0, "
  153. BUG(riscv-rt): start of .heap is not 4-byte aligned");
  154. ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
  155. ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
  156. Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
  157. ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
  158. ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
  159. Consider changing `_max_hart_id` or `_hart_stack_size`.");
  160. ASSERT(SIZEOF(.got) == 0, "
  161. .got section detected in the input files. Dynamic relocations are not
  162. supported. If you are linking to C code compiled using the `gcc` crate
  163. then modify your build script to compile the C code _without_ the
  164. -fPIC flag. See the documentation of the `gcc::Config.fpic` method for
  165. details.");
  166. /* Do not exceed this mark in the error messages above | */