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

View File

@ -228,9 +228,9 @@ pub struct ProjectConfig {
/// Fills gaps between symbols to avoid linker realignment.
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
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")]
pub auto_force_active: bool,
pub export_all: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
@ -248,7 +248,7 @@ pub struct ModuleConfig {
pub symbols: Option<PathBuf>,
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
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")]
pub force_active: Vec<String>,
#[serde(skip_serializing_if = "is_default")]
@ -397,7 +397,7 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
section,
size: existing_symbol.size,
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,
align: existing_symbol.align,
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(),
address: address as u64,
section,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global | ObjSymbolFlags::ForceActive),
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global | ObjSymbolFlags::Exported),
..*symbol
},
false,
@ -574,7 +574,7 @@ fn update_symbols(
name,
address: rel_reloc.addend as u64,
section: Some(target_section_index),
flags: ObjSymbolFlagSet(ObjSymbolFlags::ForceActive.into()),
flags: ObjSymbolFlagSet(ObjSymbolFlags::Exported.into()),
..Default::default()
})?;
}
@ -862,7 +862,7 @@ fn split_write_obj(
entry,
};
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));
out_config.units.push(OutputUnit {
object: out_path.clone(),
@ -1766,7 +1766,7 @@ fn config(args: ConfigArgs) -> Result<()> {
common_start: None,
symbols_known: false,
fill_gaps: true,
auto_force_active: true,
export_all: true,
};
let mut modules = Vec::<(u32, ModuleConfig)>::new();

View File

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

View File

@ -249,7 +249,7 @@ impl ToWriter for 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 {
Some(align) => align,
None => {
@ -277,8 +277,9 @@ impl CommentSym {
}
let mut active_flags = 0;
if !symbol.flags.is_stripped()
&& (symbol.flags.is_force_active()
|| (force_active
&& (symbol.flags.is_exported()
|| (export_all
&& !symbol.flags.is_no_export()
&& matches!(symbol.kind, ObjSymbolKind::Function | ObjSymbolKind::Object)))
{
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() };
// TODO move somewhere common
if symbol.name.starts_with("..") {
symbol.flags.0 |= ObjSymbolFlags::ForceActive;
symbol.flags.0 |= ObjSymbolFlags::Exported;
}
let attrs = captures["attrs"].split(' ');
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;
}
"force_active" => {
symbol.flags.0 |= ObjSymbolFlags::ForceActive;
symbol.flags.0 |= ObjSymbolFlags::Exported;
}
"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);
obj.blocked_ranges.insert(addr, addr.address + symbol.size as u32);
}
"noexport" => {
symbol.flags.0 |= ObjSymbolFlags::NoExport;
}
_ => bail!("Unknown symbol attribute '{attr}'"),
}
}
@ -281,6 +284,9 @@ where W: Write + ?Sized {
write!(w, " noreloc")?;
}
}
if symbol.flags.is_no_export() {
write!(w, " noexport")?;
}
writeln!(w)?;
Ok(())
}

View File

@ -346,7 +346,7 @@ where P: AsRef<Path> {
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 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 });
symbol_map[symbol_index] = Some(index.0);
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();
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());
}
}
@ -98,8 +97,7 @@ pub fn generate_ldscript_partial(
let mut force_active = force_active.to_vec();
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());
}
}

View File

@ -823,7 +823,7 @@ fn add_symbol(obj: &mut ObjInfo, symbol_entry: &SymbolEntry, section: Option<usi
};
// TODO move somewhere common
if symbol_entry.name.starts_with("..") {
flags |= ObjSymbolFlags::ForceActive;
flags |= ObjSymbolFlags::Exported;
}
if symbol_entry.unused {
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_known: true,
flags: ObjSymbolFlagSet(
ObjSymbolFlags::Local | ObjSymbolFlags::ForceActive | ObjSymbolFlags::NoWrite,
ObjSymbolFlags::Local | ObjSymbolFlags::Exported | ObjSymbolFlags::NoWrite,
),
kind: match section.kind {
ObjSectionKind::Code => ObjSymbolKind::Function,
@ -616,7 +616,7 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
flags: ObjSymbolFlagSet(
ObjSymbolFlags::Global
| ObjSymbolFlags::Hidden
| ObjSymbolFlags::ForceActive
| ObjSymbolFlags::Exported
| ObjSymbolFlags::NoWrite,
),
kind: match section.kind {