Add alf support (NVIDIA Shield TV binaries)

- Supports .alf files in all places .dol files are accepted.
- Adds `hash` and `dhash` to symbols config.
This commit is contained in:
2023-10-07 02:03:09 -04:00
parent db506fb927
commit dfb569b883
21 changed files with 976 additions and 268 deletions

92
src/cmd/alf.rs Normal file
View File

@@ -0,0 +1,92 @@
use std::{
io::{stdout, Write},
path::PathBuf,
};
use anyhow::Result;
use argp::FromArgs;
use crate::{
cmd,
util::{
alf::AlfFile,
file::{buf_writer, map_file},
reader::{Endian, FromReader},
},
};
#[derive(FromArgs, PartialEq, Debug)]
/// Commands for processing NVIDIA Shield TV alf files.
#[argp(subcommand, name = "alf")]
pub struct Args {
#[argp(subcommand)]
command: SubCommand,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum SubCommand {
Info(InfoArgs),
Hashes(HashesArgs),
}
#[derive(FromArgs, PartialEq, Debug)]
/// Prints information about an alf file. (Same as `dol info`)
#[argp(subcommand, name = "info")]
pub struct InfoArgs {
#[argp(positional)]
/// alf file
file: PathBuf,
}
#[derive(FromArgs, PartialEq, Debug)]
/// Extracts symbol hashes from an alf file.
#[argp(subcommand, name = "hashes")]
pub struct HashesArgs {
#[argp(positional)]
/// alf file
alf_file: PathBuf,
#[argp(positional)]
/// output file
output: Option<PathBuf>,
}
pub fn run(args: Args) -> Result<()> {
match args.command {
SubCommand::Info(c_args) => info(c_args),
SubCommand::Hashes(c_args) => hashes(c_args),
}
}
fn hashes(args: HashesArgs) -> Result<()> {
let alf_file = {
let file = map_file(&args.alf_file)?;
let mut reader = file.as_reader();
AlfFile::from_reader(&mut reader, Endian::Little)?
};
let mut w: Box<dyn Write> = if let Some(output) = args.output {
Box::new(buf_writer(output)?)
} else {
Box::new(stdout())
};
let mut symbols = alf_file.symbols.clone();
symbols.sort_by_key(|s| s.address);
for symbol in symbols {
writeln!(
w,
"{:#010X} | {} | {:?} | {} | {} | {:#X}",
symbol.address,
symbol.section,
symbol.kind,
symbol.name,
symbol.demangled_name,
symbol.size
)?;
}
w.flush()?;
Ok(())
}
fn info(args: InfoArgs) -> Result<()> {
cmd::dol::info(cmd::dol::InfoArgs { dol_file: args.file, selfile: None })
}

View File

@@ -31,9 +31,8 @@ use crate::{
},
cmd::shasum::file_sha1_string,
obj::{
best_match_for_reloc, ObjDataKind, ObjInfo, ObjKind, ObjReloc, ObjRelocKind,
ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope,
SymbolIndex,
best_match_for_reloc, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSectionKind, ObjSymbol,
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope, SymbolIndex,
},
util::{
asm::write_asm,
@@ -79,10 +78,10 @@ enum SubCommand {
pub struct InfoArgs {
#[argp(positional)]
/// DOL file
dol_file: PathBuf,
pub dol_file: PathBuf,
#[argp(option, short = 's')]
/// optional path to selfile.sel
selfile: Option<PathBuf>,
pub selfile: Option<PathBuf>,
}
#[derive(FromArgs, PartialEq, Eq, Debug)]
@@ -366,6 +365,8 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
kind: existing_symbol.kind,
align: existing_symbol.align,
data_kind: existing_symbol.data_kind,
name_hash: existing_symbol.name_hash,
demangled_name_hash: existing_symbol.demangled_name_hash,
})?;
} else {
log::debug!("Creating symbol {} at {:#010X}", symbol.name, address);
@@ -385,7 +386,7 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
Ok(())
}
fn info(args: InfoArgs) -> Result<()> {
pub fn info(args: InfoArgs) -> Result<()> {
let mut obj = {
let file = map_file(&args.dol_file)?;
process_dol(file.as_slice(), "")?
@@ -523,15 +524,10 @@ fn update_symbols(obj: &mut ObjInfo, modules: &ModuleMap<'_>, create_symbols: bo
};
obj.symbols.add_direct(ObjSymbol {
name,
demangled_name: None,
address: rel_reloc.addend as u64,
section: Some(target_section_index),
size: 0,
size_known: false,
flags: ObjSymbolFlagSet(ObjSymbolFlags::ForceActive.into()),
kind: Default::default(),
align: None,
data_kind: ObjDataKind::Unknown,
..Default::default()
})?;
}
}
@@ -654,14 +650,7 @@ fn resolve_external_relocations(
let symbol_idx = obj.symbols.add_direct(ObjSymbol {
name: target_symbol.name.clone(),
demangled_name: target_symbol.demangled_name.clone(),
address: 0,
section: None,
size: 0,
size_known: false,
flags: Default::default(),
kind: Default::default(),
align: None,
data_kind: Default::default(),
..Default::default()
})?;
e.insert(symbol_idx);
@@ -1542,6 +1531,8 @@ fn apply(args: ApplyArgs) -> Result<()> {
kind: linked_sym.kind,
align: linked_sym.align,
data_kind: linked_sym.data_kind,
name_hash: linked_sym.name_hash,
demangled_name_hash: linked_sym.demangled_name_hash,
})?;
}
}

View File

@@ -1,3 +1,4 @@
pub mod alf;
pub mod ar;
pub mod demangle;
pub mod dol;

View File

@@ -471,8 +471,10 @@ fn merge(args: MergeArgs) -> Result<()> {
size_known: mod_symbol.size_known,
flags: mod_symbol.flags,
kind: mod_symbol.kind,
align: None,
data_kind: Default::default(),
align: mod_symbol.align,
data_kind: mod_symbol.data_kind,
name_hash: mod_symbol.name_hash,
demangled_name_hash: mod_symbol.demangled_name_hash,
})?;
}
offset += align32(mod_section.size as u32);
@@ -506,15 +508,9 @@ fn merge(args: MergeArgs) -> Result<()> {
// Create a new label
let symbol_idx = obj.symbols.add_direct(ObjSymbol {
name: String::new(),
demangled_name: None,
address: target_addr as u64,
section: Some(target_section_index),
size: 0,
size_known: false,
flags: Default::default(),
kind: Default::default(),
align: None,
data_kind: Default::default(),
..Default::default()
})?;
(symbol_idx, 0)
};