Skip to content

Commit f535f1c

Browse files
authored
Fix flip-link, make SSP configurable (#3203)
* Test flip-link * Add todo * Rebuild if linker files change * Let espsegs show .stack * Try to fix flip_link * Changelog * Make SSP configurable * Substitute config values
1 parent eb771e1 commit f535f1c

File tree

19 files changed

+249
-144
lines changed

19 files changed

+249
-144
lines changed

esp-hal/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Support for `rand_core` 0.9 (#3211)
13+
- `ESP_HAL_CONFIG_STACK_GUARD_OFFSET` and `ESP_HAL_CONFIG_STACK_GUARD_VALUE` to configure Rust's [Stack smashing protection](https://doc.rust-lang.org/rustc/exploit-mitigations.html#stack-smashing-protection) (#3203)
1314

1415
### Changed
1516

@@ -22,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2223
- ESP32-S2: Fixed PSRAM initialization (#3196)
2324
- `Uart::{with_tx, with_rx}` can now be called on the async driver as well (#3212)
2425
- ESP32: Fixed SPI3 QSPI signals (#3201)
26+
- ESP32-C6/H2: The `flip_link` feature should no longer crash (#3203)
2527

2628
### Removed
2729

esp-hal/build.rs

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
collections::HashMap,
23
env,
34
error::Error,
45
fs::{self, File},
@@ -122,6 +123,19 @@ fn main() -> Result<(), Box<dyn Error>> {
122123
Some(Validator::Enumeration(
123124
vec![String::from("quad"), String::from("octal")]
124125
)),
126+
),
127+
// Rust's stack smashing protection configuration
128+
(
129+
"stack-guard-offset",
130+
"The stack guard variable will be placed this many bytes from the stack's end.",
131+
Value::Integer(4096),
132+
None
133+
),
134+
(
135+
"stack-guard-value",
136+
"The value to be written to the stack guard variable.",
137+
Value::Integer(0xDEED_BAAD),
138+
None
125139
)
126140
], true);
127141

@@ -166,19 +180,30 @@ fn main() -> Result<(), Box<dyn Error>> {
166180
} else {
167181
// RISC-V devices:
168182

169-
preprocess_file(&config_symbols, "ld/riscv/asserts.x", out.join("asserts.x"))?;
170-
preprocess_file(&config_symbols, "ld/riscv/debug.x", out.join("debug.x"))?;
171183
preprocess_file(
172184
&config_symbols,
185+
&cfg,
186+
"ld/riscv/asserts.x",
187+
out.join("asserts.x"),
188+
)?;
189+
preprocess_file(
190+
&config_symbols,
191+
&cfg,
192+
"ld/riscv/debug.x",
193+
out.join("debug.x"),
194+
)?;
195+
preprocess_file(
196+
&config_symbols,
197+
&cfg,
173198
"ld/riscv/hal-defaults.x",
174199
out.join("hal-defaults.x"),
175200
)?;
176201
}
177202

178203
// With the architecture-specific linker scripts taken care of, we can copy all
179204
// remaining linker scripts which are common to all devices:
180-
copy_dir_all(&config_symbols, "ld/sections", &out)?;
181-
copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?;
205+
copy_dir_all(&config_symbols, &cfg, "ld/sections", &out)?;
206+
copy_dir_all(&config_symbols, &cfg, format!("ld/{device_name}"), &out)?;
182207

183208
Ok(())
184209
}
@@ -188,6 +213,7 @@ fn main() -> Result<(), Box<dyn Error>> {
188213

189214
fn copy_dir_all(
190215
config_symbols: &[&str],
216+
cfg: &HashMap<String, Value>,
191217
src: impl AsRef<Path>,
192218
dst: impl AsRef<Path>,
193219
) -> std::io::Result<()> {
@@ -198,12 +224,14 @@ fn copy_dir_all(
198224
if ty.is_dir() {
199225
copy_dir_all(
200226
config_symbols,
227+
cfg,
201228
entry.path(),
202229
dst.as_ref().join(entry.file_name()),
203230
)?;
204231
} else {
205232
preprocess_file(
206233
config_symbols,
234+
cfg,
207235
entry.path(),
208236
dst.as_ref().join(entry.file_name()),
209237
)?;
@@ -215,17 +243,20 @@ fn copy_dir_all(
215243
/// A naive pre-processor for linker scripts
216244
fn preprocess_file(
217245
config: &[&str],
246+
cfg: &HashMap<String, Value>,
218247
src: impl AsRef<Path>,
219248
dst: impl AsRef<Path>,
220249
) -> std::io::Result<()> {
250+
println!("cargo:rerun-if-changed={}", src.as_ref().display());
251+
221252
let file = File::open(src)?;
222253
let mut out_file = File::create(dst)?;
223254

224255
let mut take = Vec::new();
225256
take.push(true);
226257

227258
for line in std::io::BufReader::new(file).lines() {
228-
let line = line?;
259+
let line = substitute_config(cfg, &line?);
229260
let trimmed = line.trim();
230261

231262
if let Some(condition) = trimmed.strip_prefix("#IF ") {
@@ -252,6 +283,43 @@ fn preprocess_file(
252283
Ok(())
253284
}
254285

286+
fn substitute_config(cfg: &HashMap<String, Value>, line: &str) -> String {
287+
let mut result = String::new();
288+
let mut chars = line.chars().peekable();
289+
290+
while let Some(c) = chars.next() {
291+
if c != '$' {
292+
result.push(c);
293+
continue;
294+
}
295+
296+
let Some('{') = chars.peek() else {
297+
result.push(c);
298+
continue;
299+
};
300+
chars.next();
301+
302+
let mut key = String::new();
303+
for c in chars.by_ref() {
304+
if c == '}' {
305+
break;
306+
}
307+
key.push(c);
308+
}
309+
match cfg
310+
.get(&key)
311+
.unwrap_or_else(|| panic!("missing config key: {key}"))
312+
{
313+
Value::Bool(true) => result.push('1'),
314+
Value::Bool(false) => result.push('0'),
315+
Value::Integer(value) => result.push_str(&value.to_string()),
316+
Value::String(value) => result.push_str(value),
317+
}
318+
}
319+
320+
result
321+
}
322+
255323
#[cfg(feature = "esp32")]
256324
fn generate_memory_extras() -> Vec<u8> {
257325
let reserve_dram = if cfg!(feature = "bluetooth") {

esp-hal/ld/esp32/esp32.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ INCLUDE "fixups/rtc_fast_rwdata_dummy.x"
1919
/* END ESP32 fixups */
2020

2121
/* Shared sections - ordering matters */
22-
INCLUDE "rwtext.x"
22+
SECTIONS {
23+
INCLUDE "rwtext.x"
24+
INCLUDE "rwdata.x"
25+
}
2326
INCLUDE "text.x"
24-
INCLUDE "rwdata.x"
2527
INCLUDE "rodata.x"
2628
INCLUDE "rtc_fast.x"
2729
INCLUDE "rtc_slow.x"

esp-hal/ld/esp32c2/esp32c2.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ PROVIDE(__global_pointer$ = _data_start + 0x800);
8080
/* end of esp32c2 fixups */
8181

8282
/* Shared sections - ordering matters */
83-
INCLUDE "rwtext.x"
83+
SECTIONS {
84+
INCLUDE "rwtext.x"
85+
INCLUDE "rwdata.x"
86+
}
8487
INCLUDE "text.x"
85-
INCLUDE "rwdata.x"
8688
INCLUDE "rodata.x"
8789
INCLUDE "stack.x"
8890
INCLUDE "dram2.x"

esp-hal/ld/esp32c3/esp32c3.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ PROVIDE(__global_pointer$ = _data_start + 0x800);
8080
/* end of esp32c3 fixups */
8181

8282
/* Shared sections - ordering matters */
83-
INCLUDE "rwtext.x"
83+
SECTIONS {
84+
INCLUDE "rwtext.x"
85+
INCLUDE "rwdata.x"
86+
}
8487
INCLUDE "text.x"
85-
INCLUDE "rwdata.x"
8688
INCLUDE "rodata.x"
8789
INCLUDE "rtc_fast.x"
8890
INCLUDE "stack.x"

esp-hal/ld/esp32c6/esp32c6.x

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,17 @@ SECTIONS {
5555
KEEP(*(.trap));
5656
*(.trap.*);
5757
} > RWTEXT
58+
59+
/* Shared sections - ordering matters */
60+
INCLUDE "rwtext.x"
61+
INCLUDE "rwdata.x"
62+
/* End of Shared sections */
5863
}
59-
INSERT BEFORE .rwtext;
64+
#IF ESP_HAL_CONFIG_FLIP_LINK
65+
/* INSERT BEFORE does not seem to work for the .stack section. Instead, we place every RAM
66+
section after .stack if `flip_link` is enabled. */
67+
INSERT AFTER .stack;
68+
#ENDIF
6069

6170
SECTIONS {
6271
/**
@@ -71,15 +80,13 @@ SECTIONS {
7180
INSERT BEFORE .rodata;
7281
/* end of esp32c6 fixups */
7382

74-
/* Shared sections - ordering matters */
75-
INCLUDE "rwtext.x"
83+
/* Shared sections #2 - ordering matters */
7684
INCLUDE "text.x"
77-
INCLUDE "rwdata.x"
7885
INCLUDE "rodata.x"
7986
INCLUDE "rtc_fast.x"
8087
INCLUDE "stack.x"
8188
INCLUDE "dram2.x"
82-
/* End of Shared sections */
89+
/* End of Shared sections #2 */
8390

8491
INCLUDE "debug.x"
8592

esp-hal/ld/esp32h2/esp32h2.x

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,24 @@ PROVIDE(_start_trap = default_start_trap);
4343
/* Must be called __global_pointer$ for linker relaxations to work. */
4444
PROVIDE(__global_pointer$ = _data_start + 0x800);
4545

46+
4647
SECTIONS {
4748
.trap : ALIGN(4)
4849
{
4950
KEEP(*(.trap));
5051
*(.trap.*);
5152
} > RWTEXT
53+
54+
/* Shared sections - ordering matters */
55+
INCLUDE "rwtext.x"
56+
INCLUDE "rwdata.x"
57+
/* End of Shared sections */
5258
}
53-
INSERT BEFORE .rwtext;
59+
#IF ESP_HAL_CONFIG_FLIP_LINK
60+
/* INSERT BEFORE does not seem to work for the .stack section. Instead, we place every RAM
61+
section after .stack if `flip_link` is enabled. */
62+
INSERT AFTER .stack;
63+
#ENDIF
5464

5565
SECTIONS {
5666
/**
@@ -64,15 +74,13 @@ SECTIONS {
6474
}
6575
INSERT BEFORE .rodata;
6676

67-
/* Shared sections - ordering matters */
68-
INCLUDE "rwtext.x"
77+
/* Shared sections #2 - ordering matters */
6978
INCLUDE "text.x"
70-
INCLUDE "rwdata.x"
7179
INCLUDE "rodata.x"
7280
INCLUDE "rtc_fast.x"
7381
INCLUDE "stack.x"
7482
INCLUDE "dram2.x"
75-
/* End of Shared sections */
83+
/* End of Shared sections #2 */
7684

7785
INCLUDE "debug.x"
7886

esp-hal/ld/esp32s2/esp32s2.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ INCLUDE "fixups/rtc_fast_rwdata_dummy.x"
2727
/* End of fixups for esp32s2 */
2828

2929
/* Shared sections - ordering matters */
30-
INCLUDE "rwtext.x"
30+
SECTIONS {
31+
INCLUDE "rwtext.x"
32+
INCLUDE "rwdata.x"
33+
}
3134
INCLUDE "text.x"
32-
INCLUDE "rwdata.x"
3335
INCLUDE "rodata.x"
3436
INCLUDE "rtc_fast.x"
3537
INCLUDE "rtc_slow.x"

esp-hal/ld/esp32s3/esp32s3.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ INCLUDE "fixups/rodata_dummy.x"
4141
/* End of ESP32S3 fixups */
4242

4343
/* Shared sections - ordering matters */
44-
INCLUDE "rwtext.x"
44+
SECTIONS {
45+
INCLUDE "rwtext.x"
46+
INCLUDE "rwdata.x"
47+
}
4548
INCLUDE "text.x"
46-
INCLUDE "rwdata.x"
4749
INCLUDE "rodata.x"
4850
INCLUDE "rtc_fast.x"
4951
INCLUDE "rtc_slow.x"

0 commit comments

Comments
 (0)