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:
Luke Street
2023-10-07 02:03:09 -04:00
parent db506fb927
commit dfb569b883
21 changed files with 976 additions and 268 deletions
+2 -7
View File
@@ -144,15 +144,12 @@ impl AnalyzerState {
obj.add_symbol(
ObjSymbol {
name,
demangled_name: None,
address: start.address as u64,
section: Some(start.section),
size: (end.address - start.address) as u64,
size_known: true,
flags: Default::default(),
kind: ObjSymbolKind::Function,
align: None,
data_kind: Default::default(),
..Default::default()
},
false,
)?;
@@ -188,15 +185,13 @@ impl AnalyzerState {
obj.add_symbol(
ObjSymbol {
name: format!("jumptable_{}", address_str),
demangled_name: None,
address: addr.address as u64,
section: Some(addr.section),
size: size as u64,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Local.into()),
kind: ObjSymbolKind::Object,
align: None,
data_kind: Default::default(),
..Default::default()
},
false,
)?;
+6 -30
View File
@@ -37,28 +37,20 @@ impl AnalysisPass for FindTRKInterruptVectorTable {
log::debug!("Found gTRKInterruptVectorTable @ {:#010X}", start);
state.known_symbols.insert(start, ObjSymbol {
name: "gTRKInterruptVectorTable".to_string(),
demangled_name: None,
address: start.address as u64,
section: Some(start.section),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(FlagSet::from(ObjSymbolFlags::Global)),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
..Default::default()
});
let end = start + TRK_TABLE_SIZE;
state.known_symbols.insert(end, ObjSymbol {
name: "gTRKInterruptVectorTableEnd".to_string(),
demangled_name: None,
address: end.address as u64,
section: Some(start.section),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(FlagSet::from(ObjSymbolFlags::Global)),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
..Default::default()
});
return Ok(());
@@ -96,29 +88,23 @@ impl AnalysisPass for FindSaveRestSleds {
});
state.known_symbols.insert(start, ObjSymbol {
name: func.to_string(),
demangled_name: None,
address: start.address as u64,
section: Some(start.section),
size: SLED_SIZE as u64,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Function,
align: None,
data_kind: Default::default(),
..Default::default()
});
for i in 14..=31 {
let addr = start + (i - 14) * 4;
state.known_symbols.insert(addr, ObjSymbol {
name: format!("{}{}", label, i),
demangled_name: None,
address: addr.address as u64,
section: Some(start.section),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
..Default::default()
});
}
}
@@ -202,30 +188,20 @@ impl AnalysisPass for FindRelCtorsDtors {
state.known_sections.insert(ctors_section_index, ".ctors".to_string());
state.known_symbols.insert(SectionAddress::new(ctors_section_index, 0), ObjSymbol {
name: "_ctors".to_string(),
demangled_name: None,
address: 0,
section: Some(ctors_section_index),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: Default::default(),
align: None,
data_kind: Default::default(),
..Default::default()
});
let dtors_section_index = possible_sections[1].0;
state.known_sections.insert(dtors_section_index, ".dtors".to_string());
state.known_symbols.insert(SectionAddress::new(dtors_section_index, 0), ObjSymbol {
name: "_dtors".to_string(),
demangled_name: None,
address: 0,
section: Some(dtors_section_index),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: Default::default(),
align: None,
data_kind: Default::default(),
..Default::default()
});
// Check for duplicate entries in .dtors, indicating __destroy_global_chain_reference
+5 -19
View File
@@ -245,15 +245,13 @@ fn apply_ctors_signatures(obj: &mut ObjInfo) -> Result<()> {
obj.symbols.add(
ObjSymbol {
name: "__init_cpp_exceptions_reference".to_string(),
demangled_name: None,
address,
section: Some(ctors_section_index),
size: 4,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global | ObjSymbolFlags::RelocationIgnore),
kind: ObjSymbolKind::Object,
align: None,
data_kind: Default::default(),
..Default::default()
},
true,
)?;
@@ -303,7 +301,6 @@ fn apply_dtors_signatures(obj: &mut ObjInfo) -> Result<()> {
obj.add_symbol(
ObjSymbol {
name: "__destroy_global_chain_reference".to_string(),
demangled_name: None,
address,
section: Some(dtors_section_index),
size: 4,
@@ -312,8 +309,7 @@ fn apply_dtors_signatures(obj: &mut ObjInfo) -> Result<()> {
ObjSymbolFlags::Global | ObjSymbolFlags::RelocationIgnore,
),
kind: ObjSymbolKind::Object,
align: None,
data_kind: Default::default(),
..Default::default()
},
true,
)?;
@@ -334,7 +330,6 @@ fn apply_dtors_signatures(obj: &mut ObjInfo) -> Result<()> {
obj.add_symbol(
ObjSymbol {
name: "__fini_cpp_exceptions_reference".to_string(),
demangled_name: None,
address: address + 4,
section: Some(dtors_section_index),
size: 4,
@@ -343,8 +338,7 @@ fn apply_dtors_signatures(obj: &mut ObjInfo) -> Result<()> {
ObjSymbolFlags::Global | ObjSymbolFlags::RelocationIgnore,
),
kind: ObjSymbolKind::Object,
align: None,
data_kind: Default::default(),
..Default::default()
},
true,
)?;
@@ -452,15 +446,11 @@ pub fn update_ctors_dtors(obj: &mut ObjInfo) -> Result<()> {
if let Some((section_index, section)) = obj.sections.by_name(".ctors")? {
obj.symbols.add_direct(ObjSymbol {
name: "_ctors".to_string(),
demangled_name: None,
address: section.address,
section: Some(section_index),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
..Default::default()
})?;
}
}
@@ -468,15 +458,11 @@ pub fn update_ctors_dtors(obj: &mut ObjInfo) -> Result<()> {
if let Some((section_index, section)) = obj.sections.by_name(".dtors")? {
obj.symbols.add_direct(ObjSymbol {
name: "_dtors".to_string(),
demangled_name: None,
address: section.address,
section: Some(section_index),
size: 0,
size_known: true,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
..Default::default()
})?;
}
}
+1 -6
View File
@@ -710,15 +710,10 @@ impl Tracker {
};
let symbol_idx = obj.symbols.add_direct(ObjSymbol {
name,
demangled_name: None,
address: target.address as u64,
section: Some(target.section),
size: 0,
size_known: false,
flags: Default::default(),
kind: Default::default(),
align: None,
data_kind,
..Default::default()
})?;
(symbol_idx, 0)
};
+92
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 })
}
+11 -20
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,
})?;
}
}
+1
View File
@@ -1,3 +1,4 @@
pub mod alf;
pub mod ar;
pub mod demangle;
pub mod dol;
+5 -9
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)
};
+2
View File
@@ -74,6 +74,7 @@ struct TopLevel {
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum SubCommand {
Alf(cmd::alf::Args),
Ar(cmd::ar::Args),
Demangle(cmd::demangle::Args),
Dol(cmd::dol::Args),
@@ -122,6 +123,7 @@ fn main() {
});
}
result = result.and_then(|_| match args.command {
SubCommand::Alf(c_args) => cmd::alf::run(c_args),
SubCommand::Ar(c_args) => cmd::ar::run(c_args),
SubCommand::Demangle(c_args) => cmd::demangle::run(c_args),
SubCommand::Dol(c_args) => cmd::dol::run(c_args),
+7
View File
@@ -165,6 +165,9 @@ pub struct ObjSymbol {
pub kind: ObjSymbolKind,
pub align: Option<u32>,
pub data_kind: ObjDataKind,
/// ALF hashes
pub name_hash: Option<u32>,
pub demangled_name_hash: Option<u32>,
}
pub type SymbolIndex = usize;
@@ -263,6 +266,8 @@ impl ObjSymbols {
ObjDataKind::Unknown => existing.data_kind,
kind => kind,
},
name_hash: in_symbol.name_hash.or(existing.name_hash),
demangled_name_hash: in_symbol.demangled_name_hash.or(existing.demangled_name_hash),
};
if existing != &new_symbol {
log::debug!("Replacing {:?} with {:?}", existing, new_symbol);
@@ -282,6 +287,8 @@ impl ObjSymbols {
kind: in_symbol.kind,
align: in_symbol.align,
data_kind: in_symbol.data_kind,
name_hash: in_symbol.name_hash,
demangled_name_hash: in_symbol.demangled_name_hash,
})?;
target_symbol_idx
};
+274
View File
@@ -0,0 +1,274 @@
use std::{
io,
io::{Read, Seek, SeekFrom},
};
use anyhow::Result;
use io::{Error, ErrorKind};
use crate::{
obj::{ObjSymbol, ObjSymbolKind},
util::{
dol::{DolLike, DolSection, DolSectionKind},
reader::{
read_string, read_vec, read_vec_args, struct_size, Endian, FromReader, DYNAMIC_SIZE,
},
},
};
pub const ALF_MAGIC: [u8; 4] = *b"RBOF";
#[derive(Debug, Clone)]
pub struct AlfFile {
pub header: AlfHeader,
pub sections: Vec<DolSection>,
pub symbols: Vec<AlfSymbol>,
}
impl FromReader for AlfFile {
type Args = ();
const STATIC_SIZE: usize = DYNAMIC_SIZE;
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let header = AlfHeader::from_reader(reader, e)?;
if !matches!(header.version, 104 | 105) {
return Err(Error::new(
ErrorKind::InvalidData,
format!("unsupported ALF version: {}", header.version),
));
}
let alf_sections: Vec<AlfSection> = read_vec(reader, header.section_count as usize, e)?;
let symtab =
AlfSymTab::from_reader_args(reader, e, AlfVersionArgs { version: header.version })?;
// Infer section types from data size and symbol typeFs
let mut sections = Vec::with_capacity(alf_sections.len());
for section in &alf_sections {
let kind =
if section.data_size == 0 { DolSectionKind::Bss } else { DolSectionKind::Data };
sections.push(DolSection {
address: section.address,
file_offset: section.file_offset,
data_size: section.data_size,
size: section.size,
kind,
index: sections.len(),
});
}
for sym in &symtab.symbols {
// Section IDs are 1-based
if sym.section == 0 {
return Err(Error::new(ErrorKind::InvalidData, "invalid ALF symbol section"));
}
if sym.kind == AlfSymbolKind::Function {
sections[sym.section as usize - 1].kind = DolSectionKind::Text;
}
}
Ok(Self { header, sections, symbols: symtab.symbols })
}
}
impl DolLike for AlfFile {
fn sections(&self) -> &[DolSection] { &self.sections }
fn symbols(&self) -> &[AlfSymbol] { &self.symbols }
fn entry_point(&self) -> u32 { self.header.entry }
fn has_unified_bss(&self) -> bool { false }
}
#[derive(Debug, Clone)]
pub struct AlfHeader {
pub version: u32,
pub entry: u32,
pub section_count: u32,
}
impl FromReader for AlfHeader {
type Args = ();
const STATIC_SIZE: usize = struct_size([
4, // magic
u32::STATIC_SIZE, // version
u32::STATIC_SIZE, // entry
u32::STATIC_SIZE, // section_count
]);
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
if <[u8; 4]>::from_reader(reader, e)? != ALF_MAGIC {
return Err(Error::new(ErrorKind::InvalidData, "invalid ALF magic"));
}
Ok(Self {
version: <_>::from_reader(reader, e)?,
entry: <_>::from_reader(reader, e)?,
section_count: <_>::from_reader(reader, e)?,
})
}
}
#[derive(Debug, Clone)]
pub struct AlfSection {
pub address: u32,
pub data_size: u32,
pub size: u32,
pub file_offset: u32,
}
impl FromReader for AlfSection {
type Args = ();
const STATIC_SIZE: usize = struct_size([
u32::STATIC_SIZE, // address
u32::STATIC_SIZE, // data_size
u32::STATIC_SIZE, // size
]);
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let result = Self {
address: <_>::from_reader(reader, e)?,
data_size: <_>::from_reader(reader, e)?,
size: <_>::from_reader(reader, e)?,
file_offset: reader.stream_position()? as u32,
};
reader.seek(SeekFrom::Current(result.data_size as i64))?;
Ok(result)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AlfSymbolKind {
Function,
Object,
}
impl FromReader for AlfSymbolKind {
type Args = ();
const STATIC_SIZE: usize = u32::STATIC_SIZE;
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
match u32::from_reader(reader, e)? {
0 => Ok(Self::Function),
1 => Ok(Self::Object),
v => Err(Error::new(ErrorKind::InvalidData, format!("invalid ALF symbol kind: {}", v))),
}
}
}
#[derive(Debug, Clone)]
pub struct AlfSymbol {
pub name: String,
pub demangled_name: String,
pub address: u32,
pub size: u32,
pub kind: AlfSymbolKind,
pub section: u32,
pub unk: u32,
}
#[derive(Copy, Clone)]
pub struct AlfVersionArgs {
pub version: u32,
}
impl FromReader for AlfSymbol {
type Args = AlfVersionArgs;
const STATIC_SIZE: usize = DYNAMIC_SIZE;
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
Ok(Self {
name: read_string::<u32, _>(reader, e)?,
demangled_name: read_string::<u32, _>(reader, e)?,
address: <_>::from_reader(reader, e)?,
size: <_>::from_reader(reader, e)?,
kind: <_>::from_reader(reader, e)?,
section: <_>::from_reader(reader, e)?,
unk: if args.version >= 105 { <_>::from_reader(reader, e)? } else { 0 },
})
}
}
impl AlfSymbol {
pub fn to_obj_symbol(&self) -> Result<ObjSymbol> {
let kind = match self.kind {
AlfSymbolKind::Function => ObjSymbolKind::Function,
AlfSymbolKind::Object => ObjSymbolKind::Object,
};
let (name, name_hash) = if self.name.starts_with('#') {
let hash_str = self.name.trim_start_matches('#');
let hash = u32::from_str_radix(hash_str, 16)?;
let name = match self.kind {
AlfSymbolKind::Function => format!("fn_{:08X}", self.address),
AlfSymbolKind::Object => format!("lbl_{:08X}", self.address),
};
(name, Some(hash))
} else {
(self.name.clone(), None)
};
let (demangled_name, demangled_name_hash) = if self.demangled_name.starts_with('#') {
let hash_str = self.demangled_name.trim_start_matches('#');
let hash = u32::from_str_radix(hash_str, 16)?;
(None, Some(hash))
} else {
(Some(self.demangled_name.clone()), None)
};
Ok(ObjSymbol {
name,
demangled_name,
address: self.address as u64,
section: Some(self.section as usize - 1),
size: self.size as u64,
size_known: true,
flags: Default::default(),
kind,
align: None,
data_kind: Default::default(),
name_hash,
demangled_name_hash,
})
}
}
#[derive(Debug)]
pub struct AlfSymTab {
pub symbols: Vec<AlfSymbol>,
}
impl FromReader for AlfSymTab {
type Args = AlfVersionArgs;
const STATIC_SIZE: usize = DYNAMIC_SIZE;
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let _size = u32::from_reader(reader, e)?;
let count = u32::from_reader(reader, e)? as usize;
let symbols = read_vec_args(reader, count, e, args)?;
Ok(Self { symbols })
}
}
pub const ALF_HASH_SEED: u32 = 0x1505;
pub fn alf_hash(mut h: u32, s: &str) -> u32 {
for c in s.bytes() {
h *= 33;
h ^= c as u32;
}
h
}
+23 -13
View File
@@ -75,18 +75,8 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
bail!("Section {} not found", section_name)
};
let demangled_name = demangle(&name, &DemangleOptions::default());
let mut symbol = ObjSymbol {
name,
demangled_name,
address: addr as u64,
section,
size: 0,
size_known: false,
flags: Default::default(),
kind: ObjSymbolKind::Unknown,
align: None,
data_kind: Default::default(),
};
let mut symbol =
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;
@@ -114,6 +104,16 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
symbol.data_kind = symbol_data_kind_from_str(value)
.ok_or_else(|| anyhow!("Unknown symbol data type '{}'", value))?;
}
"hash" => {
let hash = parse_hex(value)?;
symbol.name_hash = Some(hash);
if symbol.demangled_name_hash.is_none() {
symbol.demangled_name_hash = Some(hash);
}
}
"dhash" => {
symbol.demangled_name_hash = Some(parse_hex(value)?);
}
_ => bail!("Unknown symbol attribute '{name}'"),
}
} else {
@@ -163,7 +163,9 @@ pub fn is_skip_symbol(symbol: &ObjSymbol) -> bool {
}
pub fn is_auto_symbol(symbol: &ObjSymbol) -> bool {
symbol.name.starts_with("lbl_") || symbol.name.starts_with("fn_")
symbol.name.starts_with("lbl_")
|| symbol.name.starts_with("fn_")
|| symbol.name.starts_with("jumptable_")
}
#[inline]
@@ -204,6 +206,14 @@ fn write_symbol<W: Write>(w: &mut W, obj: &ObjInfo, symbol: &ObjSymbol) -> Resul
if let Some(kind) = symbol_data_kind_to_str(symbol.data_kind) {
write!(w, " data:{kind}")?;
}
if let Some(hash) = symbol.name_hash {
write!(w, " hash:{:#010X}", hash)?;
}
if let Some(hash) = symbol.demangled_name_hash {
if symbol.name_hash != symbol.demangled_name_hash {
write!(w, " dhash:{:#010X}", hash)?;
}
}
if symbol.flags.is_hidden() {
write!(w, " hidden")?;
}
+286 -138
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -816,7 +816,7 @@ fn to_obj_symbol(
_ => bail!("Unsupported symbol kind: {:?}", symbol),
},
align,
data_kind: Default::default(),
..Default::default()
})
}
+1 -1
View File
@@ -688,7 +688,7 @@ fn add_symbol(obj: &mut ObjInfo, symbol_entry: &SymbolEntry, section: Option<usi
SymbolKind::NoType => ObjSymbolKind::Unknown,
},
align: symbol_entry.align,
data_kind: Default::default(),
..Default::default()
},
true,
)?;
+2
View File
@@ -1,5 +1,6 @@
use std::{borrow::Cow, ops::Deref};
pub mod alf;
pub mod asm;
pub mod comment;
pub mod config;
@@ -12,6 +13,7 @@ pub mod lcf;
pub mod map;
pub mod nested;
pub mod rarc;
pub mod reader;
pub mod rel;
pub mod rso;
pub mod signatures;
+249
View File
@@ -0,0 +1,249 @@
use std::{
io,
io::{Error, ErrorKind, Read, Seek, SeekFrom},
};
use io::Write;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Endian {
Big,
Little,
}
pub const DYNAMIC_SIZE: usize = 0;
pub const fn struct_size<const N: usize>(fields: [usize; N]) -> usize {
let mut result = 0;
let mut i = 0;
while i < N {
let size = fields[i];
if size == DYNAMIC_SIZE {
// Dynamically sized
return DYNAMIC_SIZE;
}
result += size;
i += 1;
}
result
}
#[inline]
pub fn skip_bytes<const N: usize, R>(reader: &mut R) -> io::Result<()>
where R: Read + Seek + ?Sized {
reader.seek(SeekFrom::Current(N as i64))?;
Ok(())
}
pub trait FromReader: Sized {
type Args;
const STATIC_SIZE: usize;
fn from_reader_args<R>(reader: &mut R, e: Endian, args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized;
fn from_reader<R>(reader: &mut R, e: Endian) -> io::Result<Self>
where
R: Read + Seek + ?Sized,
Self::Args: Default,
{
Self::from_reader_args(reader, e, Default::default())
}
}
macro_rules! impl_from_reader {
($($t:ty),*) => {
$(
impl FromReader for $t {
const STATIC_SIZE: usize = std::mem::size_of::<Self>();
type Args = ();
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let mut buf = [0u8; Self::STATIC_SIZE];
reader.read_exact(&mut buf)?;
Ok(match e {
Endian::Big => Self::from_be_bytes(buf),
Endian::Little => Self::from_le_bytes(buf),
})
}
}
)*
};
}
impl_from_reader!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
impl<const N: usize> FromReader for [u8; N] {
type Args = ();
const STATIC_SIZE: usize = N;
#[inline]
fn from_reader_args<R>(reader: &mut R, _e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let mut buf = [0u8; N];
reader.read_exact(&mut buf)?;
Ok(buf)
}
}
impl<const N: usize> FromReader for [u32; N] {
type Args = ();
const STATIC_SIZE: usize = N * u32::STATIC_SIZE;
#[inline]
fn from_reader_args<R>(reader: &mut R, e: Endian, _args: Self::Args) -> io::Result<Self>
where R: Read + Seek + ?Sized {
let mut buf = [0u32; N];
reader.read_exact(unsafe {
std::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, Self::STATIC_SIZE)
})?;
if e == Endian::Big {
for x in buf.iter_mut() {
*x = u32::from_be(*x);
}
}
Ok(buf)
}
}
#[inline]
pub fn read_bytes<R>(reader: &mut R, count: usize) -> io::Result<Vec<u8>>
where R: Read + Seek + ?Sized {
let mut buf = vec![0u8; count];
reader.read_exact(&mut buf)?;
Ok(buf)
}
#[inline]
pub fn read_vec<T, R>(reader: &mut R, count: usize, e: Endian) -> io::Result<Vec<T>>
where
T: FromReader,
T::Args: Default,
R: Read + Seek + ?Sized,
{
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(T::from_reader(reader, e)?);
}
Ok(vec)
}
#[inline]
pub fn read_vec_args<T, R>(
reader: &mut R,
count: usize,
e: Endian,
args: T::Args,
) -> io::Result<Vec<T>>
where
T: FromReader,
T::Args: Clone,
R: Read + Seek + ?Sized,
{
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(T::from_reader_args(reader, e, args.clone())?);
}
Ok(vec)
}
#[inline]
pub fn read_string<T, R>(reader: &mut R, e: Endian) -> io::Result<String>
where
T: FromReader + TryInto<usize>,
T::Args: Default,
R: Read + Seek + ?Sized,
{
let len = <T>::from_reader(reader, e)?
.try_into()
.map_err(|_| Error::new(ErrorKind::InvalidData, "invalid string length"))?;
let mut buf = vec![0u8; len];
reader.read_exact(&mut buf)?;
String::from_utf8(buf).map_err(|e| Error::new(ErrorKind::InvalidData, e))
}
pub trait ToWriter: Sized {
fn to_writer<W>(&self, writer: &mut W, e: Endian) -> io::Result<()>
where W: Write + ?Sized;
fn to_bytes(&self, e: Endian) -> io::Result<Vec<u8>> {
let mut buf = vec![0u8; self.write_size()];
self.to_writer(&mut buf.as_mut_slice(), e)?;
Ok(buf)
}
fn write_size(&self) -> usize;
}
macro_rules! impl_to_writer {
($($t:ty),*) => {
$(
impl ToWriter for $t {
fn to_writer<W>(&self, writer: &mut W, e: Endian) -> io::Result<()>
where W: Write + ?Sized {
writer.write_all(&match e {
Endian::Big => self.to_be_bytes(),
Endian::Little => self.to_le_bytes(),
})
}
fn to_bytes(&self, e: Endian) -> io::Result<Vec<u8>> {
Ok(match e {
Endian::Big => self.to_be_bytes(),
Endian::Little => self.to_le_bytes(),
}.to_vec())
}
fn write_size(&self) -> usize {
std::mem::size_of::<Self>()
}
}
)*
};
}
impl_to_writer!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
impl<const N: usize> ToWriter for [u8; N] {
fn to_writer<W>(&self, writer: &mut W, _e: Endian) -> io::Result<()>
where W: Write + ?Sized {
writer.write_all(self)
}
fn write_size(&self) -> usize { N }
}
impl ToWriter for &[u8] {
fn to_writer<W>(&self, writer: &mut W, _e: Endian) -> io::Result<()>
where W: Write + ?Sized {
writer.write_all(self)
}
fn write_size(&self) -> usize { self.len() }
}
impl ToWriter for Vec<u8> {
fn to_writer<W>(&self, writer: &mut W, _e: Endian) -> io::Result<()>
where W: Write + ?Sized {
writer.write_all(self)
}
fn write_size(&self) -> usize { self.len() }
}
pub fn write_vec<T, W>(writer: &mut W, vec: &[T], e: Endian) -> io::Result<()>
where
T: ToWriter,
W: Write + ?Sized,
{
for item in vec {
item.to_writer(writer, e)?;
}
Ok(())
}
+1 -5
View File
@@ -232,15 +232,11 @@ pub fn process_rel<R: Read + Seek>(reader: &mut R, name: &str) -> Result<(RelHea
}
symbols.push(ObjSymbol {
name: name.to_string(),
demangled_name: None,
address: offset as u64,
section: Some(section_index),
size: 0,
size_known: false,
flags,
kind: ObjSymbolKind::Function,
align: None,
data_kind: Default::default(),
..Default::default()
});
}
Ok(())
+2 -11
View File
@@ -128,15 +128,11 @@ pub fn process_rso<R: Read + Seek>(reader: &mut R) -> Result<ObjInfo> {
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
symbols.push(ObjSymbol {
name: name.to_string(),
demangled_name: None,
address: offset as u64,
section: Some(section_index),
size: 0,
size_known: false,
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Function,
align: None,
data_kind: Default::default(),
..Default::default()
});
}
Ok(())
@@ -196,12 +192,7 @@ pub fn process_rso<R: Read + Seek>(reader: &mut R) -> Result<ObjInfo> {
demangled_name,
address: sym_off as u64,
section: Some(section),
size: 0,
size_known: false,
flags: Default::default(),
kind: Default::default(),
align: None,
data_kind: Default::default(),
..Default::default()
});
}
reader.seek(SeekFrom::Start(import_table_offset as u64))?;
+1 -2
View File
@@ -142,8 +142,7 @@ pub fn apply_symbol(
size_known: sig_symbol.size > 0 || sig_symbol.kind == ObjSymbolKind::Unknown,
flags: sig_symbol.flags,
kind: sig_symbol.kind,
align: None,
data_kind: Default::default(),
..Default::default()
},
false,
)?;

Some files were not shown because too many files have changed in this diff Show More