Add `noexport` attr to symbols.txt

Rename `auto_force_active` to `export_all`.
This is a better solution to code_merging, as
individual functions can be marked `noexport`.
This commit is contained in:
Luke Street 2024-01-14 13:57:56 -07:00
parent 1614997108
commit 7b7c8ce251
10 changed files with 42 additions and 30 deletions

2
Cargo.lock generated
View File

@ -295,7 +295,7 @@ dependencies = [
[[package]] [[package]]
name = "decomp-toolkit" name = "decomp-toolkit"
version = "0.7.1" version = "0.7.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ar", "ar",

View File

@ -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.7.1" version = "0.7.2"
edition = "2021" edition = "2021"
publish = false publish = false
repository = "https://github.com/encounter/decomp-toolkit" repository = "https://github.com/encounter/decomp-toolkit"

View File

@ -228,9 +228,9 @@ pub struct ProjectConfig {
/// Fills gaps between symbols to avoid linker realignment. /// Fills gaps between symbols to avoid linker realignment.
#[serde(default = "bool_true", skip_serializing_if = "is_true")] #[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub fill_gaps: bool, pub fill_gaps: bool,
/// Marks all emitted symbols as "force active" to prevent the linker from removing them. /// Marks all emitted symbols as "exported" to prevent the linker from removing them.
#[serde(default = "bool_true", skip_serializing_if = "is_true")] #[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub auto_force_active: bool, pub export_all: bool,
} }
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
@ -248,7 +248,7 @@ pub struct ModuleConfig {
pub symbols: Option<PathBuf>, pub symbols: Option<PathBuf>,
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")] #[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
pub map: Option<PathBuf>, pub map: Option<PathBuf>,
/// Forces the given symbols to be active in the linker script. /// Forces the given symbols to be active (exported) in the linker script.
#[serde(default, skip_serializing_if = "is_default")] #[serde(default, skip_serializing_if = "is_default")]
pub force_active: Vec<String>, pub force_active: Vec<String>,
#[serde(skip_serializing_if = "is_default")] #[serde(skip_serializing_if = "is_default")]
@ -397,7 +397,7 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
section, section,
size: existing_symbol.size, size: existing_symbol.size,
size_known: existing_symbol.size_known, size_known: existing_symbol.size_known,
flags: ObjSymbolFlagSet(existing_symbol.flags.0 | ObjSymbolFlags::ForceActive), flags: ObjSymbolFlagSet(existing_symbol.flags.0 | ObjSymbolFlags::Exported),
kind: existing_symbol.kind, kind: existing_symbol.kind,
align: existing_symbol.align, align: existing_symbol.align,
data_kind: existing_symbol.data_kind, data_kind: existing_symbol.data_kind,
@ -412,7 +412,7 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
demangled_name: symbol.demangled_name.clone(), demangled_name: symbol.demangled_name.clone(),
address: address as u64, address: address as u64,
section, section,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global | ObjSymbolFlags::ForceActive), flags: ObjSymbolFlagSet(ObjSymbolFlags::Global | ObjSymbolFlags::Exported),
..*symbol ..*symbol
}, },
false, false,
@ -574,7 +574,7 @@ fn update_symbols(
name, name,
address: rel_reloc.addend as u64, address: rel_reloc.addend as u64,
section: Some(target_section_index), section: Some(target_section_index),
flags: ObjSymbolFlagSet(ObjSymbolFlags::ForceActive.into()), flags: ObjSymbolFlagSet(ObjSymbolFlags::Exported.into()),
..Default::default() ..Default::default()
})?; })?;
} }
@ -862,7 +862,7 @@ fn split_write_obj(
entry, entry,
}; };
for (unit, split_obj) in module.obj.link_order.iter().zip(&split_objs) { for (unit, split_obj) in module.obj.link_order.iter().zip(&split_objs) {
let out_obj = write_elf(split_obj, config.auto_force_active)?; let out_obj = write_elf(split_obj, config.export_all)?;
let out_path = obj_dir.join(obj_path_for_unit(&unit.name)); let out_path = obj_dir.join(obj_path_for_unit(&unit.name));
out_config.units.push(OutputUnit { out_config.units.push(OutputUnit {
object: out_path.clone(), object: out_path.clone(),
@ -1766,7 +1766,7 @@ fn config(args: ConfigArgs) -> Result<()> {
common_start: None, common_start: None,
symbols_known: false, symbols_known: false,
fill_gaps: true, fill_gaps: true,
auto_force_active: true, export_all: true,
}; };
let mut modules = Vec::<(u32, ModuleConfig)>::new(); let mut modules = Vec::<(u32, ModuleConfig)>::new();

View File

@ -34,7 +34,8 @@ flags! {
Weak, Weak,
Common, Common,
Hidden, Hidden,
ForceActive, /// Force symbol to be exported (force active)
Exported,
/// Symbol isn't referenced by any relocations /// Symbol isn't referenced by any relocations
RelocationIgnore, RelocationIgnore,
/// Symbol won't be written to symbols file /// Symbol won't be written to symbols file
@ -42,6 +43,8 @@ flags! {
/// Symbol was stripped from the original object, /// Symbol was stripped from the original object,
/// but is still useful for common BSS matching. /// but is still useful for common BSS matching.
Stripped, Stripped,
/// Disable automatic export of symbol
NoExport,
} }
} }
@ -78,7 +81,7 @@ impl ObjSymbolFlagSet {
pub fn is_hidden(&self) -> bool { self.0.contains(ObjSymbolFlags::Hidden) } pub fn is_hidden(&self) -> bool { self.0.contains(ObjSymbolFlags::Hidden) }
#[inline] #[inline]
pub fn is_force_active(&self) -> bool { self.0.contains(ObjSymbolFlags::ForceActive) } pub fn is_exported(&self) -> bool { self.0.contains(ObjSymbolFlags::Exported) }
#[inline] #[inline]
pub fn is_relocation_ignore(&self) -> bool { self.0.contains(ObjSymbolFlags::RelocationIgnore) } pub fn is_relocation_ignore(&self) -> bool { self.0.contains(ObjSymbolFlags::RelocationIgnore) }
@ -89,6 +92,9 @@ impl ObjSymbolFlagSet {
#[inline] #[inline]
pub fn is_stripped(&self) -> bool { self.0.contains(ObjSymbolFlags::Stripped) } pub fn is_stripped(&self) -> bool { self.0.contains(ObjSymbolFlags::Stripped) }
#[inline]
pub fn is_no_export(&self) -> bool { self.0.contains(ObjSymbolFlags::NoExport) }
#[inline] #[inline]
pub fn set_scope(&mut self, scope: ObjSymbolScope) { pub fn set_scope(&mut self, scope: ObjSymbolScope) {
match scope { match scope {
@ -113,9 +119,9 @@ impl ObjSymbolFlagSet {
#[inline] #[inline]
pub fn set_force_active(&mut self, value: bool) { pub fn set_force_active(&mut self, value: bool) {
if value { if value {
self.0 |= ObjSymbolFlags::ForceActive; self.0 = (self.0 & !ObjSymbolFlags::NoExport) | ObjSymbolFlags::Exported;
} else { } else {
self.0 &= !ObjSymbolFlags::ForceActive; self.0 &= !ObjSymbolFlags::Exported;
} }
} }
@ -123,10 +129,11 @@ impl ObjSymbolFlagSet {
#[inline] #[inline]
pub fn keep_flags(&self) -> FlagSet<ObjSymbolFlags> { pub fn keep_flags(&self) -> FlagSet<ObjSymbolFlags> {
self.0 self.0
& (ObjSymbolFlags::ForceActive & (ObjSymbolFlags::Exported
| ObjSymbolFlags::NoWrite | ObjSymbolFlags::NoWrite
| ObjSymbolFlags::RelocationIgnore | ObjSymbolFlags::RelocationIgnore
| ObjSymbolFlags::Stripped) | ObjSymbolFlags::Stripped
| ObjSymbolFlags::NoExport)
} }
} }

View File

@ -249,7 +249,7 @@ impl ToWriter for CommentSym {
} }
impl CommentSym { impl CommentSym {
pub fn from(symbol: &ObjSymbol, force_active: bool) -> Self { pub fn from(symbol: &ObjSymbol, export_all: bool) -> Self {
let align = match symbol.align { let align = match symbol.align {
Some(align) => align, Some(align) => align,
None => { None => {
@ -277,8 +277,9 @@ impl CommentSym {
} }
let mut active_flags = 0; let mut active_flags = 0;
if !symbol.flags.is_stripped() if !symbol.flags.is_stripped()
&& (symbol.flags.is_force_active() && (symbol.flags.is_exported()
|| (force_active || (export_all
&& !symbol.flags.is_no_export()
&& matches!(symbol.kind, ObjSymbolKind::Function | ObjSymbolKind::Object))) && matches!(symbol.kind, ObjSymbolKind::Function | ObjSymbolKind::Object)))
{ {
active_flags |= 0x8; active_flags |= 0x8;

View File

@ -85,7 +85,7 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
ObjSymbol { name, demangled_name, address: addr as u64, section, ..Default::default() }; ObjSymbol { name, demangled_name, address: addr as u64, section, ..Default::default() };
// TODO move somewhere common // TODO move somewhere common
if symbol.name.starts_with("..") { if symbol.name.starts_with("..") {
symbol.flags.0 |= ObjSymbolFlags::ForceActive; symbol.flags.0 |= ObjSymbolFlags::Exported;
} }
let attrs = captures["attrs"].split(' '); let attrs = captures["attrs"].split(' ');
for attr in attrs { for attr in attrs {
@ -128,7 +128,7 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
symbol.flags.0 |= ObjSymbolFlags::Hidden; symbol.flags.0 |= ObjSymbolFlags::Hidden;
} }
"force_active" => { "force_active" => {
symbol.flags.0 |= ObjSymbolFlags::ForceActive; symbol.flags.0 |= ObjSymbolFlags::Exported;
} }
"stripped" => { "stripped" => {
symbol.flags.0 |= ObjSymbolFlags::Stripped; symbol.flags.0 |= ObjSymbolFlags::Stripped;
@ -147,6 +147,9 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
let addr = SectionAddress::new(section.unwrap(), symbol.address as u32); let addr = SectionAddress::new(section.unwrap(), symbol.address as u32);
obj.blocked_ranges.insert(addr, addr.address + symbol.size as u32); obj.blocked_ranges.insert(addr, addr.address + symbol.size as u32);
} }
"noexport" => {
symbol.flags.0 |= ObjSymbolFlags::NoExport;
}
_ => bail!("Unknown symbol attribute '{attr}'"), _ => bail!("Unknown symbol attribute '{attr}'"),
} }
} }
@ -281,6 +284,9 @@ where W: Write + ?Sized {
write!(w, " noreloc")?; write!(w, " noreloc")?;
} }
} }
if symbol.flags.is_no_export() {
write!(w, " noexport")?;
}
writeln!(w)?; writeln!(w)?;
Ok(()) Ok(())
} }

View File

@ -346,7 +346,7 @@ where P: AsRef<Path> {
Ok(obj) Ok(obj)
} }
pub fn write_elf(obj: &ObjInfo, force_active: bool) -> Result<Vec<u8>> { pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
let mut out_data = Vec::new(); let mut out_data = Vec::new();
let mut writer = object::write::elf::Writer::new(Endianness::Big, false, &mut out_data); let mut writer = object::write::elf::Writer::new(Endianness::Big, false, &mut out_data);
@ -540,7 +540,7 @@ pub fn write_elf(obj: &ObjInfo, force_active: bool) -> Result<Vec<u8>> {
out_symbols.push(OutSymbol { index, sym }); out_symbols.push(OutSymbol { index, sym });
symbol_map[symbol_index] = Some(index.0); symbol_map[symbol_index] = Some(index.0);
if let Some(comment_data) = &mut comment_data { if let Some(comment_data) = &mut comment_data {
CommentSym::from(symbol, force_active).to_writer_static(comment_data, Endian::Big)?; CommentSym::from(symbol, export_all).to_writer_static(comment_data, Endian::Big)?;
} }
} }

View File

@ -63,8 +63,7 @@ pub fn generate_ldscript(
let mut force_active = force_active.to_vec(); let mut force_active = force_active.to_vec();
for symbol in obj.symbols.iter() { for symbol in obj.symbols.iter() {
if symbol.flags.is_force_active() && symbol.flags.is_global() && !symbol.flags.is_no_write() if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
{
force_active.push(symbol.name.clone()); force_active.push(symbol.name.clone());
} }
} }
@ -98,8 +97,7 @@ pub fn generate_ldscript_partial(
let mut force_active = force_active.to_vec(); let mut force_active = force_active.to_vec();
for symbol in obj.symbols.iter() { for symbol in obj.symbols.iter() {
if symbol.flags.is_force_active() && symbol.flags.is_global() && !symbol.flags.is_no_write() if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
{
force_active.push(symbol.name.clone()); force_active.push(symbol.name.clone());
} }
} }

View File

@ -823,7 +823,7 @@ fn add_symbol(obj: &mut ObjInfo, symbol_entry: &SymbolEntry, section: Option<usi
}; };
// TODO move somewhere common // TODO move somewhere common
if symbol_entry.name.starts_with("..") { if symbol_entry.name.starts_with("..") {
flags |= ObjSymbolFlags::ForceActive; flags |= ObjSymbolFlags::Exported;
} }
if symbol_entry.unused { if symbol_entry.unused {
flags |= ObjSymbolFlags::Stripped; flags |= ObjSymbolFlags::Stripped;

View File

@ -563,7 +563,7 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
size: next_symbol_address - addr as u64, size: next_symbol_address - addr as u64,
size_known: true, size_known: true,
flags: ObjSymbolFlagSet( flags: ObjSymbolFlagSet(
ObjSymbolFlags::Local | ObjSymbolFlags::ForceActive | ObjSymbolFlags::NoWrite, ObjSymbolFlags::Local | ObjSymbolFlags::Exported | ObjSymbolFlags::NoWrite,
), ),
kind: match section.kind { kind: match section.kind {
ObjSectionKind::Code => ObjSymbolKind::Function, ObjSectionKind::Code => ObjSymbolKind::Function,
@ -616,7 +616,7 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
flags: ObjSymbolFlagSet( flags: ObjSymbolFlagSet(
ObjSymbolFlags::Global ObjSymbolFlags::Global
| ObjSymbolFlags::Hidden | ObjSymbolFlags::Hidden
| ObjSymbolFlags::ForceActive | ObjSymbolFlags::Exported
| ObjSymbolFlags::NoWrite, | ObjSymbolFlags::NoWrite,
), ),
kind: match section.kind { kind: match section.kind {