-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlink.x.in
284 lines (240 loc) · 9.44 KB
/
link.x.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* Provides information about the memory layout of the device */
/* This will be provided by the user (see `memory.x`) or by a Board Support Crate */
INCLUDE memory.x
/* # Entry point = reset vector */
ENTRY(Reset);
EXTERN(__RESET_VECTOR); /* depends on the `Reset` symbol */
/* # Exception vectors */
/* This is effectively weak aliasing at the linker level */
/* The user can override any of these aliases by defining the corresponding symbol themselves (cf.
the `exception!` macro) */
EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */
EXTERN(DefaultHandler);
PROVIDE(NonMaskableInt = DefaultHandler);
EXTERN(HardFaultTrampoline);
PROVIDE(MemoryManagement = DefaultHandler);
PROVIDE(BusFault = DefaultHandler);
PROVIDE(UsageFault = DefaultHandler);
PROVIDE(SecureFault = DefaultHandler);
PROVIDE(SVCall = DefaultHandler);
PROVIDE(DebugMonitor = DefaultHandler);
PROVIDE(PendSV = DefaultHandler);
PROVIDE(SysTick = DefaultHandler);
PROVIDE(DefaultHandler = DefaultHandler_);
PROVIDE(HardFault = HardFault_);
/* # Interrupt vectors */
EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */
/* # Pre-initialization function */
/* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function,
then the function this points to will be called before the RAM is initialized. */
PROVIDE(__pre_init = DefaultPreInit);
/* # Sections */
SECTIONS
{
PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
/* ## Sections in FLASH */
/* ### Vector table */
.vector_table ORIGIN(FLASH) :
{
__start_vector = .;
/* Initial Stack Pointer (SP) value */
LONG(_stack_start);
/* Reset vector */
KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */
__reset_vector = .;
/* Exceptions */
KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */
__eexceptions = .;
/* Device specific interrupts */
KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */
} > FLASH
__vector_size = SIZEOF(.vector_table);
/* Header containing data needed by the bootloader. We specify
_HUBRIS_IMAGE_HEADER_SIZE and _HUBRIS_IMAGE_HEADER_ALIGN in memory.x at
build time, then reserve enough space for the header here in the linker
script.
*/
.header :
{
ASSERT(. == ALIGN(_HUBRIS_IMAGE_HEADER_ALIGN), "error: header alignment is invalid");
HEADER = .;
. = . + _HUBRIS_IMAGE_HEADER_SIZE;
} > FLASH
/* Explicitly place text at vector table + size of header, deliberately ignoring
section alignment. This is important because the bootloader assumes that the header
immediately follows the vector table; if something changes to cause that to not
be true, this expression will cause the text and header sections to overlap, causing
a difficult to understand linker failure, which will hopefully be somewhat improved
by this comment.
*/
PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table) + SIZEOF(.header));
/* ### .text */
.text _stext :
{
__stext = .;
/* place these 2 close to each other or the `b` instruction will fail to link */
*(.PreResetTrampoline);
*(.Reset);
*(.text .text.*);
/* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`,
so must be placed close to it. */
*(.HardFaultTrampoline);
*(.HardFault.*);
. = ALIGN(4);
__etext = .;
} > FLASH
/* ### .rodata */
.rodata __etext : ALIGN(4)
{
__srodata = .;
*(.rodata .rodata.*);
/* We move this into a special section so we can ensure it is always
included in the build */
KEEP(*(.hubris_id));
/* 4-byte align the end (VMA) of this section.
This is required by LLD to ensure the LMA of the following .data
section will have the correct alignment. */
. = ALIGN(4);
__erodata = .;
} > FLASH
/* ## Sections in RAM */
/* ### .data */
.data : ALIGN(4)
{
. = ALIGN(4);
__sdata = .;
*(.data .data.*);
. = ALIGN(4); /* 4-byte align the end (VMA) of this section */
} > RAM AT>FLASH
/* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to
* use the .data loading mechanism by pushing __edata. Note: do not change
* output region or load region in those user sections! */
. = ALIGN(4);
__edata = .;
/* LMA of .data */
__sidata = LOADADDR(.data);
/* ### .gnu.sgstubs
This section contains the TrustZone-M veneers put there by the Arm GNU linker. */
/* Security Attribution Unit blocks must be 32 bytes aligned. */
/* Note that this pads the FLASH usage to 32 byte alignment. */
.gnu.sgstubs : {
. = ALIGN(32);
__veneer_base = .;
*(.gnu.sgstubs*)
. = ALIGN(32);
__veneer_limit = .;
} > FLASH
/*
* Add a 256 byte caboose region: 4 for the caboose marker, 4 for the
* caboose size and the other 248 bytes for caboosey things
*/
.caboose : ALIGN(4) {
LONG(0xcab0005e);
. += 248;
LONG(256);
} > FLASH =0xffffffff
/* ### .bss */
.bss (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__sbss = .;
*(.bss .bss.*);
*(COMMON); /* Uninitialized C statics */
. = ALIGN(4); /* 4-byte align the end (VMA) of this section */
} > RAM
/* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to
* use the .bss zeroing mechanism by pushing __ebss. Note: do not change
* output region or load region in those user sections! */
. = ALIGN(4);
__ebss = .;
/* ### .uninit */
.uninit (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__suninit = .;
*(.uninit .uninit.*);
. = ALIGN(4);
__euninit = .;
} > RAM
/* Place the heap right after `.uninit` in RAM */
PROVIDE(__sheap = __euninit);
/* ## .got */
/* Dynamic relocations are unsupported. This section is only used to detect relocatable code in
the input files and raise an error if relocatable code is found */
.got (NOLOAD) :
{
KEEP(*(.got .got.*));
}
/* ## Discarded sections */
/DISCARD/ :
{
/* Unused exception related info that only wastes space */
*(.ARM.exidx);
*(.ARM.exidx.*);
*(.ARM.extab.*);
}
}
INCLUDE device.x
/* Do not exceed this mark in the error messages below | */
/* # Alignment checks */
ASSERT(ORIGIN(FLASH) % 4 == 0, "
ERROR(cortex-m-rt): the start of the FLASH region must be 4-byte aligned");
ASSERT(ORIGIN(RAM) % 4 == 0, "
ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned");
ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, "
BUG(cortex-m-rt): .data is not 4-byte aligned");
ASSERT(__sidata % 4 == 0, "
BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned");
ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, "
BUG(cortex-m-rt): .bss is not 4-byte aligned");
ASSERT(__sheap % 4 == 0, "
BUG(cortex-m-rt): start of .heap is not 4-byte aligned");
/* # Position checks */
/* ## .vector_table */
ASSERT(__reset_vector == ADDR(.vector_table) + 0x8, "
BUG(cortex-m-rt): the reset vector is missing");
ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, "
BUG(cortex-m-rt): the exception vectors are missing");
ASSERT(SIZEOF(.vector_table) > 0x40, "
ERROR(cortex-m-rt): The interrupt vectors are missing.
Possible solutions, from most likely to less likely:
- Link to a svd2rust generated device crate
- Check that you actually use the device/hal/bsp crate in your code
- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency
may be enabling it)
- Supply the interrupt handlers yourself. Check the documentation for details.");
/* ## .text */
ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, "
ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section
Set _stext to an address greater than the end of .vector_table (See output of `nm`)");
ASSERT(_stext + SIZEOF(.text) < ORIGIN(FLASH) + LENGTH(FLASH), "
ERROR(cortex-m-rt): The .text section must be placed inside the FLASH memory.
Set _stext to an address smaller than 'ORIGIN(FLASH) + LENGTH(FLASH)'");
/* # Other checks */
ASSERT(SIZEOF(.got) == 0, "
ERROR(cortex-m-rt): .got section detected in the input object files
Dynamic relocations are not supported. If you are linking to C code compiled using
the 'cc' crate then modify your build script to compile the C code _without_
the -fPIC flag. See the documentation of the `cc::Build.pic` method for details.");
/* So let's talk about vector table alignment:
* ARMv8m section B3.30
* In a PE with a configurable vector table base, the vector table is naturally-aligned to a power of two, with an
* alignment value that is:
* - A minimum of 128 bytes.
* - Greater than or equal to (Number of Exceptions supported x4)
* ARMv7m section B1.5.3
* The Vector table must be naturally aligned to a power of two whose alignment value is greater than or equal to
* (Number of Exceptions supported x 4), with a minimum alignmentof 128 bytes.
*
* Annoyingly this means that vector table alignment is device specific.
* This is also a nice catch-22: we need to know the size of the vector
* table to calculate the alignment but we need to know the alignment
* before we know the size.
*
* The best we can do right now is use a specified alignment and
* indicate if it is wrong
*/
ASSERT(ADDR(.vector_table) % (1 << LOG2CEIL(SIZEOF(.vector_table))) == 0, "
Vector table alignment too small for number of exception entires. Increase
the alignment to the next power of two");
/* Do not exceed this mark in the error messages above | */