schnauzer/commands/
rel.rs

1use super::common;
2use super::common::options::AddToOptions;
3use super::common::ObjectFilter;
4use super::handler::*;
5use super::Printer;
6use super::Result;
7use crate::*;
8use colored::*;
9use getopts::*;
10
11static SUBCOMM_NAME: &str = "rel";
12
13pub(super) struct RelHandler {
14    pub(super) printer: Printer,
15}
16
17impl RelHandler {
18    pub(super) fn new(printer: Printer) -> Self {
19        RelHandler { printer }
20    }
21}
22
23impl Handler for RelHandler {
24    fn command_name(&self) -> String {
25        SUBCOMM_NAME.to_string()
26    }
27
28    fn description(&self) -> String {
29        "Prints relocation entries".to_string()
30    }
31
32    fn can_handle_with_name(&self, name: &str) -> bool {
33        SUBCOMM_NAME == name
34    }
35
36    fn handle_object(&self, object: ObjectType, other_args: Vec<String>) -> Result<()> {
37        let mut opts = Options::new();
38        self.accepted_option_items().add_to_opts(&mut opts);
39
40        let filter = ObjectFilter::build(&mut opts, &other_args)?;
41
42        let objects = &filter.get_objects(object);
43        let out_arch = objects.len() > 1;
44        for (idx, obj) in objects.iter().enumerate() {
45            if out_arch {
46                common::out_single_arch_title(&self.printer, &obj.header(), idx, false);
47            }
48            self.handle_load_commands(obj.load_commands_iterator());
49        }
50
51        Ok(())
52    }
53}
54
55impl RelHandler {
56    fn handle_load_commands(&self, commands: LoadCommandIterator) {
57        let commands = commands.filter(|cmd| match cmd.variant {
58            LcVariant::Segment32(_) | LcVariant::Segment64(_) => true,
59            _ => false,
60        });
61        for cmd in commands {
62            match cmd.variant {
63                LcVariant::Segment32(seg) | LcVariant::Segment64(seg) => {
64                    self.handle_segment_command(seg);
65                }
66                _ => (),
67            }
68        }
69    }
70
71    fn handle_segment_command(&self, seg: LcSegment) {
72        use output::table::FixedTabLine;
73
74        let line: FixedTabLine<7> = FixedTabLine::new([9, 6, 7, 7, 5, 10, 16]);
75
76        for section in seg.sections_iterator().filter(|s| s.nreloc > 0) {
77            self.printer.print_strings(
78                vec![
79                    section.segname.to_string().green(),
80                    section.sectname.to_string().green(),
81                ],
82                " ",
83            );
84
85            self.printer.print_line(
86                format!(" ({} entries)", section.nreloc.to_string().blue()).bright_white(),
87            );
88
89            line.print_line(["address", "pcrel", "length", "extern", "type", "scattered", "symbolnum/value"], vec![Color::White]);
90            for reloc in section.relocations_iterator() {
91                line.print_line([
92                    format!("{:08x}", reloc.r_address),
93                    reloc.r_pcrel().to_string(),
94                    reloc.r_length().to_string(),
95                    reloc.r_extern().to_string(),
96                    reloc.r_type().to_string(),
97                    reloc.is_scattered().to_string(),
98                    reloc.r_symbolnum().to_string(),
99                ],
100                vec![Color::Red, Color::Yellow]
101            );
102            }
103        }
104    }
105}