yaxpeax_core/arch/
interface.rs

1/*
2/ *
3 * This works as a common interface for architectures to present their functionality
4 * /
5struct Interface<A: Arch> {
6    display: &DisplayInterface<A>,
7    analysis: &AnalysisInterface<A>,
8}
9
10// for dynamically loaded modules we need to unmarshal
11// something to call their types
12// and do some WILDLY unsafe casts to force some function
13// pointers into othe shape of populated types
14
15trait DisplayInterface <A: Arch + BaseDisplay<F, U>, U, F, Contexts: ContextRead<A, U>> {
16    show_block: Fn(&[u8], &Contexts, function_table: &HashMap<A::Address, F>, cfg: &ControlFlowGraph<A::Address>, block: &BasicBlock<A::Address>) -> ();
17    show_linear: Fn(&[u8], &Contexts, start_addr: A::Address, end_addr: A::Address, function_table: &HashMap<A::Address, F>) -> ();
18    ssa: Option<SSADisplay>
19}
20
21trait SSADisplay {
22    show_function: ..
23}
24
25trait AnalysisInterface {
26    control_flow: ControlFlowAnalyses,
27    ssa_analyses: SSAAnalyses
28}
29
30/ *
31 * And what about when A::Instruction does not implement Determinant...
32 * /
33trait ControlFlowAnalyses<A: Arch, F, Contexts: ContextRead<A, U> + ContextWrite<A, U>, InstrCallback> {
34    explore_all: Fn(&[u8], &mut Contexts, &mut ControlFlowGraph<A::Address>, A::Address, &InstrCallback) -> Vec<A::Address>;
35    explore_control_flow: Fn(&[u8], &mut Contexts, &mut ControlFlowGraph<A::Address>, A::Address, &InstrCallback) -> Vec<A::Address>;
36}
37
38/ *
39 * this might not be implementable because in some cases A explicitly does NOT implement SSAValues
40 * /
41trait SSAAnalyses<A: Arch + SSAValues> {
42    construct_ssa: Fn(&[u8], A::Address, &ControlFlowGraph<A::Address>, GraphMap<A::Address, (), petgraph::Directed> -> SSA<A>
43}
44*/
45
46use yaxpeax_arch::Arch;
47use arch;
48use arch::Symbol;
49
50use std::fmt;
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub enum Summary<A: Arch> {
54    ListBlocks,
55    ListFunctions,
56    ListFunctionBlocks(A::Address),
57    HowMuchCode,
58    ProgramInfo,
59    SymbolInfo(Option<String>, String),
60}
61
62pub struct SummaryHelp;
63
64impl fmt::Display for SummaryHelp {
65    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
66        writeln!(fmt, "list_blocks")?;
67        writeln!(fmt, "list_functions")?;
68        writeln!(fmt, "list_function_blocks:<function_address>")?;
69        writeln!(fmt, "howmuchcode")?;
70        writeln!(fmt, "program_info")?;
71        writeln!(fmt, "symbol_info:<library_name>:<symbol_name>")?;
72
73        Ok(())
74    }
75}
76
77pub struct ListHelp;
78
79impl fmt::Display for ListHelp {
80    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
81        writeln!(fmt, "list_functions")?;
82        writeln!(fmt, "list_function_blocks:<function_address>")?;
83
84        Ok(())
85    }
86}
87
88#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
89pub enum Display<A: Arch> {
90    RenderInstruction(A::Address),
91    RenderBlock(A::Address),
92    RenderRange(A::Address, A::Address),
93    RenderFunction(A::Address),
94    RenderInstructionSSA(A::Address),
95    RenderBlockSSA(A::Address),
96    RenderFunctionSSA(A::Address)
97}
98
99pub struct DisplayHelp;
100
101impl fmt::Display for DisplayHelp {
102    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
103        writeln!(fmt, "render_instruction:<address>")?;
104        writeln!(fmt, "render_block:<address>")?;
105        writeln!(fmt, "render_range:<start_address>:<end_address>")?;
106        writeln!(fmt, "render_function:<address>")?;
107        writeln!(fmt, "render_instruction_ssa:<address>")?;
108        writeln!(fmt, "render_block_ssa:<address>")?;
109        writeln!(fmt, "render_function_ssa:<address>")?;
110
111        Ok(())
112    }
113}
114
115pub enum ParseResult<A: Arch, T> {
116    Operation(Operation<A, T>),
117    Help(&'static dyn fmt::Display),
118    Err(OperationError)
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub enum Operation<A: Arch, T> {
123    /* base ops */
124    Display(Display<A>),
125    Analysis(Analysis<A>),
126    Debug(Debug),
127    Summary(Summary<A>),
128    Data(Data<A>),
129    Specific(T)
130}
131
132pub struct OperationHelp;
133
134impl fmt::Display for OperationHelp {
135    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
136        writeln!(fmt, "display")?;
137        writeln!(fmt, "  commands related to displaying data, instructions, functions, etc")?;
138        writeln!(fmt, "analysis")?;
139        writeln!(fmt, "  commands to run analyses of code")?;
140        writeln!(fmt, "debug")?;
141        writeln!(fmt, "  commands for debugging (attaching to a process, breakpoints, execution, ...")?;
142        writeln!(fmt, "summary")?;
143        writeln!(fmt, "  commands for summarizing information about the program in question, data that is known, ...")?;
144        writeln!(fmt, "data")?;
145        writeln!(fmt, "  commands for directly modifying low level data that is tracked - adding function hints, adding contextual overrides of instruction semantics, data overrides, etc")?;
146        writeln!(fmt, "specific")?;
147        writeln!(fmt, "  architecture-specific commands (none of these yet!)")?;
148
149        Ok(())
150    }
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub enum Data<A: Arch> {
155    AddFunctionHint(A::Address),
156    DefineSymbol(A::Address, Symbol),
157    CodeComment(A::Address, String),
158}
159
160pub struct DataHelp;
161
162impl fmt::Display for DataHelp {
163    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
164        writeln!(fmt, "add_function_hint:<address>")?;
165        writeln!(fmt, "define_symbol:<address>:<symbol name>")?;
166        writeln!(fmt, "code_comment:<address>:<comment>")?;
167
168        Ok(())
169    }
170}
171
172#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
173pub enum Debug {
174    ShowMaps,
175    ShowModules,
176    ShowThreads,
177    ShowInfo,
178    Step,
179}
180
181pub struct DebugHelp;
182
183impl fmt::Display for DebugHelp {
184    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
185        writeln!(fmt, "show_maps")?;
186        writeln!(fmt, "show_modules")?;
187        writeln!(fmt, "show_threads")?;
188        writeln!(fmt, "show_info")?;
189
190        Ok(())
191    }
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub enum Analysis<A: Arch> {
196    ComputeSSAForm(A::Address),
197    ControlFlowLinear(A::Address, A::Address),
198    ControlFlowIncremental(Vec<A::Address>),
199    DoEverything
200}
201
202pub struct AnalysisHelp;
203
204impl fmt::Display for AnalysisHelp {
205    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
206        writeln!(fmt, "compute_ssa_form:<at_address>")?;
207        writeln!(fmt, "control_flow_linear:<start_address>:<end_address>")?;
208        writeln!(fmt, "  computes control flow between `start` and `end`")?;
209        writeln!(fmt, "  this is not what you want if a linear decode is invalid (might decode incorrect instructions, for example)")?;
210        writeln!(fmt, "control_flow_incremental:<start_address>")?;
211        writeln!(fmt, "  recursively builds control flow information from `start_address`, with no runtime/memory/size bounds")?;
212        writeln!(fmt, "compute_ssa_form:<address>")?;
213        writeln!(fmt, "  computes SSA numbering for the control flow graph started at `address`.")?;
214        writeln!(fmt, "do_everything")?;
215        writeln!(fmt, "  recursively finds control flow from hinted start points, then computes SSA form for reached code")?;
216
217        Ok(())
218    }
219}
220
221#[derive(Debug, Serialize, Deserialize)]
222pub enum OperationSuccess {
223    Ok,
224    OkWithOutput(Vec<(usize, Vec<String>)>),
225    SwitchArch(arch::ISA)
226}
227
228#[derive(Debug, Serialize, Deserialize)]
229pub enum ParseError {
230    Address(String),
231    Symbol(String),
232    Command(String),
233}
234
235impl std::fmt::Display for ParseError {
236    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
237        match self {
238            ParseError::Address(addr) => {
239                write!(fmt, "Invalid address: \"{}\"", addr)
240            },
241            ParseError::Symbol(sym) => {
242                write!(fmt, "Invalid symbol: \"{}\"", sym)
243            },
244            ParseError::Command(cmd) => {
245                write!(fmt, "Invalid command: \"{}\"", cmd)
246            },
247        }
248    }
249}
250
251#[derive(Debug, Serialize, Deserialize)]
252pub enum OperationError {
253    ParseError(ParseError),
254    Invalid(String),
255    Unknown(String),
256    Unsupported(String),
257    Misc(String)
258}
259
260pub trait Operate<T, A: Arch> {
261//    type TargetArch: Arch;
262//    fn evaluate(operation: Operation<Self::TargetArch, T>) -> Result<OperationSuccess, OperationError<Self::TargetArch, T>>;
263    fn evaluate(&mut self, operation: Operation<A, T>) -> Result<OperationSuccess, OperationError>;
264}