Skip to content

Commit bb6bdb2

Browse files
committed
fixes #274
Resolve issue where the linker script was not being preprocessed.
1 parent f08d177 commit bb6bdb2

File tree

3 files changed

+129
-39
lines changed

3 files changed

+129
-39
lines changed

optee-utee-build/src/code_generator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ fn property_value_data_codes(value: &PropertyValue) -> Result<proc_macro2::Token
232232
PropertyValue::Str(v) => Ok(string_to_binary_codes(v)),
233233
PropertyValue::BinaryBlock(v) => Ok(string_to_binary_codes(v)),
234234
PropertyValue::Identity(login, uuid) => {
235-
identity_to_tee_identity_value_codes(login.clone(), &uuid)
235+
identity_to_tee_identity_value_codes(*login, uuid)
236236
}
237237
}
238238
}

optee-utee-build/src/error.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub enum Error {
2222
Uuid(uuid::Error),
2323
PropertyNotFound(String),
2424
InvalidVersion(String),
25+
Utf(std::string::FromUtf8Error),
2526
}
2627

2728
impl From<std::io::Error> for Error {
@@ -41,3 +42,9 @@ impl From<uuid::Error> for Error {
4142
Self::Uuid(value)
4243
}
4344
}
45+
46+
impl From<std::string::FromUtf8Error> for Error {
47+
fn from(value: std::string::FromUtf8Error) -> Self {
48+
Self::Utf(value)
49+
}
50+
}

optee-utee-build/src/linker.rs

Lines changed: 121 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
use std::env;
1919
use std::fs::File;
2020
use std::io::Write;
21-
use std::io::{BufRead, BufReader};
2221
use std::path::PathBuf;
22+
use std::process::Command;
2323

2424
use crate::Error;
2525

