dynasm/arch/x64/
mod.rs

1pub mod ast;
2mod compiler;
3pub mod parser;
4mod debug;
5mod x64data;
6
7use crate::State;
8use crate::arch::{Arch, Error, BasicExprBuilder};
9use crate::common::{Size, Stmt, Jump};
10
11#[cfg(feature = "dynasm_opmap")]
12pub use debug::create_opmap;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum X86Mode {
16    Long,
17    Protected
18}
19
20struct Context<'a> {
21    pub state: &'a mut dyn BasicExprBuilder,
22    pub mode: X86Mode,
23    pub features: x64data::Features
24}
25
26#[derive(Clone, Debug)]
27pub struct Archx64 {
28    features: x64data::Features,
29}
30
31#[derive(Clone, Debug)]
32pub struct Archx86 {
33    features: x64data::Features,
34}
35
36#[derive(Debug)]
37pub struct InstructionX64 {
38    pub inst: ast::Instruction,
39    pub args: Vec<ast::CleanArg>,
40}
41
42#[derive(Debug)]
43pub struct InstructionX86 {
44    pub inst: ast::Instruction,
45    pub args: Vec<ast::CleanArg>,
46}
47
48impl Default for Archx64 {
49    fn default() -> Archx64 {
50        Archx64 { features: x64data::Features::all() }
51    }
52}
53
54impl Default for Archx86 {
55    fn default() -> Archx86 {
56        Archx86 { features: x64data::Features::all() }
57    }
58}
59
60pub trait AssembleX64 {
61    /// Turn an expression into binary format.
62    /// May error when dynamic data is present at bad locations such as memory address scaling.
63    fn compile_instruction(&mut self, arch: &Archx64, _: InstructionX64) -> Result<(), Error>;
64
65    /// Create an instruction composed from dynamic data.
66    /// Only available when the type is also capable of building new composite expressions.
67    fn build_instruction(&mut self, arch: &Archx64, _: InstructionX64) -> Result<(), Error>
68        where Self: BasicExprBuilder;
69}
70
71pub trait AssembleX86 {
72    /// Turn an expression into binary format.
73    /// May error when dynamic data is present at bad locations such as memory address scaling.
74    fn compile_instruction(&mut self, arch: &Archx86, _: InstructionX86) -> Result<(), Error>;
75
76    /// Create an instruction composed from dynamic data.
77    /// Only available when the type is also capable of building new composite expressions.
78    fn build_instruction(&mut self, arch: &Archx86, _: InstructionX86) -> Result<(), Error>
79        where Self: BasicExprBuilder;
80}
81
82impl Arch for Archx64 {
83    fn name(&self) -> &str {
84        "x64"
85    }
86
87    fn set_features(&mut self, features: &[String]) {
88        let mut new_features = x64data::Features::empty();
89        for ident in features {
90            new_features |= match x64data::Features::from_str(&ident.to_string()) {
91                Some(feature) => feature,
92                None => {
93                    eprintln!("Architecture x64 does not support feature '{}'", ident.to_string());
94                    continue;
95                }
96            }
97        }
98        self.features = new_features;
99    }
100
101    fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size) {
102        let data = [0, size.in_bytes()]; // no offset, specified size, relative implicit
103
104        stmts.push(Stmt::zeroed(size));
105        stmts.push(reloc.encode(&data));
106    }
107
108    fn default_align(&self) -> u8 {
109        0x90
110    }
111}
112
113impl AssembleX64 for State<'_> {
114    fn compile_instruction(&mut self, arch: &Archx64, instruction: InstructionX64) -> Result<(), Error> {
115        let InstructionX64 { inst, args } = instruction;
116
117        let ctx = Context {
118            state: self,
119            mode: X86Mode::Long,
120            features: arch.features,
121        };
122
123        compiler::compile_instruction(ctx, inst, args)
124    }
125
126    fn build_instruction(&mut self, _: &Archx64, _: InstructionX64) -> Result<(), Error>
127        where Self: BasicExprBuilder
128    {
129        unreachable!("Statically uncallable, Self is not BasicExprBuilder")
130    }
131}
132
133impl Arch for Archx86 {
134    fn name(&self) -> &str {
135        "x86"
136    }
137
138    fn set_features(&mut self, features: &[String]) {
139        let mut new_features = x64data::Features::empty();
140        for ident in features {
141            new_features |= match x64data::Features::from_str(&ident.to_string()) {
142                Some(feature) => feature,
143                None => {
144                    eprintln!("Architecture x86 does not support feature '{}'", ident.to_string());
145                    continue;
146                }
147            }
148        }
149        self.features = new_features;
150    }
151
152    fn handle_static_reloc(&self, stmts: &mut Vec<Stmt>, reloc: Jump, size: Size) {
153        let data = [0, size.in_bytes(), 0]; // no offset, specified size, relative
154
155        stmts.push(Stmt::zeroed(size));
156        stmts.push(reloc.encode(&data));
157    }
158
159    fn default_align(&self) -> u8 {
160        0x90
161    }
162}
163
164impl AssembleX86 for State<'_> {
165    fn compile_instruction(&mut self, arch: &Archx86, instruction: InstructionX86) -> Result<(), Error> {
166        let InstructionX86 { inst, args } = instruction;
167
168        let ctx = Context {
169            state: self,
170            mode: X86Mode::Protected,
171            features: arch.features,
172        };
173
174        compiler::compile_instruction(ctx, inst, args)
175    }
176
177    fn build_instruction(&mut self, _: &Archx86, _: InstructionX86) -> Result<(), Error>
178        where Self: BasicExprBuilder
179    {
180        unreachable!("Statically uncallable, Self is not BasicExprBuilder")
181    }
182}