1/* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright © 2020 Keith Packard 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * 3. Neither the name of the copyright holder nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 * OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35__flash = 0x00000000; 36__flash_size = 0x00400000; 37__ram = 0x20000000; 38__ram_size = 0x00004000; 39__stack_size = 2k; 40 41ENTRY(_start) 42 43/* 44 * These values should be provided by the application. We'll include 45 * some phony values here to make things link for testing 46 */ 47 48MEMORY 49{ 50 flash (rxai!w) : ORIGIN = DEFINED(__flash) ? __flash : 0x10000000, LENGTH = DEFINED(__flash_size) ? __flash_size : 0x10000 51 ram (wxa!ri) : ORIGIN = DEFINED(__ram ) ? __ram : 0x20000000, LENGTH = DEFINED(__ram_size ) ? __ram_size : 0x08000 52} 53 54PHDRS 55{ 56 text PT_LOAD; 57 ram PT_LOAD; 58 ram_init PT_LOAD; 59 tls PT_TLS; 60} 61 62SECTIONS 63{ 64 PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram)); 65 66 .init : { 67 KEEP (*(.text.init.enter)) 68 KEEP (*(.data.init.enter)) 69 KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) 70 } >flash AT>flash :text 71 72 .text : { 73 74 /* code */ 75 *(.text.unlikely .text.unlikely.*) 76 *(.text.startup .text.startup.*) 77 *(.text .text.*) 78 *(.gnu.linkonce.t.*) 79 KEEP (*(.fini .fini.*)) 80 __text_end = .; 81 82 PROVIDE (__etext = __text_end); 83 PROVIDE (_etext = __text_end); 84 PROVIDE (etext = __text_end); 85 86 /* read-only data */ 87 *(.rdata) 88 *(.rodata .rodata.*) 89 *(.gnu.linkonce.r.*) 90 91 *(.srodata.cst16) 92 *(.srodata.cst8) 93 *(.srodata.cst4) 94 *(.srodata.cst2) 95 *(.srodata .srodata.*) 96 *(.data.rel.ro .data.rel.ro.*) 97 *(.got .got.*) 98 99 /* Need to pre-align so that the symbols come after padding */ 100 . = ALIGN(8); 101 102 /* lists of constructors and destructors */ 103 PROVIDE_HIDDEN ( __preinit_array_start = . ); 104 KEEP (*(.preinit_array)) 105 PROVIDE_HIDDEN ( __preinit_array_end = . ); 106 107 PROVIDE_HIDDEN ( __init_array_start = . ); 108 KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 109 KEEP (*(.init_array .ctors)) 110 PROVIDE_HIDDEN ( __init_array_end = . ); 111 112 PROVIDE_HIDDEN ( __fini_array_start = . ); 113 KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 114 KEEP (*(.fini_array .dtors)) 115 PROVIDE_HIDDEN ( __fini_array_end = . ); 116 } >flash AT>flash :text 117 118 /* 119 * Data values which are preserved across reset 120 */ 121 .preserve (NOLOAD) : { 122 PROVIDE(__preserve_start__ = .); 123 KEEP(*(SORT_BY_NAME(.preserve.*))) 124 KEEP(*(.preserve)) 125 PROVIDE(__preserve_end__ = .); 126 } >ram AT>ram :ram 127 128 .data : ALIGN_WITH_INPUT { 129 *(.data .data.*) 130 *(.gnu.linkonce.d.*) 131 132 /* Need to pre-align so that the symbols come after padding */ 133 . = ALIGN(8); 134 135 PROVIDE( __global_pointer$ = . + 0x800 ); 136 *(.sdata .sdata.* .sdata2.*) 137 *(.gnu.linkonce.s.*) 138 } >ram AT>flash :ram_init 139 PROVIDE(__data_start = ADDR(.data)); 140 PROVIDE(__data_source = LOADADDR(.data)); 141 142 /* Thread local initialized data. This gets 143 * space allocated as it is expected to be placed 144 * in ram to be used as a template for TLS data blocks 145 * allocated at runtime. We're slightly abusing that 146 * by placing the data in flash where it will be copied 147 * into the allocate ram addresses by the existing 148 * data initialization code in crt0 149 */ 150 .tdata : ALIGN_WITH_INPUT { 151 *(.tdata .tdata.* .gnu.linkonce.td.*) 152 PROVIDE(__data_end = .); 153 PROVIDE(__tdata_end = .); 154 } >ram AT>flash :tls :ram_init 155 PROVIDE( __tls_base = ADDR(.tdata)); 156 PROVIDE( __tdata_start = ADDR(.tdata)); 157 PROVIDE( __tdata_source = LOADADDR(.tdata) ); 158 PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); 159 PROVIDE( __data_source_end = __tdata_source_end ); 160 PROVIDE( __tdata_size = SIZEOF(.tdata) ); 161 162 PROVIDE( __edata = __data_end ); 163 PROVIDE( _edata = __data_end ); 164 PROVIDE( edata = __data_end ); 165 PROVIDE( __data_size = __data_end - __data_start ); 166 PROVIDE( __data_source_size = __data_source_end - __data_source ); 167 168 .tbss (NOLOAD) : { 169 *(.tbss .tbss.* .gnu.linkonce.tb.*) 170 *(.tcommon) 171 PROVIDE( __tls_end = . ); 172 PROVIDE( __tbss_end = . ); 173 } >ram AT>ram :tls :ram 174 PROVIDE( __bss_start = ADDR(.tbss)); 175 PROVIDE( __tbss_start = ADDR(.tbss)); 176 PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); 177 PROVIDE( __tbss_size = SIZEOF(.tbss) ); 178 PROVIDE( __tls_size = __tls_end - __tls_base ); 179 PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); 180 PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); 181 PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); 182 183 /* 184 * The linker special cases .tbss segments which are 185 * identified as segments which are not loaded and are 186 * thread_local. 187 * 188 * For these segments, the linker does not advance 'dot' 189 * across them. We actually need memory allocated for tbss, 190 * so we create a special segment here just to make room 191 */ 192 .tbss_space (NOLOAD) : { 193 . = ADDR(.tbss); 194 . = . + SIZEOF(.tbss); 195 } >ram AT>ram :ram 196 197 .bss (NOLOAD) : { 198 *(.sbss*) 199 *(.gnu.linkonce.sb.*) 200 *(.bss .bss.*) 201 *(.gnu.linkonce.b.*) 202 *(COMMON) 203 204 /* Align the heap */ 205 . = ALIGN(8); 206 __bss_end = .; 207 } >ram AT>ram :ram 208 PROVIDE( __non_tls_bss_start = ADDR(.bss) ); 209 PROVIDE( __end = __bss_end ); 210 PROVIDE( _end = __bss_end ); 211 PROVIDE( end = __bss_end ); 212 PROVIDE( __bss_size = __bss_end - __bss_start ); 213 214 /* Make the rest of memory available for heap storage */ 215 PROVIDE (__heap_start = __end); 216 PROVIDE (__heap_end = __stack - (DEFINED(__stack_size) ? __stack_size : 0x800)); 217 PROVIDE (__heap_size = __heap_end - __heap_start); 218 219 /* Define a stack region to make sure it fits in memory */ 220 .stack (NOLOAD) : { 221 . += (DEFINED(__stack_size) ? __stack_size : 0x800); 222 } >ram :ram 223 224 /* Throw away C++ exception handling information */ 225 226 /DISCARD/ : { 227 *(.note .note.*) 228 *(.eh_frame .eh_frame.*) 229 *(.ARM.extab* .gnu.linkonce.armextab.*) 230 *(.ARM.exidx*) 231 } 232} 233/* 234 * Check that sections that are copied from flash to RAM have matching 235 * padding, so that a single memcpy() of __data_size copies the correct bytes. 236 */ 237ASSERT( __data_size == __data_source_size, 238 "ERROR: .data/.tdata flash size does not match RAM size"); 239