diff --git a/Cargo.lock b/Cargo.lock index e1353ab..916bddc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "decomp-toolkit" -version = "0.5.2" +version = "0.5.3" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 4870da9..43f5a50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "decomp-toolkit" description = "Yet another GameCube/Wii decompilation toolkit." authors = ["Luke Street "] license = "MIT OR Apache-2.0" -version = "0.5.2" +version = "0.5.3" edition = "2021" publish = false build = "build.rs" diff --git a/src/cmd/dol.rs b/src/cmd/dol.rs index a8ac2db..dc7c742 100644 --- a/src/cmd/dol.rs +++ b/src/cmd/dol.rs @@ -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, + #[serde(skip_serializing_if = "is_default")] + pub ldscript_template: Option, } 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()), diff --git a/src/util/lcf.rs b/src/util/lcf.rs index 1a646d2..06f6db2 100644 --- a/src/util/lcf.rs +++ b/src/util/lcf.rs @@ -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 { +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 { 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 Result Result { +pub fn generate_ldscript_partial( + obj: &ObjInfo, + template: Option<&str>, + force_active: &[String], +) -> Result { 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) }