1use crate::arch::{get_sla, get_language};
2use crate::sleigh::*;
3
4extern crate bitvec;
5extern crate nom;
6
7use super::arch::Language;
8
9use nom::branch::*;
10use nom::bytes::complete::*;
11use nom::character::complete::*;
12use nom::combinator::*;
13use nom::error::*;
14use nom::multi::*;
15use nom::sequence::*;
16use nom::*;
17
18use bitvec::prelude::*;
19
20use std::collections::HashMap;
21use std::hash::{Hash, Hasher};
22use std::fmt;
23
24pub type Res<T, U> = IResult<T, U, Error<T>>;
25
26#[derive(Debug, PartialEq, Eq, Clone)]
27pub struct MaskWord {
28 pub mask: u32,
29 pub val: u32,
30}
31
32#[derive(Debug, PartialEq, Eq, Clone)]
33pub struct PatternBlock {
34 pub offset: u32,
35 pub nonzero: u32,
36 pub masks: Vec<MaskWord>,
37}
38
39#[derive(Debug, PartialEq, Eq, Clone)]
40pub enum DecisionPattern {
41 Context(PatternBlock),
42 Instruction(PatternBlock),
43 Combine((Box<DecisionPattern>, Box<DecisionPattern>)),
44}
45
46#[derive(Debug, PartialEq, Eq, Clone)]
47pub enum DecisionTree {
48 Leaf(Vec<(u32, DecisionPattern)>),
49 NonLeaf((bool, u32, u32, Vec<DecisionTree>)),
50}
51
52impl Hash for DecisionTree {
53 fn hash<H: Hasher>(&self, state: &mut H) {
54 match self {
55 DecisionTree::Leaf(patterns) => {
56 "Leaf".hash(state);
57 patterns.hash(state);
58 }
59 DecisionTree::NonLeaf((b, u1, u2, subtrees)) => {
60 "NonLeaf".hash(state);
61 b.hash(state);
62 u1.hash(state);
63 u2.hash(state);
64 subtrees.hash(state);
65 }
66 }
67 }
68}
69
70impl Hash for MaskWord {
71 fn hash<H: Hasher>(&self, state: &mut H) {
72 self.mask.hash(state);
73 self.val.hash(state);
74 }
75}
76
77impl Hash for PatternBlock {
78 fn hash<H: Hasher>(&self, state: &mut H) {
79 self.offset.hash(state);
80 self.nonzero.hash(state);
81 self.masks.hash(state);
82 }
83}
84
85impl Hash for DecisionPattern {
86 fn hash<H: Hasher>(&self, state: &mut H) {
87 match self {
88 DecisionPattern::Context(block) => {
89 "Context".hash(state);
90 block.hash(state);
91 }
92 DecisionPattern::Instruction(block) => {
93 "Instruction".hash(state);
94 block.hash(state);
95 }
96 DecisionPattern::Combine((p1, p2)) => {
97 "Combine".hash(state);
98 p1.hash(state);
99 p2.hash(state);
100 }
101 }
102 }
103}
104
105#[derive(Debug, PartialEq, Eq, Clone)]
106pub struct Space {
107 pub name: String,
108 pub index: u32,
109 pub big_endian: bool,
110 pub delay: u32,
111 pub size: u32,
112 pub physical: bool,
113}
114
115#[derive(Debug, PartialEq, Eq, Clone)]
116pub struct Scope {
117 parent: u32,
118}
119
120#[derive(Debug, PartialEq, Eq, Clone)]
121pub struct SymbolHead {
122 pub name: String,
123 pub scope: u32,
124}
125
126#[derive(Debug, PartialEq, Eq, Clone)]
127pub struct VarnodeSym {
128 pub name: String,
129 pub scope: u32,
130 pub space: AddressSpace,
131 pub offset: u64,
132 pub size: u64,
133}
134
135#[derive(Debug, PartialEq, Eq, Clone)]
136pub struct Value {
137 pub name: String,
138 pub scope: u32,
139 pub field: Field,
140}
141
142#[derive(Debug, PartialEq, Eq, Clone)]
143pub struct Varlist {
144 pub name: String,
145 pub scope: u32,
146 pub field: Field,
147 pub vars: Vec<Option<u32>>,
148}
149
150#[derive(Debug, PartialEq, Eq, Clone)]
151pub struct NameTable {
152 pub name: String,
153 pub scope: u32,
154 pub field: Field,
155 pub names: Vec<Option<String>>,
156}
157
158#[derive(Debug, PartialEq, Eq, Clone)]
159pub struct Valuemap {
160 pub name: String,
161 pub scope: u32,
162 pub field: Field,
163 pub vars: Vec<u64>,
164}
165
166#[derive(Debug, PartialEq, Eq, Clone)]
167pub struct Operand {
168 pub name: String,
169 pub scope: u32,
170 pub subsym: u32,
171 pub off: u64,
172 pub base: i64,
173 pub min_len: u64,
174 pub idx: u64,
175 pub is_code: bool,
176 pub operand_expr: OperandExpr,
177 pub expr: Option<Expr>,
178}
179
180#[derive(Debug, PartialEq, Eq, Clone)]
181pub struct Context {
182 pub name: String,
183 pub scope: u32,
184 pub varnode: u32,
185 pub low: u32,
186 pub high: u32,
187 pub flow: bool,
188 pub context_field: ContextField,
189}
190
191#[derive(Debug, PartialEq, Eq, Clone)]
192pub struct UserOp {
193 name: String,
194 scope: u32,
195 idx: u32,
196}
197
198#[derive(Debug, PartialEq, Eq, Clone)]
199pub enum SymbolBody {
200 Scope(Scope),
201 SymHead(SymbolHead),
202 Subtable(Subtable),
203 Varnode(VarnodeSym),
204 Value(Value),
205 Varlist(Varlist),
206 Nametab(NameTable),
207 Valuemap(Valuemap),
208 Operand(Operand),
209 Context(Context),
210 UserOp(UserOp),
211 Start(SymbolHead),
212 End(SymbolHead),
213 Next2(SymbolHead),
214}
215
216#[derive(Debug, Clone)]
217pub struct Symbol {
218 pub id: u32,
219 pub body: SymbolBody,
220}
221
222impl PartialEq for Symbol {
223 fn eq(&self, other: &Self) -> bool {
224 self.id == other.id
225 }
226}
227
228impl Eq for Symbol {}
229
230#[derive(Debug, PartialEq, Eq, Clone)]
231pub struct Subtable {
232 pub name: String,
233 pub scope: u32,
234 pub constructors: Vec<Constructor>,
235 pub decision_tree: DecisionTree,
236}
237
238#[derive(Debug, PartialEq, Eq, Clone)]
239pub struct ContextField {
240 pub sign_bit: bool,
241 pub start_bit: u32,
242 pub end_bit: u32,
243 pub start_byte: u32,
244 pub end_byte: u32,
245 pub shift: u32,
246}
247
248#[derive(Debug, PartialEq, Eq, Clone)]
249pub struct TokenField {
250 pub big_endian: bool,
251 pub sign_bit: bool,
252 pub start_bit: u32,
253 pub end_bit: u32,
254 pub start_byte: u32,
255 pub end_byte: u32,
256 pub shift: u32,
257}
258
259#[derive(Debug, PartialEq, Eq, Clone)]
260pub enum Field {
261 Context(ContextField),
262 Token(TokenField),
263}
264
265#[derive(Debug, PartialEq, Eq, Clone)]
266pub struct OperandExpr {
267 pub idx: u32,
268 pub table: u32,
269 pub ct: u32,
270}
271
272#[derive(Debug, PartialEq, Eq, Clone)]
273pub enum ExprOp {
274 Not, Minus,
275 Xor, Add, Sub, Lshift, Rshift, Mult, And, Or
276}
277
278#[derive(Debug, PartialEq, Eq, Clone)]
279pub enum Expr {
280 Const(i64),
281 Operand(OperandExpr),
282 Field(Field),
283 Unary((ExprOp, Box<Expr>)),
284 Binary((ExprOp, Box<Expr>, Box<Expr>)),
285 End,
286 Start,
287 Next2,
288}
289
290#[derive(Debug, Clone)]
291pub struct Constructor {
292 pub _parent: u32,
293 pub _first: i32,
294 pub length: u32,
295 pub operands: Vec<u32>,
296 pub print_commands: Option<Vec<PrintCommand>>,
297 pub context_ops: Vec<ContextOp>,
298 pub template: Option<ConstructorTemplate>,
299 pub line: (usize, usize),
300}
301
302impl PartialEq for Constructor {
303 fn eq(&self, other: &Self) -> bool {
304 self.line == other.line
305 }
306}
307
308impl Eq for Constructor {}
309
310#[derive(Debug, PartialEq, Eq, Clone)]
311pub enum PrintCommand {
312 Op(u32),
313 Piece(String),
314}
315
316#[derive(Debug, PartialEq, Eq, Clone)]
317pub struct ContextOp {
318 pub i: u32,
319 pub shift: u32,
320 pub mask: u32,
321 pub expr: Expr,
322}
323
324#[derive(Debug, PartialEq, Eq, Clone)]
325pub struct ConstructorTemplate {
326 pub num_labels: u32,
327 pub statements: Vec<ConsTemplate>,
328}
329
330#[derive(Debug, PartialEq, Eq, Clone)]
331pub struct OpTemplate {
332 pub code: String,
333 pub output: Option<VarnodeTemplate>,
334 pub inputs: Vec<VarnodeTemplate>,
335}
336
337impl fmt::Display for OpTemplate {
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 let input_str = self.inputs.iter().map(|i| format!("{}", i)).collect::<Vec<String>>().join(", ");
340
341 if let Some(output) = &self.output {
342 write!(f, "{} = {}({})", output, self.code, input_str)
343 } else {
344 write!(f, "{}({})", self.code, input_str)
345 }
346 }
347}
348
349
350#[derive(Debug, PartialEq, Eq, Clone)]
351pub struct HandleTemplate {
352 pub space_template: ConstTemplate,
353 pub size_template: ConstTemplate,
354 pub pointer_template: VarnodeTemplate,
355 pub temp_space_template: ConstTemplate,
356 pub temp_offset_template: ConstTemplate,
357}
358
359impl fmt::Display for HandleTemplate {
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 write!(f, "*[{}:{}]({})", self.space_template, self.size_template, self.pointer_template)
362 }
368}
369
370#[derive(Debug, PartialEq, Eq, Clone)]
371pub enum ConsTemplate {
372 Op(OpTemplate),
373 Handle(HandleTemplate),
374}
375
376#[derive(Debug, PartialEq, Eq, Clone)]
377pub struct ConcreteVarnodeTemplate {
378 space: String,
379 offset: u64,
380 size: u32,
381}
382
383#[derive(Debug, PartialEq, Eq, Clone)]
384pub struct VarnodeTemplate {
385 pub space_template: ConstTemplate,
386 pub offset_template: ConstTemplate,
387 pub size_template: ConstTemplate,
388}
389
390impl VarnodeTemplate {
391 pub fn handle_index(&self) -> Option<usize> {
392 use ConstTemplate::*;
393
394 match (&self.space_template, &self.offset_template, &self.size_template) {
395 (Handle((h1, _)), Handle((h2, _)), Handle((h3, _))) if h1 == h2 && h2 == h3 => Some(*h1 as usize),
396 _ => None
397 }
398 }
399}
400
401impl fmt::Display for VarnodeTemplate {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 use ConstTemplate::*;
404
405 match (&self.space_template, &self.offset_template, &self.size_template) {
406 (Handle((h1, _)), Handle((h2, _)), Handle((h3, _))) if h1 == h2 && h2 == h3 => {
407 write!(f, "Handle#{}", h1)
408 },
409 _ => {
410 write!(f, "{}:{}:{}", self.space_template, self.offset_template, self.size_template)
411 },
412 }
413 }
414}
415
416#[derive(Debug, PartialEq, Eq, Clone)]
417pub enum HandleExpr {
418 OffsetPlus(u32),
419}
420
421#[derive(Debug, PartialEq, Eq, Clone)]
422pub enum ConstTemplate {
423 SpaceId(String),
424 Val(u64),
425 Handle((u32, Option<HandleExpr>)),
426 Relative(u32),
427 Start,
428 Next,
429 CurSpace,
430 CurSpaceSize,
431}
432
433impl fmt::Display for ConstTemplate {
434 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435 use ConstTemplate::*;
436
437 match self {
438 SpaceId(space) => write!(f, "{}", space),
439 Val(val) => write!(f, "{:x}", val),
440 Handle((idx, _)) => write!(f, "Handle#{}", idx),
441 _ => write!(f, "{:?}", self)
442 }
443 }
444}
445
446#[derive(Clone, PartialEq, Eq, Debug)]
447pub enum FixupType {
448 Start, End,
449}
450
451#[derive(Debug, PartialEq, Eq, Clone)]
452pub struct Program {
453 pub version: u32,
454 pub bigendian: bool,
455 pub align: u32,
456 pub uniqbase: u64,
457 pub default_space: String,
458 pub spaces: Vec<Space>,
459 pub symbols: Vec<Symbol>,
460}
461
462fn source_files(input: &str) -> Res<&str, &str> {
463 delimited(
464 tag("<sourcefiles>"),
465 take_until("</sourcefiles>"),
466 tag("</sourcefiles>"),
467 )(input)
468}
469
470fn space(input: &str) -> Res<&str, Space> {
471 delimited(
472 alt((tag("<space_other"), tag("<space_unique"), tag("<space"))),
473 take_until("/>"),
474 tag("/>"),
475 )(input)
476 .map(|(next, res)| {
477 let (_, attrs) = attrs(res).finish().unwrap();
478 let space = Space {
480 name: attrs[0].1.to_string(),
481 index: u32dec(attrs[1].1),
482 big_endian: to_bool(attrs[2].1),
483 delay: u32dec(attrs[3].1),
484 size: u32dec(attrs[4].1),
485 physical: to_bool(attrs[5].1),
486 };
487 (next, space)
488 })
489}
490
491fn spaces(input: &str) -> Res<&str, (&str, Vec<Space>)> {
492 tuple((
493 terminated(
494 delimited(tag("<spaces "), take_until(">"), tag(">")),
495 line_ending,
496 ),
497 terminated(
498 separated_list1(line_ending, space),
499 preceded(line_ending, tag("</spaces>")),
500 ),
501 ))(input)
502 .map(|(next, res)| {
503 let (_, attrs) = attrs(res.0).finish().unwrap();
504 (next, (attrs[0].1, res.1))
505 })
506}
507
508fn to_bool(s: &str) -> bool {
509 s.parse::<bool>().unwrap()
510}
511
512pub fn u32hex(s: &str) -> u32 {
513 u32::from_str_radix(&s[2..], 16).unwrap()
514}
515
516pub fn u64hex(s: &str) -> u64 {
517 u64::from_str_radix(&s[2..], 16).unwrap()
518}
519
520pub fn u64dec(s: &str) -> u64 {
521 s.parse::<u64>().unwrap()
522}
523
524pub fn u32dec(s: &str) -> u32 {
525 s.parse::<u32>().unwrap()
526}
527
528fn i64dec(s: &str) -> i64 {
529 s.parse::<i64>().unwrap()
530}
531
532fn i32dec(s: &str) -> i32 {
533 s.parse::<i32>().unwrap()
534}
535
536fn scope(input: &str) -> Res<&str, Symbol> {
537 delimited(tag("<scope "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
538 let (_, attrs) = attrs(res).finish().unwrap();
539 let id = u32hex(attrs[1].1);
541 let scope = Scope {
542 parent: u32hex(attrs[1].1),
543 };
544 (
545 next,
546 Symbol {
547 id,
548 body: SymbolBody::Scope(scope),
549 },
550 )
551 })
552}
553
554fn sym_head(input: &str) -> Res<&str, Symbol> {
555 delimited(
556 preceded(
557 tag("<"),
558 alt((
559 terminated(
560 alt((
561 tag("subtable"),
562 tag("start"),
563 tag("end"),
564 tag("next2"),
565 tag("varnode"),
566 tag("valuemap"),
567 tag("varlist"),
568 tag("value"),
569 tag("context"),
570 tag("operand"),
571 tag("name"),
572 )),
573 tag("_sym_head "),
574 ),
575 tag("userop_head "),
576 )),
577 ),
578 take_until("/>"),
579 tag("/>"),
580 )(input)
581 .map(|(next, res)| {
582 let (_, attrs) = attrs(res).finish().unwrap();
583 let id = u32hex(attrs[1].1);
585 let sym_head = SymbolHead {
586 name: attrs[0].1.to_string(),
587 scope: u32hex(attrs[2].1),
588 };
589 (
590 next,
591 Symbol {
592 id,
593 body: SymbolBody::SymHead(sym_head),
594 },
595 )
596 })
597}
598
599fn operand(input: &str) -> Res<&str, u32> {
600 let res = delimited(tag("<oper"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
601 let (_, attrs) = attrs(res).finish().unwrap();
602 (next, u32hex(attrs[0].1))
604 });
605
606 res
611}
612
613fn operands(input: &str) -> Res<&str, Vec<u32>> {
614 separated_list1(line_ending, operand)(input)
615}
616
617fn opprint(input: &str) -> Res<&str, PrintCommand> {
618 delimited(tag("<opprint"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
619 let (_, attrs) = attrs(res).finish().unwrap();
620 (next, PrintCommand::Op(u32dec(attrs[0].1)))
621 })
622}
623
624fn print_piece(input: &str) -> Res<&str, PrintCommand> {
625 delimited(tag("<print"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
626 let (_, attrs) = attrs(res).finish().unwrap();
627 (next, PrintCommand::Piece(attrs[0].1.to_string()))
628 })
629}
630
631fn print_command(input: &str) -> Res<&str, PrintCommand> {
632 alt((opprint, print_piece))(input)
633}
634
635fn print_commands(input: &str) -> Res<&str, Vec<PrintCommand>> {
636 separated_list1(line_ending, print_command)(input)
637}
638
639fn const_expr(input: &str) -> Res<&str, Expr> {
640 delimited(tag("<intb"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
642 let (_, attrs) = attrs(res).finish().unwrap();
644 (next, Expr::Const(i64dec(attrs[0].1)))
646 })
647}
648
649fn operand_expr(input: &str) -> Res<&str, Expr> {
650 delimited(tag("<operand_exp"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
651 let (_, attrs) = attrs(res).finish().unwrap();
652 let operand_expr = OperandExpr {
654 idx: u32dec(attrs[0].1),
655 table: u32hex(attrs[1].1),
656 ct: u32hex(attrs[2].1),
657 };
658 (next, Expr::Operand(operand_expr))
659 })
660}
661
662fn contextfield(input: &str) -> Res<&str, Field> {
663 delimited(tag("<contextfield"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
664 let (_, attrs) = attrs(res).finish().unwrap();
665 let context_field = ContextField {
666 sign_bit: to_bool(attrs[0].1),
667 start_bit: u32dec(attrs[1].1),
668 end_bit: u32dec(attrs[2].1),
669 start_byte: u32dec(attrs[3].1),
670 end_byte: u32dec(attrs[4].1),
671 shift: u32dec(attrs[5].1),
672 };
673 (next, Field::Context(context_field))
674 })
675}
676
677fn field_expr(input: &str) -> Res<&str, Expr> {
678 field(input).map(|(next, res)| (next, Expr::Field(res)))
680}
681
682fn start_expr(input: &str) -> Res<&str, Expr> {
683 tag("<start_exp/>")(input).map(|(next, _)| (next, (Expr::Start)))
684}
685
686fn end_expr(input: &str) -> Res<&str, Expr> {
687 tag("<end_exp/>")(input).map(|(next, _)| (next, (Expr::End)))
688}
689
690fn next2_expr(input: &str) -> Res<&str, Expr> {
691 tag("<next2_exp/>")(input).map(|(next, _)| (next, (Expr::Next2)))
692}
693
694fn unary_expr(input: &str) -> Res<&str, Expr> {
695 let expr_types = alt((
697 tag("not_exp"),
698 tag("minus_exp"),
699 tag("dummy_exp")
700 ));
701
702 let (input, (expr_type, hs_expr, _)) = tuple((
703 terminated(delimited(char('<'), expr_types, char('>')), line_ending),
704 expr,
705 preceded(line_ending, delimited(tag("</"), identifier, char('>'))),
706 ))(input)?;
707
708 let hs = Box::new(hs_expr);
709
710 let op = match expr_type {
711 "not_exp" => ExprOp::Not,
712 "minus_exp" => ExprOp::Minus,
713 _ => todo!(),
714 };
715
716 Ok((input, Expr::Unary((op, hs))))
717}
718
719fn binary_expr(input: &str) -> Res<&str, Expr> {
720 let expr_types = alt((
722 tag("plus_exp"),
723 tag("sub_exp"),
724 tag("and_exp"),
725 tag("xor_exp"),
726 tag("or_exp"),
727 tag("lshift_exp"),
728 tag("rshift_exp"),
729 tag("mult_exp"),
730 ));
731
732 let (input, (expr_type, (lhs_expr, rhs_expr), _)) = tuple((
733 terminated(delimited(char('<'), expr_types, char('>')), line_ending),
734 separated_pair(expr, opt(line_ending), expr),
735 preceded(line_ending, delimited(tag("</"), identifier, char('>'))),
736 ))(input)?;
737
738 let lhs = Box::new(lhs_expr);
739 let rhs = Box::new(rhs_expr);
740
741 let op = match expr_type {
742 "plus_exp" => ExprOp::Add,
743 "sub_exp" => ExprOp::Sub,
744 "and_exp" => ExprOp::And,
745 "or_exp" => ExprOp::Or,
746 "xor_exp" => ExprOp::Xor,
747 "lshift_exp" => ExprOp::Lshift,
748 "rshift_exp" => ExprOp::Rshift,
749 "mult_exp" => ExprOp::Mult,
750 _ => todo!(),
751 };
752
753 Ok((input, Expr::Binary((op, lhs, rhs))))
754}
755
756fn expr(input: &str) -> Res<&str, Expr> {
757 alt((
765 start_expr,
766 end_expr,
767 next2_expr,
768 const_expr,
769 operand_expr,
770 field_expr,
771 unary_expr,
772 binary_expr,
773 ))(input)
774}
775
776fn context_op(input: &str) -> Res<&str, ContextOp> {
777 let res = tuple((
778 terminated(
779 delimited(tag("<context_op"), take_until(">"), tag(">")),
780 line_ending,
781 ),
782 terminated(expr, terminated(line_ending, tag("</context_op>"))),
783 ))(input)
784 .map(|(next, res)| {
785 let (_, attrs) = attrs(res.0).finish().unwrap();
787 let context_op = ContextOp {
789 i: u32dec(attrs[0].1),
790 shift: u32dec(attrs[1].1),
791 mask: u32hex(attrs[2].1),
792 expr: res.1,
793 };
794 (next, context_op)
795 });
796
797 res
802}
803
804fn context_ops(input: &str) -> Res<&str, Vec<ContextOp>> {
805 separated_list1(line_ending, context_op)(input)
806}
807
808fn const_template(input: &str) -> Res<&str, ConstTemplate> {
809 delimited(tag("<const_tpl"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
811 let (_, attrs) = attrs(res).finish().unwrap();
812 let const_template = match attrs[0].1 {
815 "spaceid" => ConstTemplate::SpaceId(attrs[1].1.to_string()),
816 "real" => ConstTemplate::Val(u64hex(attrs[1].1)),
817 "handle" => {
818 let expr = if attrs.len() > 2 && attrs[2].0 == "s" {
819 match attrs[2].1 {
820 "offset_plus" => Some(HandleExpr::OffsetPlus(u32hex(attrs[3].1) & 0xffff)),
821 _ => None,
822 }
823 } else {
824 None
825 };
826
827 ConstTemplate::Handle((u32dec(attrs[1].1), expr))
828 },
829 "relative" => ConstTemplate::Relative(u32hex(attrs[1].1)),
830 "start" => ConstTemplate::Start,
831 "next" => ConstTemplate::Next,
832 "curspace" => ConstTemplate::CurSpace,
833 "curspace_size" => ConstTemplate::CurSpaceSize,
834 _ => todo!(),
835 };
836
837 (next, const_template)
838 })
839}
840
841fn nonnull_varnode_template(input: &str) -> Res<&str, Option<VarnodeTemplate>> {
842 delimited(
844 tag("<varnode_tpl>"),
845 tuple((const_template, const_template, const_template)),
846 tag("</varnode_tpl>"),
847 )(input)
848 .map(|(next, res)| {
849 let varnode_template = VarnodeTemplate {
851 space_template: res.0,
852 offset_template: res.1,
853 size_template: res.2,
854 };
855 (next, Some(varnode_template))
856 })
857}
858
859fn null_varnode_template(input: &str) -> Res<&str, Option<VarnodeTemplate>> {
860 tag("<null/>")(input).map(|(next, _)| (next, None))
861}
862
863fn varnode_template(input: &str) -> Res<&str, Option<VarnodeTemplate>> {
864 alt((null_varnode_template, nonnull_varnode_template))(input)
865}
866
867fn op_template(input: &str) -> Res<&str, ConsTemplate> {
868 preceded(
870 opt(tag("<null/>")),
871 tuple((
872 delimited(tag("<op_tpl"), take_until(">"), tag(">")),
873 terminated(varnode_template, line_ending),
874 terminated(
875 separated_list0(line_ending, varnode_template),
876 terminated(line_ending, tag("</op_tpl>")),
877 ),
878 )),
879 )(input)
880 .map(|(next, res)| {
881 let (_, attrs) = attrs(res.0).finish().unwrap();
883 let op_template = OpTemplate {
884 code: attrs[0].1.to_string(),
885 output: res.1,
886 inputs: res.2.into_iter().flatten().collect(),
887 };
888 (next, ConsTemplate::Op(op_template))
890 })
891}
892
893fn handle_template(input: &str) -> Res<&str, ConsTemplate> {
894 preceded(
895 opt(tag("<null/>")),
896 delimited(
897 tag("<handle_tpl>"),
898 tuple((
899 const_template,
900 const_template,
901 const_template,
902 const_template,
903 const_template,
904 const_template,
905 const_template,
906 )),
907 tag("</handle_tpl>"),
908 ),
909 )(input)
910 .map(|(next, res)| {
911 let pointer_template = VarnodeTemplate {
912 space_template: res.2,
913 offset_template: res.3,
914 size_template: res.4,
915 };
916
917 let handle_template = HandleTemplate {
918 space_template: res.0,
919 size_template: res.1,
920 pointer_template,
921 temp_space_template: res.5,
922 temp_offset_template: res.6,
923 };
924
925 (next, ConsTemplate::Handle(handle_template))
926 })
927}
928
929fn null_ops(input: &str) -> Res<&str, Vec<ConsTemplate>> {
930 tag("<null/>")(input).map(|(next, _)| (next, vec![]))
931}
932
933fn constructor_template(input: &str) -> Res<&str, ConstructorTemplate> {
934 tuple((
935 terminated(
936 delimited(tag("<construct_tpl"), take_until(">"), tag(">")),
937 line_ending,
938 ),
939 terminated(
940 alt((
941 terminated(
942 separated_list0(line_ending, alt((op_template, handle_template))),
943 line_ending,
944 ),
945 null_ops,
946 )),
947 tag("</construct_tpl>"),
948 ),
949 ))(input)
950 .map(|(next, res)| {
951 let (_, attrs) = attrs(res.0).finish().unwrap();
953
954 let num_labels = match attrs.len() {
955 0 => 0,
956 1 => u32dec(attrs[0].1),
957 _ => todo!(),
958 };
959
960 let constructor_template = ConstructorTemplate {
961 num_labels,
962 statements: res.1,
963 };
964
965 (next, constructor_template)
966 })
967}
968
969fn constructor(input: &str) -> Res<&str, Constructor> {
970 let res = tuple((
971 delimited(
972 tag("<constructor "),
973 take_until(">"),
974 terminated(tag(">"), line_ending),
975 ),
976 terminated(
977 tuple((
978 opt(terminated(operands, line_ending)),
979 opt(terminated(print_commands, line_ending)),
980 opt(terminated(context_ops, line_ending)),
981 opt(terminated(constructor_template, line_ending)),
982 )),
983 tag("</constructor>"),
984 ),
985 ))(input)
986 .map(|(next, res)| {
987 let (_, attrs) = attrs(res.0).finish().unwrap();
989 let mut iter = attrs[3].1.split(":");
993
994 let constructor = Constructor {
995 _parent: u32hex(attrs[0].1),
996 _first: i32dec(attrs[1].1),
997 length: u32dec(attrs[2].1),
998 operands: res.1.0.unwrap_or_default(),
999 print_commands: res.1.1,
1000 context_ops: res.1.2.unwrap_or_default(),
1001 template: res.1.3,
1002 line: (u64dec(iter.next().unwrap()) as usize, u64dec(iter.next().unwrap()) as usize),
1003 };
1004
1005 (next, constructor)
1010 });
1011
1012 res
1017}
1018
1019fn mask_word(input: &str) -> Res<&str, MaskWord> {
1020 delimited(tag("<mask_word "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1021 let (_, attrs) = attrs(res).finish().unwrap();
1023 let mask_word = MaskWord {
1024 mask: u32hex(attrs[0].1),
1025 val: u32hex(attrs[1].1),
1026 };
1027 (next, mask_word)
1028 })
1029}
1030
1031fn pattern_block(input: &str) -> Res<&str, PatternBlock> {
1032 tuple((
1033 terminated(
1034 delimited(tag("<pat_block "), take_until(">"), tag(">")),
1035 line_ending,
1036 ),
1037 alt((
1038 terminated(
1039 separated_list1(line_ending, preceded(space0, mask_word)),
1040 line_ending,
1041 ),
1042 separated_list0(line_ending, mask_word),
1043 )),
1044 tag("</pat_block>"),
1045 ))(input)
1046 .map(|(next, res)| {
1047 let (_, attrs) = attrs(res.0).finish().unwrap();
1049 let pattern_block = PatternBlock {
1050 offset: u32dec(attrs[0].1),
1051 nonzero: u32dec(attrs[1].1),
1052 masks: res.1,
1053 };
1054 (next, pattern_block)
1055 })
1056}
1057
1058fn combine_pattern(input: &str) -> Res<&str, DecisionPattern> {
1059 delimited(
1060 terminated(tag("<combine_pat>"), line_ending),
1061 separated_pair(decision_pattern, line_ending, decision_pattern),
1062 preceded(line_ending, tag("</combine_pat>")),
1063 )(input)
1064 .map(|(next, res)| {
1065 (
1067 next,
1068 DecisionPattern::Combine((Box::new(res.0), Box::new(res.1))),
1069 )
1070 })
1071}
1072
1073fn context_pattern(input: &str) -> Res<&str, DecisionPattern> {
1074 delimited(
1075 terminated(tag("<context_pat>"), line_ending),
1076 pattern_block,
1077 preceded(line_ending, tag("</context_pat>")),
1078 )(input)
1079 .map(|(next, res)| {
1080 (next, DecisionPattern::Context(res))
1082 })
1083}
1084
1085fn instruction_pattern(input: &str) -> Res<&str, DecisionPattern> {
1086 delimited(
1087 terminated(tag("<instruct_pat>"), line_ending),
1088 pattern_block,
1089 preceded(line_ending, tag("</instruct_pat>")),
1090 )(input)
1091 .map(|(next, res)| {
1092 (next, DecisionPattern::Instruction(res))
1094 })
1095}
1096
1097fn decision_pattern(input: &str) -> Res<&str, DecisionPattern> {
1098 alt((context_pattern, instruction_pattern, combine_pattern))(input)
1099}
1100
1101fn decision_pair(input: &str) -> Res<&str, (u32, DecisionPattern)> {
1102 tuple((
1103 terminated(
1104 delimited(tag("<pair "), take_until(">"), tag(">")),
1105 line_ending,
1106 ),
1107 terminated(terminated(decision_pattern, line_ending), tag("</pair>")),
1108 ))(input)
1109 .map(|(next, res)| {
1110 let (_, attrs) = attrs(res.0).finish().unwrap();
1111 let id = u32dec(attrs[0].1);
1112 (next, (id, res.1))
1113 })
1114}
1115
1116fn decision_pairs(input: &str) -> Res<&str, DecisionTree> {
1117 separated_list1(line_ending, decision_pair)(input).map(|(next, res)| {
1118 (next, DecisionTree::Leaf(res))
1120 })
1121}
1122
1123fn decision_body(input: &str) -> Res<&str, DecisionTree> {
1124 alt((decision_pairs, decision_tree))(input)
1125}
1126
1127fn decision_tree(input: &str) -> Res<&str, DecisionTree> {
1128 tuple((
1130 delimited(
1131 tag("<decision"),
1132 take_until(">"),
1133 terminated(tag(">"), line_ending),
1134 ),
1135 terminated(
1136 alt((
1137 terminated(separated_list1(line_ending, decision_body), line_ending),
1138 separated_list0(line_ending, decision_body),
1139 )),
1140 tag("</decision>"),
1141 ),
1142 ))(input)
1143 .map(|(next, res)| {
1144 let (_, attrs) = attrs(res.0).finish().unwrap();
1146 let is_context = to_bool(attrs[1].1);
1148 let start = u32dec(attrs[2].1);
1149 let size = u32dec(attrs[3].1);
1150 (
1151 next,
1152 DecisionTree::NonLeaf((is_context, start, size, res.1)),
1153 )
1154 })
1155}
1156
1157fn subtable_sym(input: &str) -> Res<&str, Symbol> {
1158 tuple((
1160 delimited(
1161 tag("<subtable_sym "),
1162 take_until(">"),
1163 terminated(tag(">"), line_ending),
1164 ),
1165 terminated(
1166 tuple((
1167 terminated(separated_list1(line_ending, constructor), line_ending),
1168 decision_tree,
1169 )),
1170 preceded(line_ending, tag("</subtable_sym>")),
1171 ),
1172 ))(input)
1173 .map(|(next, res)| {
1174 let (_, attrs) = attrs(res.0).finish().unwrap();
1176 let id = u32hex(attrs[1].1);
1178 let subtable = Subtable {
1179 name: attrs[0].1.to_string(),
1180 scope: u32hex(attrs[2].1),
1181 constructors: res.1.0,
1182 decision_tree: res.1.1,
1183 };
1184 (
1185 next,
1186 Symbol {
1187 id,
1188 body: SymbolBody::Subtable(subtable),
1189 },
1190 )
1191 })
1192}
1193
1194fn start_sym(input: &str) -> Res<&str, Symbol> {
1195 delimited(tag("<start_sym "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1196 let (_, attrs) = attrs(res).finish().unwrap();
1197 let id = u32hex(attrs[1].1);
1198 let sym_head = SymbolHead {
1199 name: attrs[0].1.to_string(),
1200 scope: u32hex(attrs[2].1),
1201 };
1202 (
1203 next,
1204 Symbol {
1205 id,
1206 body: SymbolBody::Start(sym_head),
1207 },
1208 )
1209 })
1210}
1211
1212fn end_sym(input: &str) -> Res<&str, Symbol> {
1213 delimited(tag("<end_sym "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1214 let (_, attrs) = attrs(res).finish().unwrap();
1215 let id = u32hex(attrs[1].1);
1216 let sym_head = SymbolHead {
1217 name: attrs[0].1.to_string(),
1218 scope: u32hex(attrs[2].1),
1219 };
1220 (
1221 next,
1222 Symbol {
1223 id,
1224 body: SymbolBody::End(sym_head),
1225 },
1226 )
1227 })
1228}
1229
1230fn next2_sym(input: &str) -> Res<&str, Symbol> {
1231 delimited(tag("<next2_sym "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1232 let (_, attrs) = attrs(res).finish().unwrap();
1233 let id = u32hex(attrs[1].1);
1234 let sym_head = SymbolHead {
1235 name: attrs[0].1.to_string(),
1236 scope: u32hex(attrs[2].1),
1237 };
1238 (
1239 next,
1240 Symbol {
1241 id,
1242 body: SymbolBody::Next2(sym_head),
1243 },
1244 )
1245 })
1246}
1247
1248fn varnode_sym(input: &str) -> Res<&str, Symbol> {
1249 terminated(
1250 delimited(
1251 tag("<varnode_sym "),
1252 take_until(">"),
1253 terminated(tag(">"), line_ending),
1254 ),
1255 tag("</varnode_sym>"),
1256 )(input)
1257 .map(|(next, res)| {
1258 let (_, attrs) = attrs(res).finish().unwrap();
1259 let id = u32hex(attrs[1].1);
1261 let varnode = VarnodeSym {
1262 name: attrs[0].1.to_string(),
1263 scope: u32hex(attrs[2].1),
1264 space: attrs[3].1.parse::<AddressSpace>().unwrap(),
1265 offset: u64hex(attrs[4].1),
1266 size: u64dec(attrs[5].1),
1267 };
1268 (
1269 next,
1270 Symbol {
1271 id,
1272 body: SymbolBody::Varnode(varnode),
1273 },
1274 )
1275 })
1276}
1277
1278fn tokenfield(input: &str) -> Res<&str, Field> {
1279 delimited(tag("<tokenfield"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1280 let (_, attrs) = attrs(res).finish().unwrap();
1281 let token_field = TokenField {
1282 big_endian: to_bool(attrs[0].1),
1283 sign_bit: to_bool(attrs[1].1),
1284 start_bit: u32dec(attrs[2].1),
1285 end_bit: u32dec(attrs[3].1),
1286 start_byte: u32dec(attrs[4].1),
1287 end_byte: u32dec(attrs[5].1),
1288 shift: u32dec(attrs[6].1),
1289 };
1290 (next, Field::Token(token_field))
1291 })
1292}
1293
1294fn field(input: &str) -> Res<&str, Field> {
1295 alt((contextfield, tokenfield))(input)
1296}
1297
1298fn valuetab(input: &str) -> Res<&str, u64> {
1299 delimited(tag("<valuetab"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1301 let (_, attrs) = attrs(res).finish().unwrap();
1302 let val = u64dec(attrs[0].1);
1303 (next, val)
1304 })
1305}
1306
1307fn valuemap_sym(input: &str) -> Res<&str, Symbol> {
1308 tuple((
1309 delimited(
1310 tag("<valuemap_sym "),
1311 take_until(">"),
1312 terminated(tag(">"), line_ending),
1313 ),
1314 terminated(
1315 separated_pair(
1316 field,
1317 line_ending,
1318 terminated(separated_list0(line_ending, valuetab), line_ending),
1319 ),
1320 tag("</valuemap_sym>"),
1321 ),
1322 ))(input)
1323 .map(|(next, res)| {
1324 let (_, attrs) = attrs(res.0).finish().unwrap();
1325 let id = u32hex(attrs[1].1);
1326 let valuemap = Valuemap {
1327 name: attrs[0].1.to_string(),
1328 scope: u32hex(attrs[2].1),
1329 field: res.1 .0,
1330 vars: res.1 .1,
1331 };
1332 (
1333 next,
1334 Symbol {
1335 id,
1336 body: SymbolBody::Valuemap(valuemap),
1337 },
1338 )
1339 })
1340}
1341
1342fn nonnull_var(input: &str) -> Res<&str, Option<u32>> {
1343 delimited(tag("<var"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1344 let (_, attrs) = attrs(res).finish().unwrap();
1345 let id = u32hex(attrs[0].1);
1346 (next, Some(id))
1347 })
1348}
1349
1350fn null_var(input: &str) -> Res<&str, Option<u32>> {
1351 tag("<null/>")(input).map(|(next, _)| (next, None))
1352}
1353
1354fn var(input: &str) -> Res<&str, Option<u32>> {
1355 alt((nonnull_var, null_var))(input)
1357}
1358
1359fn varlist_sym(input: &str) -> Res<&str, Symbol> {
1360 tuple((
1362 delimited(
1363 tag("<varlist_sym "),
1364 take_until(">"),
1365 terminated(tag(">"), line_ending),
1366 ),
1367 terminated(
1368 separated_pair(
1369 field,
1370 line_ending,
1371 terminated(separated_list0(line_ending, var), line_ending),
1372 ),
1373 tag("</varlist_sym>"),
1374 ),
1375 ))(input)
1376 .map(|(next, res)| {
1377 let (_, attrs) = attrs(res.0).finish().unwrap();
1378 let id = u32hex(attrs[1].1);
1379 let varlist = Varlist {
1380 name: attrs[0].1.to_string(),
1381 scope: u32hex(attrs[2].1),
1382 field: res.1.0,
1383 vars: res.1.1,
1384 };
1385 (
1386 next,
1387 Symbol {
1388 id,
1389 body: SymbolBody::Varlist(varlist),
1390 },
1391 )
1392 })
1393}
1394
1395fn name(input: &str) -> Res<&str, Option<String>> {
1396 delimited(tag("<nametab"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1398 let (_, attrs) = attrs(res).finish().unwrap();
1399
1400 if attrs.is_empty() {
1401 (next, None)
1402 } else {
1403 let name = attrs[0].1.to_string();
1404 (next, Some(name))
1405 }
1406 })
1407}
1408
1409fn name_sym(input: &str) -> Res<&str, Symbol> {
1410 tuple((
1412 delimited(
1413 tag("<name_sym "),
1414 take_until(">"),
1415 terminated(tag(">"), line_ending),
1416 ),
1417 terminated(
1418 separated_pair(
1419 field,
1420 line_ending,
1421 terminated(separated_list0(line_ending, name), line_ending),
1422 ),
1423 tag("</name_sym>"),
1424 ),
1425 ))(input)
1426 .map(|(next, res)| {
1427 let (_, attrs) = attrs(res.0).finish().unwrap();
1428 let id = u32hex(attrs[1].1);
1429 let nametab = NameTable {
1430 name: attrs[0].1.to_string(),
1431 scope: u32hex(attrs[2].1),
1432 field: res.1.0,
1433 names: res.1.1,
1434 };
1435 (
1436 next,
1437 Symbol {
1438 id,
1439 body: SymbolBody::Nametab(nametab),
1440 },
1441 )
1442 })
1443}
1444
1445fn value_sym(input: &str) -> Res<&str, Symbol> {
1446 tuple((
1447 delimited(
1448 tag("<value_sym "),
1449 take_until(">"),
1450 terminated(tag(">"), line_ending),
1451 ),
1452 terminated(tokenfield, preceded(line_ending, tag("</value_sym>"))),
1453 ))(input)
1454 .map(|(next, res)| {
1455 let (_, attrs) = attrs(res.0).finish().unwrap();
1456 let id = u32hex(attrs[1].1);
1457 let value = Value {
1458 name: attrs[0].1.to_string(),
1459 scope: u32hex(attrs[2].1),
1460 field: res.1,
1461 };
1462 (
1463 next,
1464 Symbol {
1465 id,
1466 body: SymbolBody::Value(value),
1467 },
1468 )
1469 })
1470}
1471
1472fn context_sym(input: &str) -> Res<&str, Symbol> {
1473 tuple((
1474 delimited(
1475 tag("<context_sym "),
1476 take_until(">"),
1477 terminated(tag(">"), line_ending),
1478 ),
1479 terminated(contextfield, preceded(line_ending, tag("</context_sym>"))),
1480 ))(input)
1481 .map(|(next, res)| {
1482 let (_, attrs) = attrs(res.0).finish().unwrap();
1483
1484 let context_field = match res.1 {
1485 Field::Context(ctx_field) => ctx_field,
1486 _ => panic!(),
1487 };
1488
1489 let id = u32hex(attrs[1].1);
1490
1491 let context = Context {
1492 name: attrs[0].1.to_string(),
1493 scope: u32hex(attrs[2].1),
1494 varnode: u32hex(attrs[3].1),
1495 low: u32dec(attrs[4].1),
1496 high: u32dec(attrs[5].1),
1497 flow: to_bool(attrs[6].1),
1498 context_field,
1499 };
1500 (
1501 next,
1502 Symbol {
1503 id,
1504 body: SymbolBody::Context(context),
1505 },
1506 )
1507 })
1508}
1509
1510fn operand_sym(input: &str) -> Res<&str, Symbol> {
1511 tuple((
1512 delimited(
1513 tag("<operand_sym "),
1514 take_until(">"),
1515 terminated(tag(">"), line_ending),
1516 ),
1517 terminated(
1518 tuple((operand_expr, opt(preceded(line_ending, expr)))),
1519 preceded(line_ending, tag("</operand_sym>")),
1520 ),
1521 ))(input)
1522 .map(|(next, res)| {
1523 let (_, attrs) = attrs(res.0).finish().unwrap();
1524 let operand_expr = match res.1 .0 {
1527 Expr::Operand(op_expr) => op_expr,
1528 _ => panic!(),
1529 };
1530
1531 let kvs: HashMap<&str, &str> = attrs.into_iter().collect();
1532 let id = u32hex(kvs["id"]);
1533
1534 let operand = Operand {
1535 name: kvs["name"].to_string(),
1536 scope: u32hex(kvs["scope"]),
1537 subsym: kvs.get("subsym").map(|s| u32hex(s)).unwrap_or(0),
1538 off: kvs.get("off").map(|s| u64dec(s)).unwrap_or(0),
1539 base: kvs.get("base").map(|s| i64dec(s)).unwrap_or(0),
1540 min_len: kvs.get("minlen").map(|s| u64dec(s)).unwrap_or(0),
1541 idx: kvs.get("idx").map(|s| u64dec(s)).unwrap_or(0),
1542 is_code: kvs.get("code").map(|s| to_bool(s)).unwrap_or(false),
1543 operand_expr,
1544 expr: res.1 .1,
1545 };
1546 (
1547 next,
1548 Symbol {
1549 id,
1550 body: SymbolBody::Operand(operand),
1551 },
1552 )
1553 })
1554}
1555
1556fn userop(input: &str) -> Res<&str, Symbol> {
1557 delimited(tag("<userop "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1558 let (_, attrs) = attrs(res).finish().unwrap();
1559 let id = u32hex(attrs[1].1);
1560
1561 let userop = UserOp {
1562 name: attrs[0].1.to_string(),
1563 scope: u32hex(attrs[2].1),
1564 idx: u32dec(attrs[3].1),
1565 };
1566
1567 (
1568 next,
1569 Symbol {
1570 id,
1571 body: SymbolBody::UserOp(userop),
1572 },
1573 )
1574 })
1575}
1576
1577fn sym(input: &str) -> Res<&str, Symbol> {
1578 alt((
1580 subtable_sym,
1581 varnode_sym,
1582 start_sym,
1583 end_sym,
1584 next2_sym,
1585 valuemap_sym,
1586 varlist_sym,
1587 name_sym,
1588 value_sym,
1589 context_sym,
1590 operand_sym,
1591 userop,
1592 ))(input)
1593}
1594
1595fn symbol(input: &str) -> Res<&str, Symbol> {
1596 alt((scope, sym_head, sym))(input)
1597}
1598
1599fn symbol_table(input: &str) -> Res<&str, Vec<Symbol>> {
1600 tuple((
1601 terminated(
1602 delimited(tag("<symbol_table "), take_until(">"), tag(">")),
1603 line_ending,
1604 ),
1605 terminated(
1606 separated_list1(line_ending, symbol),
1607 preceded(line_ending, tag("</symbol_table>")),
1608 ),
1609 ))(input)
1610 .map(|(next, res)| {
1611 (next, res.1)
1613 })
1614}
1615
1616fn attrs(input: &str) -> Res<&str, Vec<(&str, &str)>> {
1617 preceded(
1619 space0,
1620 separated_list0(char(' '), separated_pair(identifier, char('='), string)),
1621 )(input)
1622}
1623
1624pub fn program(input: &str) -> Res<&str, Program> {
1625 tuple((
1626 terminated(
1627 delimited(tag("<sleigh "), take_until(">"), tag(">")),
1628 line_ending,
1629 ),
1630 terminated(source_files, line_ending),
1631 terminated(spaces, line_ending),
1632 terminated(symbol_table, line_ending),
1633 ))(input)
1634 .map(|(next, res)| {
1635 let (_, attrs) = attrs(res.0).finish().unwrap();
1636 let prog = Program {
1637 version: u32dec(attrs[0].1),
1638 bigendian: attrs[1].1.parse::<bool>().unwrap(),
1639 align: u32dec(attrs[2].1),
1640 uniqbase: u64hex(attrs[3].1),
1641 default_space: res.2.0.to_string(),
1642 spaces: res.2 .1,
1643 symbols: res.3,
1644 };
1645 (next, prog)
1646 })
1647}
1648
1649fn identifier(input: &str) -> Res<&str, &str> {
1650 recognize(pair(
1651 alt((alpha1, tag("_"), tag("."))),
1652 many0_count(alt((alphanumeric1, tag("_"), tag(".")))),
1653 ))(input)
1654}
1655
1656fn string(input: &str) -> Res<&str, &str> {
1657 delimited(char('"'), take_until("\""), char('"'))(input)
1658}
1659
1660pub fn read_reg(
1661 reg: &VarnodeSym,
1662 reg_space: &BitVec<u8, Msb0>,
1663) -> Vec<u32> {
1664 let mut words = vec![];
1665 let mut size_left = reg.size * 8;
1666
1667 while size_left > 0 {
1668 let start = (reg.offset * 8 + (words.len() as u64) * 32) as usize;
1669 let end = start + 32;
1670 words.push(reg_space[start..end].load_be::<u32>());
1671 size_left -= size_left.min(32);
1672 }
1673
1674 words
1675}
1676
1677pub fn get_word(words: &[u8], start: usize, size: usize) -> u64 {
1678 let mut word: u64 = 0;
1679
1680 for i in 0..size {
1681 if start + i >= words.len() {
1682 break;
1683 }
1684
1685 word = (word << 8) | (words[start + i] as u64);
1686 }
1687
1688 word
1689}
1690
1691pub fn get_word_le(words: &[u8], start: usize, size: usize) -> u64 {
1692 let mut word: u64 = 0;
1693
1694 for i in 0..size {
1695 if start + i >= words.len() {
1696 break;
1697 }
1698
1699 word |= (words[start + i] as u64) << (i * 8);
1700 }
1701
1702 word
1703}
1704
1705#[allow(dead_code)]
1706pub struct SleighLanguage {
1707 pub language: Language,
1708 pub bit_align: usize,
1709 pub symbols: HashMap<u32, Symbol>,
1710 pub spaces: HashMap<String, u64>,
1711 pub _varnodes: HashMap<String, VarnodeSym>,
1712 pub varnode_map: HashMap<(u64, u64), String>,
1713 pub context_syms: HashMap<String, Context>,
1714 pub reg_sizes: Vec<Vec<Varnode>>,
1715 pub registers: HashMap<(u64, u64), Varnode>,
1716 pub reg_space_size: usize,
1717 pub insn_table_id: u32,
1718 pub context_reg: VarnodeSym,
1719}
1720
1721impl SleighLanguage {
1722 pub fn create(lang_id: &str, compiler_id: &str) -> SleighLanguage {
1723 let arch_family = lang_id.split(":").next().unwrap();
1724 let sla_contents = get_sla(arch_family, lang_id).unwrap();
1725 let (_, sla) = program(&sla_contents).finish().unwrap();
1726
1727 let mut symbols: HashMap<u32, Symbol> = HashMap::new();
1728 let mut spaces: HashMap<String, u64> = HashMap::new();
1729 let mut varnodes: HashMap<String, VarnodeSym> = HashMap::new();
1730 let mut varnode_map: HashMap<(u64, u64), String> = HashMap::new();
1731 let mut rev_varnode_map: HashMap<String, Varnode> = HashMap::new();
1732 let mut registers: HashMap<(u64, u64), Varnode> = HashMap::new();
1733 let mut context_syms: HashMap<String, Context> = HashMap::new();
1734 let mut reg_space_size: usize = 0;
1735 let mut insn_table_id = 0;
1736
1737 for space in &sla.spaces {
1738 spaces.insert(space.name.clone(), spaces.len() as u64);
1739 }
1740
1741 for sym in &sla.symbols {
1742 match &sym.body {
1743 SymbolBody::Subtable(subtable) => {
1744 if subtable.name == "instruction" {
1745 insn_table_id = sym.id;
1746 }
1747 }
1748 SymbolBody::Varnode(varnode) => {
1749 varnodes.insert(varnode.name.clone(), varnode.clone());
1750
1751 if varnode.space == AddressSpace::Register {
1752 reg_space_size = reg_space_size.max((varnode.offset + varnode.size) as usize);
1753 varnode_map.insert((varnode.offset, varnode.size), varnode.name.clone());
1754 rev_varnode_map.insert(varnode.name.clone(), Varnode {
1755 name: Some(varnode.name.clone()),
1756 space: varnode.space,
1757 offset: varnode.offset,
1758 size: varnode.size,
1759 });
1760 registers.insert((varnode.offset, varnode.size), Varnode {
1761 name: Some(varnode.name.clone()),
1762 space: varnode.space,
1763 offset: varnode.offset,
1764 size: varnode.size,
1765 });
1766 }
1767 }
1768 SymbolBody::Context(ctx) => {
1769 context_syms.insert(ctx.name.clone(), ctx.clone());
1770 }
1771 _ => (),
1772 }
1773
1774 symbols.insert(sym.id, sym.clone());
1775 }
1776
1777 let ctx_reg = varnodes["contextreg"].clone();
1778 let lang = get_language(arch_family, lang_id, compiler_id, &rev_varnode_map).unwrap();
1779
1780 let mut registers = HashMap::new();
1781 let mut max_off = 0;
1782
1783 for ((start, sz), name) in &varnode_map {
1784 let register = Varnode {
1785 name: Some(name.clone()),
1786 space: AddressSpace::Register,
1787 offset: *start,
1788 size: *sz,
1789 };
1790
1791 registers.insert((*start, *sz), register.clone());
1792 max_off = max_off.max(*start + *sz);
1793 }
1794
1795 let mut reg_sizes: Vec<Vec<Varnode>> = Vec::with_capacity(max_off as usize);
1796
1797 for _ in 0..max_off {
1798 reg_sizes.push(vec![]);
1799 }
1800
1801 for reg in registers.values() {
1802 reg_sizes[reg.offset as usize].push(reg.clone());
1803 }
1804
1805 for sizes in &mut reg_sizes {
1806 sizes.sort_by(|a, b| a.size.cmp(&b.size));
1807 }
1808
1809 SleighLanguage {
1810 language: lang,
1811 bit_align: (sla.align * 8) as usize,
1812 symbols,
1813 spaces,
1814 _varnodes: varnodes,
1815 varnode_map,
1816 context_syms,
1817 registers,
1818 reg_sizes,
1819 reg_space_size,
1820 insn_table_id,
1821 context_reg: ctx_reg,
1822 }
1823 }
1824}