schnauzer 0.3.5

Library for parsing Mach-O files
Documentation
use super::common;
use super::common::options::AddToOptions;
use super::common::ObjectFilter;
use super::handler;
use super::handler::*;
use super::Printer;
use super::Result;
use crate::*;
use colored::*;

mod config;
use config::*;
use getopts::Options;

static SUBCOMM_NAME: &str = "data";

pub(super) struct DataHandler {
    printer: Printer,
}

impl DataHandler {
    pub(super) fn new(printer: Printer) -> Self {
        Self { printer }
    }
}

impl Handler for DataHandler {
    fn command_name(&self) -> String {
        SUBCOMM_NAME.to_string()
    }

    fn description(&self) -> String {
        "Prints hex dump".to_string()
    }

    fn can_handle_with_name(&self, name: &str) -> bool {
        SUBCOMM_NAME == name
    }

    fn handle_object(&self, object: ObjectType, other_args: Vec<String>) -> Result<()> {
        let mut opts = Options::new();
        self.accepted_option_items().add_to_opts(&mut opts);
        let config = Config::build(&mut opts, &other_args)?;
        let filter = ObjectFilter::build(&mut opts, &other_args)?;

        let objects = &filter.get_objects(object);
        let out_arch = objects.len() > 1;
        for (idx, obj) in objects.iter().enumerate() {
            if out_arch {
                common::out_single_arch_title(
                    &self.printer,
                    &obj.header(),
                    idx,
                    false,
                );
            }
            self.handle_load_commands(obj.load_commands_iterator(), &config);
        }

        Ok(())
    }

    fn accepted_option_items(&self) -> Vec<common::options::OptionItem> {
        let mut items = handler::default_option_items();
        items.append(&mut Config::option_items());
        items
    }
}

impl DataHandler {
    fn handle_load_commands(&self, commands: LoadCommandIterator, config: &Config) {
        let segs = commands.filter_map(|cmd| match cmd.variant {
            LcVariant::Segment32(s) | LcVariant::Segment64(s) => {
                if s.segname.to_string() == config.seg {
                    Some(s)
                } else {
                    None
                }
            }
            _ => None,
        });

        let sections: Vec<Section> = segs.filter_map(|seg| {
            seg.sections_iterator()
                .find(|s| s.sectname.to_string() == config.sect)
        }).collect();

        if sections.len() == 0 {
            println!("{}\n", "Section not found".dimmed());
        }

        for sect in sections {
            self.handle_section(sect);
            print!("\n\n")
        }
    }

    fn handle_section(&self, sect: Section) {
        use crate::output::hex::*;
        println!("{} {}", sect.segname.to_string().yellow(), sect.sectname.to_string().yellow());
        if sect.size.0 == 0 {
            println!("{}\n", "No data in section".dimmed());
        }
        dump_section(&sect).unwrap();
    }
}