dwarfdump/
lib.rs

1extern crate object;
2
3use object::Object;
4
5mod parser;
6use parser::{ parse, LittleEndian, BigEndian };
7
8use std::collections::BTreeMap;
9use std::fmt;
10use std::fmt::Write;
11
12pub struct Symbols {
13    pub functions: BTreeMap<String, Function>
14}
15
16#[derive(Clone)]
17pub struct Function {
18    pub name: Option<String>,
19    pub typed: Typed,
20    pub parameters: Parameters
21}
22
23#[derive(Clone)]
24pub struct Parameter {
25    pub name: Option<String>,
26    pub typed: Typed
27}
28pub type Parameters = Vec<Parameter>;
29pub type Member = Parameter;
30pub type Members = Vec<Member>;
31
32#[derive(Clone)]
33pub struct Typed {
34    pub name: String,
35    pub value: TypedValue,
36    pub modifiers: Modifiers
37}
38
39#[derive(Clone)]
40#[derive(Debug)]
41pub enum TypedValue {
42    Base,
43    Enum,
44    Typedef(Box<Typed>),
45    Function(Box<Function>),
46    Struct(Members),
47    Union(Members),
48    Array(Box<Typed>, u16),
49    Circular
50}
51
52#[derive(Clone)]
53pub enum Modifier {
54    Pointer,
55    Reference,
56    Const,
57    Volatile,
58    Restrict
59}
60pub type Modifiers = Vec<Modifier>;
61
62impl Symbols {
63    pub fn from(file: object::File) -> Symbols {
64        if file.is_little_endian() {
65            parse::<LittleEndian>(file)
66        } else {
67            parse::<BigEndian>(file)
68        }
69    }
70
71    fn new() -> Symbols {
72        Symbols {
73            functions: BTreeMap::new()
74        }
75    }
76}
77
78impl fmt::Debug for Function {
79    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80        let typeds = self.parameters.iter().fold(format!("\n{:?}", self.typed), |mut s, p| {
81            let _ = write!(s, "\n{:?}", p);
82            s
83        });
84        write!(f, "{}{}", self, typeds)
85    }
86}
87
88impl fmt::Display for Function {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        // Vec cannot impl fmt::Display, so it is done here
91        let parameters = self.parameters.iter().fold(String::new(), |mut s, p| {
92            let _ = if s.is_empty() {
93                write!(s, "{}", p)
94            } else {
95                write!(s, ", {}", p)
96            };
97            s
98        });
99
100        match self.name {
101            Some(ref name) => write!(f, "{} {}({})", name, self.typed, parameters),
102            None => write!(f, "{}({})", self.typed, parameters)
103        }
104    }
105}
106
107impl fmt::Debug for Parameter {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        let name = match self.name {
110            Some(ref name) => format!("name: {}\t", name),
111            None => String::new()
112        };
113        write!(f, "{}{:?}", name, self.typed)
114    }
115}
116
117impl fmt::Display for Parameter {
118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119        match self.typed.value {
120            TypedValue::Function(ref function) => {
121                let mut function_ptr = (*function).clone();
122                function_ptr.name = Some(match self.name {
123                    Some(ref name) => format!("(*{})", name),
124                    None => String::from("(*)")
125                });
126                write!(f, "{}", function_ptr)
127            },
128            _ => {
129                match self.name {
130                    Some(ref name) => write!(f, "{} {}", self.typed, name),
131                    None => write!(f, "{}", self.typed)
132                }
133            }
134        }
135    }
136}
137
138impl fmt::Debug for Typed {
139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140        write!(f, "{} {:#?}", self, self.value)
141    }
142}
143
144impl fmt::Display for Typed {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        let specifier = self.modifiers.iter().fold(self.name.clone(), |s, m| {
147            match m {
148                &Modifier::Pointer => s + "*",
149                &Modifier::Reference => s + "&",
150                &Modifier::Const => s + " const",
151                &Modifier::Volatile => s + " volatile",
152                &Modifier::Restrict => s + " restrict"
153            }
154        });
155        write!(f, "{}", specifier)
156    }
157}