Add `ldscript_template` option to project config

This commit is contained in:
Luke Street 2023-09-23 07:56:49 -04:00
parent 400fb7fa7f
commit 610a2e56b9
4 changed files with 36 additions and 8 deletions

2
Cargo.lock generated
View File

@ -331,7 +331,7 @@ dependencies = [
[[package]]
name = "decomp-toolkit"
version = "0.5.2"
version = "0.5.3"
dependencies = [
"anyhow",
"ar",

View File

@ -3,7 +3,7 @@ name = "decomp-toolkit"
description = "Yet another GameCube/Wii decompilation toolkit."
authors = ["Luke Street <luke@street.dev>"]
license = "MIT OR Apache-2.0"
version = "0.5.2"
version = "0.5.3"
edition = "2021"
publish = false
build = "build.rs"

View File

@ -244,6 +244,8 @@ pub struct ModuleConfig {
/// Forces the given symbols to be active in the linker script.
#[serde(default, skip_serializing_if = "is_default")]
pub force_active: Vec<String>,
#[serde(skip_serializing_if = "is_default")]
pub ldscript_template: Option<PathBuf>,
}
impl ModuleConfig {
@ -821,7 +823,17 @@ fn split_write_obj(
}
// Generate ldscript.lcf
fs::write(&out_config.ldscript, generate_ldscript(obj, &module_config.force_active)?)?;
let ldscript_template = if let Some(template) = &module_config.ldscript_template {
Some(fs::read_to_string(template).with_context(|| {
format!("Failed to read linker script template '{}'", template.display())
})?)
} else {
None
};
fs::write(
&out_config.ldscript,
generate_ldscript(obj, ldscript_template.as_deref(), &module_config.force_active)?,
)?;
if config.write_asm {
debug!("Writing disassembly");
@ -1556,6 +1568,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None,
map: None,
force_active: vec![],
ldscript_template: None,
},
selfile: None,
selfile_hash: None,
@ -1590,6 +1603,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None,
map: None,
force_active: vec![],
ldscript_template: None,
});
}
Some(ext) if ext.eq_ignore_ascii_case(OsStr::new("sel")) => {
@ -1605,6 +1619,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None,
map: None,
force_active: vec![],
ldscript_template: None,
});
}
_ => bail!("Unknown file extension: '{}'", path.display()),

View File

@ -9,9 +9,16 @@ use crate::obj::{ObjInfo, ObjKind};
#[inline]
const fn align_up(value: u32, align: u32) -> u32 { (value + (align - 1)) & !(align - 1) }
pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<String> {
const LCF_TEMPLATE: &str = include_str!("../../assets/ldscript.lcf");
const LCF_PARTIAL_TEMPLATE: &str = include_str!("../../assets/ldscript_partial.lcf");
pub fn generate_ldscript(
obj: &ObjInfo,
template: Option<&str>,
force_active: &[String],
) -> Result<String> {
if obj.kind == ObjKind::Relocatable {
return generate_ldscript_partial(obj, force_active);
return generate_ldscript_partial(obj, template, force_active);
}
let origin = obj.sections.iter().map(|(_, s)| s.address).min().unwrap();
@ -66,7 +73,8 @@ pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<Strin
let last_section_name = obj.sections.iter().next_back().unwrap().1.name.clone();
let last_section_symbol = format!("_f_{}", last_section_name.trim_start_matches('.'));
let out = include_str!("../../assets/ldscript.lcf")
let out = template
.unwrap_or(LCF_TEMPLATE)
.replace("$ORIGIN", &format!("{:#X}", origin))
.replace("$SECTIONS", &section_defs)
.replace("$LAST_SECTION_SYMBOL", &last_section_symbol)
@ -77,7 +85,11 @@ pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<Strin
Ok(out)
}
pub fn generate_ldscript_partial(obj: &ObjInfo, force_active: &[String]) -> Result<String> {
pub fn generate_ldscript_partial(
obj: &ObjInfo,
template: Option<&str>,
force_active: &[String],
) -> Result<String> {
let mut force_files = Vec::with_capacity(obj.link_order.len());
for unit in &obj.link_order {
let obj_path = obj_path_for_unit(&unit.name);
@ -92,7 +104,8 @@ pub fn generate_ldscript_partial(obj: &ObjInfo, force_active: &[String]) -> Resu
}
}
let out = include_str!("../../assets/ldscript_partial.lcf")
let out = template
.unwrap_or(LCF_PARTIAL_TEMPLATE)
.replace("$FORCEACTIVE", &force_active.join("\n "));
Ok(out)
}