@@ -67,20 +67,27 @@ pub enum LinkerType {
6767
///
6868
pub struct Linker {
6969
linker_type: LinkerType,
70+
ftrace_buf_size: Option<usize>,
7071
}
7172

7273
impl Linker {
7374
/// Construct a Linker by manually specific the type of linker, you may use
7475
/// `auto`, it would detect current linker automatically.
7576
pub fn new(linker_type: LinkerType) -> Self {
76-
Self { linker_type }
77+
Self {
78+
linker_type,
79+
ftrace_buf_size: None,
80+
}
7781
}
7882
/// Construct a Linker by auto detect the type of linker, try `new` function
7983
/// if our detection mismatch.
8084
pub fn auto() -> Self {
81-
Self {
82-
linker_type: Self::auto_detect_linker_type(),
83-
}
85+
Self::new(Self::auto_detect_linker_type())
86+
}
87+
/// Set the ftrace buffer size
88+
pub fn with_ftrace_buf_size(mut self, ftrace_buf_size: usize) -> Self {
89+
self.ftrace_buf_size = Some(ftrace_buf_size);
90+
self
8491
}
8592
/// Handle all the linking stuff.
8693
///
@@ -106,9 +113,9 @@ impl Linker {
106113
LinkerType::Ld => println!("cargo:rustc-link-arg=--sort-section=alignment"),
107114
};
108115
let mut dyn_list = File::create(out_dir.join("dyn_list"))?;
109-
write!(
116+
writeln!(
110117
dyn_list,
111-
"{{ __elf_phdr_info; trace_ext_prefix; trace_level; ta_head; }};\n"
118+
"{{ __elf_phdr_info; trace_ext_prefix; trace_level; ta_head; }};"
112119
)?;
113120
match self.linker_type {
114121
LinkerType::Cc => println!("cargo:rustc-link-arg=-Wl,--dynamic-list=dyn_list"),
@@ -129,53 +136,129 @@ impl Linker {
129136
// cargo passes TARGET as env to the build scripts
130137
const ENV_TARGET: &str = "TARGET";
131138
println!("cargo:rerun-if-env-changed={}", ENV_TARGET);
132-
let mut aarch64_flag = true;
133139
match env::var(ENV_TARGET) {
134140
Ok(ref v) if v == "arm-unknown-linux-gnueabihf" || v == "arm-unknown-optee" => {
135141
match self.linker_type {
136142
LinkerType::Cc => println!("cargo:rustc-link-arg=-Wl,--no-warn-mismatch"),
137143
LinkerType::Ld => println!("cargo:rustc-link-arg=--no-warn-mismatch"),
138144
};
139-
aarch64_flag = false;
140145
}
141146
_ => {}
142147
};
143148

144-
let f = BufReader::new(File::open(ta_dev_kit_dir.join("src/ta.ld.S"))?);
145-
let ta_lds_file_path = out_dir.join("ta.lds");
146-
let mut ta_lds = File::create(ta_lds_file_path.clone())?;
147-
for line in f.lines() {
148-
let l = line?;
149-
150-
if aarch64_flag {
151-
if l.starts_with('#')
152-
|| l == "OUTPUT_FORMAT(\"elf32-littlearm\")"
153-
|| l == "OUTPUT_ARCH(arm)"
154-
{
155-
continue;
156-
}
157-
} else {
158-
if l.starts_with('#')
159-
|| l == "OUTPUT_FORMAT(\"elf64-littleaarch64\")"
160-
|| l == "OUTPUT_ARCH(aarch64)"
161-
{
162-
continue;
163-
}
164-
}
165-
166-
if l == "\t. = ALIGN(4096);" {
167-
write!(ta_lds, "\t. = ALIGN(65536);\n")?;
168-
} else {
169-
write!(ta_lds, "{}\n", l)?;
170-
}
149+
let link_script_dest = out_dir.join("ta.lds");
150+
let link_script = self.generate_new_link_script(ta_dev_kit_dir)?;
151+
if !std::fs::read(link_script_dest.as_path())
152+
.is_ok_and(|v| v.as_slice() == link_script.as_bytes())
153+
{
154+
std::fs::write(link_script_dest.as_path(), link_script.as_bytes())?;
171155
}
172156

157+
Self::change_default_page_size();
173158
println!("cargo:rustc-link-search={}", out_dir.display());
174-
println!("cargo:rerun-if-changed={}", ta_lds_file_path.display());
175-
println!("cargo:rustc-link-arg=-T{}", ta_lds_file_path.display());
159+
println!("cargo:rerun-if-changed={}", link_script_dest.display());
160+
println!("cargo:rustc-link-arg=-T{}", link_script_dest.display());
176161
Ok(())
177162
}
178163

164+
// Correcting ELF segment alignment discrepancy between Rust and C, and in
165+
// the linker script provided by OP-TEE, the alignment are set to 0x1000.
166+
//
167+
// There is a mismatch in the ELF segment alignment between the Rust and
168+
// C builds.
169+
// The C-compiled binary correctly uses an alignment of 0x1000 (4KB),
170+
// which is required for OP-TEE compatibility. However, the
171+
// Rust-generated ELF defaults to 0x10000 (64KB).
172+
// To resolve this, we need to adjust the Rust linker parameters to
173+
// match the C alignment.
174+
//
175+
// example of C build elf header:
176+
// Elf file type is DYN (Position-Independent Executable file)
177+
// Entry point 0x2f4
178+
// There are 4 program headers, starting at offset 64
179+
//
180+
// Program Headers:
181+
// Type Offset VirtAddr PhysAddr
182+
// FileSiz MemSiz Flags Align
183+
// LOAD 0x0000000000001000 0x0000000000000000 0x0000000000000000
184+
// 0x00000000000191b8 0x00000000000191b8 R E 0x1000
185+
// LOAD 0x000000000001b000 0x000000000001a000 0x000000000001a000
186+
// 0x00000000000006c4 0x000000000000bf80 RW 0x1000
187+
// DYNAMIC 0x000000000001b000 0x000000000001a000 0x000000000001a000
188+
// 0x0000000000000110 0x0000000000000110 RW 0x8
189+
// GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
190+
// 0x0000000000000000 0x0000000000000000 RW 0x10
191+
//
192+
// example of Rust build elf header:
193+
// Elf file type is DYN (Position-Independent Executable file)
194+
// Entry point 0x18d8
195+
// There are 5 program headers, starting at offset 64
196+
//
197+
// Program Headers:
198+
// Type Offset VirtAddr PhysAddr
199+
// FileSiz MemSiz Flags Align
200+
// LOAD 0x0000000000010000 0x0000000000000000 0x0000000000000000
201+
// 0x000000000001c89c 0x0000000000028150 RWE 0x10000
202+
// DYNAMIC 0x000000000002c000 0x000000000001c000 0x000000000001c000
203+
// 0x0000000000000170 0x0000000000000170 RW 0x8
204+
// NOTE 0x000000000002c4b0 0x000000000001c4b0 0x000000000001c4b0
205+
// 0x0000000000000044 0x0000000000000044 R 0x4
206+
// GNU_EH_FRAME 0x0000000000024b54 0x0000000000014b54 0x0000000000014b54
207+
// 0x0000000000000e6c 0x0000000000000e6c R 0x4
208+
// GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
209+
// 0x0000000000000000 0x0000000000000000 RW 0x10
210+
fn change_default_page_size() {
211+
println!("cargo:rustc-link-arg=-z");
212+
println!("cargo:rustc-link-arg=max-page-size=0x1000");
213+
println!("cargo:rustc-link-arg=-z");
214+
println!("cargo:rustc-link-arg=common-page-size=0x1000");
215+
}
216+
217+
fn generate_new_link_script(&self, ta_dev_kit_dir: PathBuf) -> Result<String, Error> {
218+
let link_script_template_path = ta_dev_kit_dir.join("src/ta.ld.S");
219+
println!("cargo:rerun-if-changed={}", link_script_template_path.display());
220+
221+
let link_script_output = {
222+
const ENV_CC: &str = "CC";
223+
println!("cargo:rerun-if-env-changed={}", ENV_CC);
224+
225+
let cc_cmd = env::var(ENV_CC).unwrap_or("cc".to_string());
226+
let mut tmp = Command::new(cc_cmd);
227+
tmp.args([
228+
"-E",
229+
"-P",
230+
"-x",
231+
"c",
232+
link_script_template_path.to_str().expect("infallible"),
233+
]);
234+
const ENV_TARGET_ARCH: &str = "CARGO_CFG_TARGET_ARCH";
235+
println!("cargo:rerun-if-env-changed={}", ENV_TARGET_ARCH);
236+
match env::var(ENV_TARGET_ARCH)?.as_str() {
237+
"riscv32" => {
238+
tmp.arg("-DRV32=1");
239+
}
240+
"riscv64" => {
241+
tmp.arg("-DRV64=1");
242+
}
243+
"arm" => {
244+
tmp.arg("-DARM32=1");
245+
}
246+
"aarch64" => {
247+
tmp.arg("-DARM64=1");
248+
}
249+
_ => {}
250+
};
251+
if let Some(ftrace_buf_size) = self.ftrace_buf_size {
252+
tmp.arg(format!("-DCFG_FTRACE_BUF_SIZE={}", ftrace_buf_size));
253+
}
254+
tmp
255+
}
256+
.output()?
257+
.stdout;
258+
let link_script_text = String::from_utf8(link_script_output)?;
259+
Ok(link_script_text)
260+
}
261+
179262
fn auto_detect_linker_type() -> LinkerType {
180263
const ENV_RUSTC_LINKER: &str = "RUSTC_LINKER";
181264
println!("cargo:rerun-if-env-changed={}", ENV_RUSTC_LINKER);

0 commit comments

Comments
 (0)