mirror of
https://github.com/encounter/decomp-toolkit.git
synced 2025-12-17 00:47:08 +00:00
Overhauled common BSS support & more
- With a map, attempts to detect and handle common BSS automatically - With a map, attempts to detect and correct inflated common BSS bug (< GC 2.7 linker) - Support for "stripped" symbols, sometimes required to match inflated common BSS sizes - Warns on duplicated TUs in a map (other than common BSS) - Automatically adds `comment:0` to `.s` TUs from a map (avoids linker crash)
This commit is contained in:
@@ -125,6 +125,13 @@ impl ObjSections {
|
||||
self.iter()
|
||||
.flat_map(|(idx, s)| s.splits.iter().map(move |(addr, split)| (idx, s, addr, split)))
|
||||
}
|
||||
|
||||
pub fn common_bss_start(&self) -> Option<(usize, u32)> {
|
||||
let Ok(Some((section_index, section))) = self.by_name(".bss") else {
|
||||
return None;
|
||||
};
|
||||
section.splits.iter().find(|(_, split)| split.common).map(|(addr, _)| (section_index, addr))
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for ObjSections {
|
||||
|
||||
@@ -26,9 +26,9 @@ pub enum ObjSymbolScope {
|
||||
}
|
||||
|
||||
flags! {
|
||||
#[repr(u8)]
|
||||
#[repr(u32)]
|
||||
#[derive(Deserialize_repr, Serialize_repr)]
|
||||
pub enum ObjSymbolFlags: u8 {
|
||||
pub enum ObjSymbolFlags: u32 {
|
||||
Global,
|
||||
Local,
|
||||
Weak,
|
||||
@@ -39,6 +39,9 @@ flags! {
|
||||
RelocationIgnore,
|
||||
/// Symbol won't be written to symbols file
|
||||
NoWrite,
|
||||
/// Symbol was stripped from the original object,
|
||||
/// but is still useful for common BSS matching.
|
||||
Stripped,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +86,9 @@ impl ObjSymbolFlagSet {
|
||||
#[inline]
|
||||
pub fn is_no_write(&self) -> bool { self.0.contains(ObjSymbolFlags::NoWrite) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_stripped(&self) -> bool { self.0.contains(ObjSymbolFlags::Stripped) }
|
||||
|
||||
#[inline]
|
||||
pub fn set_scope(&mut self, scope: ObjSymbolScope) {
|
||||
match scope {
|
||||
@@ -119,7 +125,8 @@ impl ObjSymbolFlagSet {
|
||||
self.0
|
||||
& (ObjSymbolFlags::ForceActive
|
||||
| ObjSymbolFlags::NoWrite
|
||||
| ObjSymbolFlags::RelocationIgnore)
|
||||
| ObjSymbolFlags::RelocationIgnore
|
||||
| ObjSymbolFlags::Stripped)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +219,10 @@ impl ObjSymbols {
|
||||
}
|
||||
|
||||
pub fn add(&mut self, in_symbol: ObjSymbol, replace: bool) -> Result<SymbolIndex> {
|
||||
let opt = if let Some(section_index) = in_symbol.section {
|
||||
let opt = if in_symbol.flags.is_stripped() {
|
||||
// Stripped symbols don't overwrite existing symbols
|
||||
None
|
||||
} else if let Some(section_index) = in_symbol.section {
|
||||
self.at_section_address(section_index, in_symbol.address as u32).find(|(_, symbol)| {
|
||||
symbol.kind == in_symbol.kind ||
|
||||
// Replace auto symbols with real symbols
|
||||
@@ -228,7 +238,8 @@ impl ObjSymbols {
|
||||
let replace = replace || (is_auto_symbol(existing) && !is_auto_symbol(&in_symbol));
|
||||
let size =
|
||||
if existing.size_known && in_symbol.size_known && existing.size != in_symbol.size {
|
||||
log::warn!(
|
||||
// TODO fix this and restore to warning
|
||||
log::debug!(
|
||||
"Conflicting size for {}: was {:#X}, now {:#X}",
|
||||
existing.name,
|
||||
existing.size,
|
||||
@@ -336,6 +347,8 @@ impl ObjSymbols {
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(move |&idx| (idx, &self.symbols[idx]))
|
||||
// "Stripped" symbols don't actually exist at the address
|
||||
.filter(|(_, sym)| !sym.flags.is_stripped())
|
||||
}
|
||||
|
||||
pub fn kind_at_section_address(
|
||||
@@ -513,7 +526,7 @@ impl Index<SymbolIndex> for ObjSymbols {
|
||||
impl ObjSymbol {
|
||||
/// Whether this symbol can be referenced by the given relocation kind.
|
||||
pub fn referenced_by(&self, reloc_kind: ObjRelocKind) -> bool {
|
||||
if self.flags.is_relocation_ignore() {
|
||||
if self.flags.is_relocation_ignore() || self.flags.is_stripped() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user