libpcode/
sla_parser.rs

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        // if matches!(self.temp_space_template, ConstTemplate::SpaceId(_)) {
363        //     write!(f, "[{}]({})", self.indirect_template, self.varnode_template)
364        // } else {
365        //     write!(f, "{}", self.varnode_template)
366        // }
367    }
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        //println!("{} {:?}", res, attrs);
479        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        //println!("{} {:?}", res, attrs);
540        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        //println!("{} {:?}", res, attrs);
584        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        //println!("{} {:?}", res, attrs);
603        (next, u32hex(attrs[0].1))
604    });
605
606    // if res.is_err() {
607    //     panic!("Could not parse operand at {}", input);
608    // }
609    
610    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    //println!("const {}", &input[0..20]);
641    delimited(tag("<intb"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
642        //println!("foobar {:?}", res);
643        let (_, attrs) = attrs(res).finish().unwrap();
644        //println!("{} {:?}", res, attrs);
645        (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        //println!("{} {:?}", res, attrs);
653        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    //println!("* field {}", &input[0..20]);
679    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    //println!("* unary {}", &input[0..20]);
696    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    //println!("* binary {}", &input[0..20]);
721    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    //println!("* context expr {}", &input[0..20]);
758    
759
760    // if res.is_err() {
761    //     panic!("Could not parse expr at {}", input);
762    // }
763
764    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        //println!("context {:?}", res.0);
786        let (_, attrs) = attrs(res.0).finish().unwrap();
787        //println!("{} {:?}", res.0, attrs);
788        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    // if res.is_err() {
798    //     panic!("Could not parse context op at {}", input);
799    // }
800
801    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    //println!("const {}", &input[0..20]);
810    delimited(tag("<const_tpl"), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
811        let (_, attrs) = attrs(res).finish().unwrap();
812        //println!("{} {:?}", res, attrs);
813
814        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    //println!("vnode {}", &input[0..20]);
843    delimited(
844        tag("<varnode_tpl>"),
845        tuple((const_template, const_template, const_template)),
846        tag("</varnode_tpl>"),
847    )(input)
848    .map(|(next, res)| {
849        //println!("varnode {:?}", res.1);
850        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    //println!("op {}", &input[0..20]);
869    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        //println!("op {:?}", res.1);
882        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        // println!("{} {}", op_template.code, op_template.inputs.len());
889        (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        //println!("construtor_tpl {:?}", res);
952        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        //println!("constructor {:?}", res.1);
988        let (_, attrs) = attrs(res.0).finish().unwrap();
989        //println!("{:?}", attrs);
990
991        // println!("{}", attrs[3].1);
992        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        // if constructor.line.0 == 0 && constructor.line.1 == 8255 {
1006        //     println!("{}", &input[..2000]);
1007        // }
1008
1009        (next, constructor)
1010    });
1011
1012    // if res.is_err() {
1013    //     panic!("Could not parse constructor at {}", input);
1014    // }
1015
1016    res
1017}
1018
1019fn mask_word(input: &str) -> Res<&str, MaskWord> {
1020    delimited(tag("<mask_word "), take_until("/>"), tag("/>"))(input).map(|(next, res)| {
1021        //println!("mask word {:?}", res);
1022        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        //println!("pattern block {:?}", res);
1048        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        //println!("combine pattern {:?}", res);
1066        (
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        //println!("context pattern {:?}", res);
1081        (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        //println!("instruct pattern {:?}", res);
1093        (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        //println!("decision pairs {:?}", res);
1119        (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    //println!("decision tree {}", &input[0..20]);
1129    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        //println!("decision body {:?}", res);
1145        let (_, attrs) = attrs(res.0).finish().unwrap();
1146        //println!("{} {:?}", res.0, attrs);
1147        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    //println!("subtable_sym {}", &input[0..50]);
1159    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        //println!("{:?}", res.1.0.len());
1175        let (_, attrs) = attrs(res.0).finish().unwrap();
1176        //println!("{} {:?}", res.0, attrs);
1177        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        //println!("{} {:?}", res, attrs);
1260        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    //println!("valuetab {}", &input[0..20]);
1300    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    //println!("var {}", &input[0..20]);
1356    alt((nonnull_var, null_var))(input)
1357}
1358
1359fn varlist_sym(input: &str) -> Res<&str, Symbol> {
1360    //println!("varlist {}", &input[0..50]);
1361    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    //println!("name {}", &input[0..20]);
1397    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    //println!("varlist {}", &input[0..50]);
1411    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        //println!("{} {:?}", res.0, attrs);
1525
1526        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    //println!("** {}", &input[0..20]);
1579    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        //println!("{:?}", res.1.len());
1612        (next, res.1)
1613    })
1614}
1615
1616fn attrs(input: &str) -> Res<&str, Vec<(&str, &str)>> {
1617    //println!("{:?}", &input);
1618    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}