163 lines
5.2 KiB
Rust
163 lines
5.2 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use anyhow::{bail, ensure, Result};
|
|
use argp::FromArgs;
|
|
use cwdemangle::{demangle, DemangleOptions};
|
|
|
|
use crate::util::{
|
|
file::map_file,
|
|
map::{process_map, SymbolEntry, SymbolRef},
|
|
};
|
|
|
|
#[derive(FromArgs, PartialEq, Debug)]
|
|
/// Commands for processing CodeWarrior maps.
|
|
#[argp(subcommand, name = "map")]
|
|
pub struct Args {
|
|
#[argp(subcommand)]
|
|
command: SubCommand,
|
|
}
|
|
|
|
#[derive(FromArgs, PartialEq, Debug)]
|
|
#[argp(subcommand)]
|
|
enum SubCommand {
|
|
Entries(EntriesArgs),
|
|
Symbol(SymbolArgs),
|
|
}
|
|
|
|
#[derive(FromArgs, PartialEq, Eq, Debug)]
|
|
/// Displays all entries for a particular TU.
|
|
#[argp(subcommand, name = "entries")]
|
|
pub struct EntriesArgs {
|
|
#[argp(positional)]
|
|
/// path to input map
|
|
map_file: PathBuf,
|
|
#[argp(positional)]
|
|
/// TU to display entries for
|
|
unit: String,
|
|
}
|
|
|
|
#[derive(FromArgs, PartialEq, Eq, Debug)]
|
|
/// Displays all references to a symbol.
|
|
#[argp(subcommand, name = "symbol")]
|
|
pub struct SymbolArgs {
|
|
#[argp(positional)]
|
|
/// path to input map
|
|
map_file: PathBuf,
|
|
#[argp(positional)]
|
|
/// symbol to display references for
|
|
symbol: String,
|
|
}
|
|
|
|
pub fn run(args: Args) -> Result<()> {
|
|
match args.command {
|
|
SubCommand::Entries(c_args) => entries(c_args),
|
|
SubCommand::Symbol(c_args) => symbol(c_args),
|
|
}
|
|
}
|
|
|
|
fn entries(args: EntriesArgs) -> Result<()> {
|
|
let file = map_file(&args.map_file)?;
|
|
let entries = process_map(&mut file.as_reader())?;
|
|
match entries.unit_entries.get_vec(&args.unit) {
|
|
Some(vec) => {
|
|
println!("Entries for {}:", args.unit);
|
|
for symbol_ref in vec {
|
|
if symbol_ref.name.starts_with('@') {
|
|
continue;
|
|
}
|
|
if let Some((section, entry)) = entries.get_section_symbol(symbol_ref) {
|
|
println!(
|
|
">>> {} ({:?},{:?}) @ {}:{:#010X} [{}]",
|
|
entry.demangled.as_ref().unwrap_or(&entry.name),
|
|
entry.kind,
|
|
entry.visibility,
|
|
section,
|
|
entry.address,
|
|
entry.unit.as_deref().unwrap_or("(generated)"),
|
|
);
|
|
} else {
|
|
let demangled = demangle(&symbol_ref.name, &DemangleOptions::default());
|
|
println!(">>> {}", demangled.as_deref().unwrap_or(&symbol_ref.name));
|
|
}
|
|
}
|
|
}
|
|
None => bail!("Failed to find entries for TU '{}' in map", args.unit),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn symbol(args: SymbolArgs) -> Result<()> {
|
|
let file = map_file(&args.map_file)?;
|
|
log::info!("Processing map...");
|
|
let entries = process_map(&mut file.as_reader())?;
|
|
log::info!("Done!");
|
|
let mut opt_ref: Option<(String, SymbolEntry)> = None;
|
|
|
|
for (section, symbol_map) in &entries.section_symbols {
|
|
for symbol_entry in symbol_map.values().flatten() {
|
|
if symbol_entry.name == args.symbol {
|
|
ensure!(opt_ref.is_none(), "Found multiple symbols with name '{}'", args.symbol);
|
|
opt_ref = Some((section.clone(), symbol_entry.clone()));
|
|
}
|
|
}
|
|
}
|
|
let Some((section, symbol)) = opt_ref else {
|
|
bail!("Failed to find symbol '{}' in map", args.symbol);
|
|
};
|
|
|
|
println!(
|
|
"Located symbol {} ({:?},{:?}) @ {}:{:#010X} [{}]",
|
|
symbol.demangled.as_ref().unwrap_or(&symbol.name),
|
|
symbol.kind,
|
|
symbol.visibility,
|
|
section,
|
|
symbol.address,
|
|
symbol.unit.as_deref().unwrap_or("(generated)"),
|
|
);
|
|
let symbol_ref = SymbolRef { name: symbol.name.clone(), unit: symbol.unit.clone() };
|
|
if let Some(vec) = entries.entry_references.get_vec(&symbol_ref) {
|
|
println!("\nKnown references:");
|
|
for x in vec {
|
|
if let Some((section, entry)) = entries.get_section_symbol(x) {
|
|
println!(
|
|
">>> {} ({:?},{:?}) @ {}:{:#010X} [{}]",
|
|
entry.demangled.as_ref().unwrap_or(&entry.name),
|
|
entry.kind,
|
|
entry.visibility,
|
|
section,
|
|
entry.address,
|
|
entry.unit.as_deref().unwrap_or("(generated)"),
|
|
);
|
|
} else {
|
|
println!(">>> {} (NOT FOUND)", x.name);
|
|
}
|
|
}
|
|
}
|
|
if let Some(vec) = entries.entry_referenced_from.get_vec(&symbol_ref) {
|
|
println!("\nKnown referenced from:");
|
|
for x in vec {
|
|
if let Some((section, entry)) = entries.get_section_symbol(x) {
|
|
println!(
|
|
">>> {} ({:?}, {:?}) @ {}:{:#010X} [{}]",
|
|
entry.demangled.as_ref().unwrap_or(&entry.name),
|
|
entry.kind,
|
|
entry.visibility,
|
|
section,
|
|
entry.address,
|
|
entry.unit.as_deref().unwrap_or("(generated)"),
|
|
);
|
|
} else {
|
|
println!(">>> {} (NOT FOUND)", x.name);
|
|
}
|
|
}
|
|
}
|
|
if let Some(vec) = entries.unit_references.get_vec(&symbol_ref) {
|
|
println!("\nGenerated in TUs:");
|
|
for x in vec {
|
|
println!(">>> {}", x);
|
|
}
|
|
}
|
|
println!("\n");
|
|
Ok(())
|
|
}
|