1use std::collections::HashMap;
5use std::path::PathBuf;
6
7use crate::backend::{FlowConfig, OperandKind};
8use crate::config::{
9 BinjaOptions, CppGuardStyle, CppOptions, Dispatch, GenTarget, IdaOptions, LangOptions,
10 LutTarget,
11};
12use crate::error::{Error, ErrorKind};
13
14use super::resolve::ResolvedBindings;
15use super::types::*;
16
17pub struct LoweredItem {
21 pub target_kind: TargetKind,
22 pub decoder_name: String,
23 pub kind: LoweredKind,
24}
25
26pub enum LoweredKind {
27 Gen(GenTarget),
28 Lut(LutTarget),
29 InstrType {
33 input: PathBuf,
34 output: String,
35 struct_name: String,
36 subdecoder: Option<String>,
37 },
38}
39
40pub struct LoweredBindings {
41 pub items: Vec<LoweredItem>,
42}
43
44pub fn lower_resolved(resolved: &ResolvedBindings) -> Result<LoweredBindings, Vec<Error>> {
45 let mut items: Vec<LoweredItem> = Vec::new();
46 let mut errors: Vec<Error> = Vec::new();
47
48 for target in &resolved.file.targets {
49 match target.kind {
50 TargetKind::Rust => {
51 for d in &target.rust_decoders {
52 if let Err(mut errs) = lower_rust_decoder(resolved, d, &mut items) {
53 errors.append(&mut errs);
54 }
55 }
56 for d in &target.rust_dispatches {
57 if let Err(mut errs) = lower_rust_dispatch(resolved, d, None, &mut items) {
58 errors.append(&mut errs);
59 }
60 }
61 }
62 TargetKind::Cpp => {
63 for d in &target.cpp_decoders {
64 if let Err(mut errs) = lower_cpp_decoder(resolved, d, &mut items) {
65 errors.append(&mut errs);
66 }
67 }
68 }
69 TargetKind::Ida => {
70 for p in &target.ida_processors {
71 if let Err(mut errs) = lower_ida_processor(resolved, p, &mut items) {
72 errors.append(&mut errs);
73 }
74 }
75 }
76 TargetKind::Binja => {
77 for a in &target.binja_architectures {
78 if let Err(mut errs) = lower_binja_architecture(resolved, a, &mut items) {
79 errors.append(&mut errs);
80 }
81 }
82 }
83 }
84 }
85
86 if errors.is_empty() {
87 Ok(LoweredBindings { items })
88 } else {
89 Err(errors)
90 }
91}
92
93fn spec_path(resolved: &ResolvedBindings, decoder_name: &str) -> Result<PathBuf, Error> {
94 if let Some((spec, _)) = resolved.find_decoder_or_sub(decoder_name) {
95 Ok(spec.path.clone())
96 } else {
97 Err(Error::new(
98 ErrorKind::UnknownDecoderInBinding {
99 name: decoder_name.to_string(),
100 suggestion: None,
101 },
102 crate::error::Span::new("<lower>", 0, 0, 0),
103 ))
104 }
105}
106
107fn lower_rust_decoder(
108 resolved: &ResolvedBindings,
109 d: &DecoderBinding,
110 items: &mut Vec<LoweredItem>,
111) -> Result<(), Vec<Error>> {
112 let input = spec_path(resolved, &d.decoder_name).map_err(|e| vec![e])?;
113 let mut type_map = HashMap::new();
114 for (k, v) in &d.type_map {
115 type_map.insert(k.clone(), v.clone());
116 }
117 let target = GenTarget {
118 input: input.to_string_lossy().into_owned(),
119 lang: "rust".to_string(),
120 output: d.output.clone(),
121 format: false,
122 dispatch: Dispatch::default(),
123 dispatch_overrides: HashMap::new(),
124 type_map,
125 lang_options: LangOptions::None,
126 };
127 items.push(LoweredItem {
128 target_kind: TargetKind::Rust,
129 decoder_name: d.decoder_name.clone(),
130 kind: LoweredKind::Gen(target),
131 });
132
133 let _ = &d.subdecoders;
139
140 Ok(())
141}
142
143fn lower_cpp_decoder(
144 resolved: &ResolvedBindings,
145 d: &DecoderBinding,
146 items: &mut Vec<LoweredItem>,
147) -> Result<(), Vec<Error>> {
148 let input = spec_path(resolved, &d.decoder_name).map_err(|e| vec![e])?;
149 let mut type_map = HashMap::new();
150 for (k, v) in &d.type_map {
151 type_map.insert(k.clone(), v.clone());
152 }
153 let guard_style = match d.cpp_guard_style.as_deref() {
154 Some("ifndef") => CppGuardStyle::Ifndef,
155 _ => CppGuardStyle::Pragma,
156 };
157 let cpp = CppOptions {
158 namespace: d.cpp_namespace.clone(),
159 guard_style,
160 includes: d.cpp_includes.clone(),
161 };
162 let target = GenTarget {
163 input: input.to_string_lossy().into_owned(),
164 lang: "cpp".to_string(),
165 output: d.output.clone(),
166 format: false,
167 dispatch: Dispatch::default(),
168 dispatch_overrides: HashMap::new(),
169 type_map,
170 lang_options: LangOptions::Cpp(cpp),
171 };
172 items.push(LoweredItem {
173 target_kind: TargetKind::Cpp,
174 decoder_name: d.decoder_name.clone(),
175 kind: LoweredKind::Gen(target),
176 });
177 Ok(())
178}
179
180fn lower_ida_processor(
181 resolved: &ResolvedBindings,
182 p: &IdaProcessorBinding,
183 items: &mut Vec<LoweredItem>,
184) -> Result<(), Vec<Error>> {
185 let input = spec_path(resolved, &p.decoder_name).map_err(|e| vec![e])?;
186 let opts = IdaOptions {
187 processor_name: p.name.clone().unwrap_or_default(),
188 processor_long_name: p.long_name.clone().unwrap_or_default(),
189 processor_id: p.id.unwrap_or(0),
190 register_names: p.registers.clone(),
191 segment_registers: p.segment_registers.iter().map(|(s, _)| s.clone()).collect(),
192 address_size: p.address_size.unwrap_or(32),
193 bytes_per_unit: p.bytes_per_unit.unwrap_or(1),
194 flags: Vec::new(),
195 operand_types: HashMap::<String, OperandKind>::new(),
196 display_prefixes: HashMap::new(),
197 flow: FlowConfig {
198 calls: p.flow.calls.iter().map(|(s, _)| s.clone()).collect(),
199 branches: Vec::new(),
200 unconditional_branches: Vec::new(),
201 returns: p.flow.returns.iter().map(|(s, _)| s.clone()).collect(),
202 stops: p.flow.stops.iter().map(|(s, _)| s.clone()).collect(),
203 },
204 };
205 let output = p.output.clone().unwrap_or_default();
206 let target = GenTarget {
207 input: input.to_string_lossy().into_owned(),
208 lang: "ida".to_string(),
209 output,
210 format: false,
211 dispatch: Dispatch::default(),
212 dispatch_overrides: HashMap::new(),
213 type_map: HashMap::new(),
214 lang_options: LangOptions::Ida(opts),
215 };
216 items.push(LoweredItem {
217 target_kind: TargetKind::Ida,
218 decoder_name: p.decoder_name.clone(),
219 kind: LoweredKind::Gen(target),
220 });
221 Ok(())
222}
223
224fn lower_binja_architecture(
225 resolved: &ResolvedBindings,
226 a: &BinjaArchitectureBinding,
227 items: &mut Vec<LoweredItem>,
228) -> Result<(), Vec<Error>> {
229 let input = spec_path(resolved, &a.decoder_name).map_err(|e| vec![e])?;
230 let endian = a
231 .endianness
232 .as_ref()
233 .map(|(s, _)| match s.as_str() {
234 "big" => "BigEndian",
235 "little" => "LittleEndian",
236 _ => "LittleEndian",
237 })
238 .unwrap_or("LittleEndian")
239 .to_string();
240 let address_size = a.address_size.unwrap_or(4);
241 let opts = BinjaOptions {
242 architecture_name: a.name.clone().unwrap_or_default(),
243 address_size,
244 default_int_size: a.default_int_size.unwrap_or(address_size),
245 max_instr_length: address_size,
246 endianness: endian,
247 register_names: a.registers.clone(),
248 register_size: address_size,
249 stack_pointer: None,
250 link_register: None,
251 bytes_per_unit: 1,
252 display_prefixes: HashMap::new(),
253 operand_types: HashMap::<String, OperandKind>::new(),
254 flow: FlowConfig::default(),
255 };
256 let output = a.output.clone().unwrap_or_default();
257 let target = GenTarget {
258 input: input.to_string_lossy().into_owned(),
259 lang: "binja".to_string(),
260 output,
261 format: false,
262 dispatch: Dispatch::default(),
263 dispatch_overrides: HashMap::new(),
264 type_map: HashMap::new(),
265 lang_options: LangOptions::Binja(opts),
266 };
267 items.push(LoweredItem {
268 target_kind: TargetKind::Binja,
269 decoder_name: a.decoder_name.clone(),
270 kind: LoweredKind::Gen(target),
271 });
272 Ok(())
273}
274
275fn lower_rust_dispatch(
276 resolved: &ResolvedBindings,
277 d: &DispatchBinding,
278 parent: Option<&DispatchBinding>,
279 items: &mut Vec<LoweredItem>,
280) -> Result<(), Vec<Error>> {
281 let input = spec_path(resolved, &d.decoder_name).map_err(|e| vec![e])?;
282
283 let context = d
284 .context
285 .clone()
286 .or_else(|| parent.and_then(|p| p.context.clone()))
287 .unwrap_or_default();
288 let handlers = d
289 .handlers
290 .clone()
291 .or_else(|| parent.and_then(|p| p.handlers.clone()))
292 .unwrap_or_default();
293 let strategy = d
294 .strategy
295 .or_else(|| parent.and_then(|p| p.strategy))
296 .unwrap_or(Dispatch::FnPtrLut);
297 let invalid_handler = d
298 .invalid_handler
299 .clone()
300 .or_else(|| parent.and_then(|p| p.invalid_handler.clone()));
301
302 let mut groups: HashMap<String, Vec<String>> = HashMap::new();
303 for g in &d.handler_groups {
304 let names: Vec<String> = g.instructions.iter().map(|(n, _)| n.clone()).collect();
305 groups.insert(g.handler_name.clone(), names);
306 }
307
308 let instr_type = d
309 .instruction_type
310 .as_ref()
311 .map(|it| it.type_path.clone())
312 .or_else(|| {
313 parent.and_then(|p| p.instruction_type.as_ref().map(|it| it.type_path.clone()))
314 });
315 let raw_expr = if instr_type.is_some() {
316 Some("instr.0".to_string())
317 } else {
318 None
319 };
320 let instr_type_output = d.instruction_type.as_ref().and_then(|it| it.output.clone());
321
322 let lut_mod: Option<String> = None;
323
324 let mut subdecoder_groups: HashMap<String, HashMap<String, Vec<String>>> = HashMap::new();
325 let mut subdecoder_instr_types: HashMap<String, String> = HashMap::new();
326 let mut subdecoder_instr_type_outputs: HashMap<String, String> = HashMap::new();
327 let mut subdecoder_dispatch: HashMap<String, Dispatch> = HashMap::new();
328 let mut subdecoder_invalid_handlers: HashMap<String, String> = HashMap::new();
329 let mut subdecoder_handler_mods: HashMap<String, String> = HashMap::new();
330
331 for sd in &d.subdispatches {
332 let mut sg: HashMap<String, Vec<String>> = HashMap::new();
333 for g in &sd.handler_groups {
334 let names: Vec<String> = g.instructions.iter().map(|(n, _)| n.clone()).collect();
335 sg.insert(g.handler_name.clone(), names);
336 }
337 if !sg.is_empty() {
338 subdecoder_groups.insert(sd.decoder_name.clone(), sg);
339 }
340 if let Some(it) = &sd.instruction_type {
341 subdecoder_instr_types.insert(sd.decoder_name.clone(), it.type_path.clone());
342 if let Some(out) = &it.output {
343 subdecoder_instr_type_outputs.insert(sd.decoder_name.clone(), out.clone());
344 }
345 }
346 let strat = sd.strategy.unwrap_or(strategy);
347 subdecoder_dispatch.insert(sd.decoder_name.clone(), strat);
348
349 if let Some(h) = &sd.invalid_handler {
350 subdecoder_invalid_handlers.insert(sd.decoder_name.clone(), h.clone());
351 } else if let Some(h) = &invalid_handler {
352 subdecoder_invalid_handlers.insert(sd.decoder_name.clone(), h.clone());
353 }
354 if let Some(h) = &sd.handlers {
355 subdecoder_handler_mods.insert(sd.decoder_name.clone(), h.clone());
356 }
357 }
358
359 let target = LutTarget {
360 input: input.to_string_lossy().into_owned(),
361 output: d.output.clone().unwrap_or_default(),
362 handler_mod: handlers,
363 ctx_type: context,
364 dispatch: strategy,
365 groups,
366 lut_mod,
367 instr_type,
368 raw_expr,
369 instr_type_output,
370 subdecoder_groups,
371 subdecoder_instr_type_outputs,
372 subdecoder_instr_types,
373 subdecoder_dispatch,
374 invalid_handler,
375 subdecoder_invalid_handlers,
376 subdecoder_handler_mods,
377 };
378 items.push(LoweredItem {
379 target_kind: TargetKind::Rust,
380 decoder_name: d.decoder_name.clone(),
381 kind: LoweredKind::Lut(target),
382 });
383
384 let _ = parent;
387
388 Ok(())
389}