Emit FORCEACTIVE in LCF & various fixes
This commit is contained in:
parent
d9e1ae2777
commit
457ee10a42
|
@ -214,7 +214,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decomp-toolkit"
|
name = "decomp-toolkit"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ar",
|
"ar",
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "decomp-toolkit"
|
||||||
description = "Yet another GameCube/Wii decompilation toolkit."
|
description = "Yet another GameCube/Wii decompilation toolkit."
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
|
@ -26,4 +26,5 @@ FORCEFILES
|
||||||
|
|
||||||
FORCEACTIVE
|
FORCEACTIVE
|
||||||
{
|
{
|
||||||
|
$FORCEACTIVE
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,7 @@ pub struct ProjectConfig {
|
||||||
/// Version of the MW `.comment` section format.
|
/// Version of the MW `.comment` section format.
|
||||||
/// If not present, no `.comment` sections will be written.
|
/// If not present, no `.comment` sections will be written.
|
||||||
pub mw_comment_version: Option<u8>,
|
pub mw_comment_version: Option<u8>,
|
||||||
|
#[serde(default)]
|
||||||
pub modules: Vec<ModuleConfig>,
|
pub modules: Vec<ModuleConfig>,
|
||||||
// Analysis options
|
// Analysis options
|
||||||
#[serde(default = "bool_true")]
|
#[serde(default = "bool_true")]
|
||||||
|
@ -258,6 +259,14 @@ fn split(args: SplitArgs) -> Result<()> {
|
||||||
if let Some((symbol_index, symbol)) =
|
if let Some((symbol_index, symbol)) =
|
||||||
obj.symbols.for_relocation(target, rel_reloc.kind)?
|
obj.symbols.for_relocation(target, rel_reloc.kind)?
|
||||||
{
|
{
|
||||||
|
if symbol.flags.is_local() {
|
||||||
|
bail!(
|
||||||
|
"Module {} relocation to {:#010X} found local symbol {}",
|
||||||
|
module_id,
|
||||||
|
symbol.address,
|
||||||
|
symbol.name
|
||||||
|
);
|
||||||
|
}
|
||||||
let addend = target as i64 - symbol.address as i64;
|
let addend = target as i64 - symbol.address as i64;
|
||||||
if addend != 0 {
|
if addend != 0 {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -268,7 +277,7 @@ fn split(args: SplitArgs) -> Result<()> {
|
||||||
addend
|
addend
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
obj.symbols.set_externally_referenced(symbol_index, true);
|
obj.symbols.flags(symbol_index).set_force_active(true);
|
||||||
} else {
|
} else {
|
||||||
// Add label
|
// Add label
|
||||||
let target_section = obj.section_at(target)?;
|
let target_section = obj.section_at(target)?;
|
||||||
|
@ -577,6 +586,10 @@ fn diff(args: DiffArgs) -> Result<()> {
|
||||||
apply_map_file(&args.map_file, &mut linked_obj)?;
|
apply_map_file(&args.map_file, &mut linked_obj)?;
|
||||||
|
|
||||||
for orig_sym in obj.symbols.iter() {
|
for orig_sym in obj.symbols.iter() {
|
||||||
|
if orig_sym.kind == ObjSymbolKind::Section || orig_sym.section.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let linked_sym = linked_obj
|
let linked_sym = linked_obj
|
||||||
.symbols
|
.symbols
|
||||||
.at_address(orig_sym.address as u32)
|
.at_address(orig_sym.address as u32)
|
||||||
|
|
|
@ -34,8 +34,6 @@ flags! {
|
||||||
Common,
|
Common,
|
||||||
Hidden,
|
Hidden,
|
||||||
ForceActive,
|
ForceActive,
|
||||||
// Same as ForceActive, but used internally
|
|
||||||
ExternallyReferenced,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +72,6 @@ impl ObjSymbolFlagSet {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_force_active(&self) -> bool { self.0.contains(ObjSymbolFlags::ForceActive) }
|
pub fn is_force_active(&self) -> bool { self.0.contains(ObjSymbolFlags::ForceActive) }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn is_externally_referenced(&self) -> bool {
|
|
||||||
self.0.contains(ObjSymbolFlags::ExternallyReferenced)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_scope(&mut self, scope: ObjSymbolScope) {
|
pub fn set_scope(&mut self, scope: ObjSymbolScope) {
|
||||||
match scope {
|
match scope {
|
||||||
|
@ -101,11 +94,11 @@ impl ObjSymbolFlagSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_externally_referenced(&mut self, value: bool) {
|
pub fn set_force_active(&mut self, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
self.0 |= ObjSymbolFlags::ExternallyReferenced;
|
self.0 |= ObjSymbolFlags::ForceActive;
|
||||||
} else {
|
} else {
|
||||||
self.0 &= !ObjSymbolFlags::ExternallyReferenced;
|
self.0 &= !ObjSymbolFlags::ForceActive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,8 +555,9 @@ impl ObjSymbols {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_externally_referenced(&mut self, idx: SymbolIndex, value: bool) {
|
#[inline]
|
||||||
self.symbols[idx].flags.set_externally_referenced(value);
|
pub fn flags(&mut self, idx: SymbolIndex) -> &mut ObjSymbolFlagSet {
|
||||||
|
&mut self.symbols[idx].flags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,6 +623,18 @@ impl ObjInfo {
|
||||||
|
|
||||||
pub fn section_data(&self, start: u32, end: u32) -> Result<(&ObjSection, &[u8])> {
|
pub fn section_data(&self, start: u32, end: u32) -> Result<(&ObjSection, &[u8])> {
|
||||||
let section = self.section_at(start)?;
|
let section = self.section_at(start)?;
|
||||||
|
ensure!(
|
||||||
|
section.contains_range(start..end),
|
||||||
|
"Range {:#010X}-{:#010X} outside of section {}: {:#010X}-{:#010X}",
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
section.name,
|
||||||
|
section.address,
|
||||||
|
section.address + section.size
|
||||||
|
);
|
||||||
|
if section.kind == ObjSectionKind::Bss {
|
||||||
|
return Ok((section, &[]));
|
||||||
|
}
|
||||||
let data = if end == 0 {
|
let data = if end == 0 {
|
||||||
§ion.data[(start as u64 - section.address) as usize..]
|
§ion.data[(start as u64 - section.address) as usize..]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -97,7 +97,7 @@ fn split_ctors_dtors(obj: &mut ObjInfo, section_start: u32, section_end: u32) ->
|
||||||
|
|
||||||
// Hack to avoid deadstripping
|
// Hack to avoid deadstripping
|
||||||
for symbol_idx in referenced_symbols {
|
for symbol_idx in referenced_symbols {
|
||||||
obj.symbols.set_externally_referenced(symbol_idx, true);
|
obj.symbols.flags(symbol_idx).set_force_active(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl CommentSym {
|
||||||
vis_flags |= 0xD;
|
vis_flags |= 0xD;
|
||||||
}
|
}
|
||||||
let mut active_flags = 0;
|
let mut active_flags = 0;
|
||||||
if symbol.flags.is_force_active() || symbol.flags.is_externally_referenced() {
|
if symbol.flags.is_force_active() {
|
||||||
active_flags |= 0x8; // TODO what is 0x10?
|
active_flags |= 0x8; // TODO what is 0x10?
|
||||||
}
|
}
|
||||||
Self { align, vis_flags, active_flags }
|
Self { align, vis_flags, active_flags }
|
||||||
|
|
|
@ -200,9 +200,9 @@ fn write_symbol<W: Write>(w: &mut W, obj: &ObjInfo, symbol: &ObjSymbol) -> Resul
|
||||||
if symbol.flags.is_hidden() {
|
if symbol.flags.is_hidden() {
|
||||||
write!(w, " hidden")?;
|
write!(w, " hidden")?;
|
||||||
}
|
}
|
||||||
if symbol.flags.is_force_active() {
|
// if symbol.flags.is_force_active() {
|
||||||
write!(w, " force_active")?;
|
// write!(w, " force_active")?;
|
||||||
}
|
// }
|
||||||
if obj.blocked_ranges.contains_key(&(symbol.address as u32)) {
|
if obj.blocked_ranges.contains_key(&(symbol.address as u32)) {
|
||||||
write!(w, " noreloc")?;
|
write!(w, " noreloc")?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,13 @@ pub fn generate_ldscript(obj: &ObjInfo, auto_force_files: bool) -> Result<String
|
||||||
force_files.push(obj_path.file_name().unwrap().to_str().unwrap().to_string());
|
force_files.push(obj_path.file_name().unwrap().to_str().unwrap().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut force_active = vec![];
|
||||||
|
for symbol in obj.symbols.iter() {
|
||||||
|
if symbol.flags.is_force_active() && symbol.flags.is_global() {
|
||||||
|
force_active.push(symbol.name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to handle missing .sbss2 section... what's the proper way?
|
// Hack to handle missing .sbss2 section... what's the proper way?
|
||||||
let last_section_name = obj.sections.last().unwrap().name.clone();
|
let last_section_name = obj.sections.last().unwrap().name.clone();
|
||||||
let last_section_symbol = format!("_f_{}", last_section_name.trim_start_matches('.'));
|
let last_section_symbol = format!("_f_{}", last_section_name.trim_start_matches('.'));
|
||||||
|
@ -31,7 +38,8 @@ pub fn generate_ldscript(obj: &ObjInfo, auto_force_files: bool) -> Result<String
|
||||||
.replacen("$SECTIONS", §ion_defs, 1)
|
.replacen("$SECTIONS", §ion_defs, 1)
|
||||||
.replace("$LAST_SECTION_SYMBOL", &last_section_symbol)
|
.replace("$LAST_SECTION_SYMBOL", &last_section_symbol)
|
||||||
.replace("$LAST_SECTION_NAME", &last_section_name)
|
.replace("$LAST_SECTION_NAME", &last_section_name)
|
||||||
.replacen("$STACKSIZE", &format!("{:#X}", stack_size), 1);
|
.replacen("$STACKSIZE", &format!("{:#X}", stack_size), 1)
|
||||||
|
.replacen("$FORCEACTIVE", &force_active.join("\n "), 1);
|
||||||
out = if auto_force_files {
|
out = if auto_force_files {
|
||||||
out.replacen("$FORCEFILES", &force_files.join("\n "), 1)
|
out.replacen("$FORCEFILES", &force_files.join("\n "), 1)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue