ACPI AML decompiler w/ CFG recovery and structured pseudocode
1#include "t.h"
2
3#include "cf.h"
4#include "p.h"
5
6int t_cf(void) {
7 uint8_t ifelse[] = {0x14,0x15,'I','F','E','0',0x01,0xa0,0x06,0x68,0x70,0x0a,0x01,0x60,0xa1,0x05,0x70,0x0a,0x02,0x60,0xa4,0x60};
8 tobi_parse_result r;
9 T_CHECK(tobi_parse(ifelse, sizeof(ifelse), 0, &r));
10 T_CHECK(tobi_cf_recover(r.root, &r.diag));
11 tobi_ir *ifn = r.root->child[0]->child[0]->child[0];
12 T_CHECK(ifn->kind == TOBI_IR_IF && ifn->child_len == 3);
13 char *dot = tobi_cf_dot(r.root);
14 T_STR(dot, "digraph tobi_cfg");
15 T_STR(dot, "then");
16 T_STR(dot, "else");
17 free(dot);
18 tobi_parse_result_free(&r);
19
20 uint8_t wh[] = {0x14,0x20,'W','L','O','0',0x01,0x70,0x0a,0x03,0x60,0xa2,0x13,0x60,0xa0,0x06,0x68,0x70,0x0a,0x01,0x61,0xa1,0x05,0x70,0x0a,0x02,0x61,0x74,0x60,0x01,0x60,0xa4,0x61};
21 T_CHECK(tobi_parse(wh, sizeof(wh), 0, &r));
22 T_CHECK(tobi_cf_recover(r.root, &r.diag));
23 tobi_ir *while_n = r.root->child[0]->child[0]->child[1];
24 T_CHECK(while_n->kind == TOBI_IR_WHILE);
25 T_CHECK(while_n->child[1]->child[0]->kind == TOBI_IR_IF);
26 tobi_parse_result_free(&r);
27
28 uint8_t ll[] = {
29 0x14,0x24,'L','L','0','0',0x01,
30 0x70,0x00,0x60,
31 0x70,0x0a,0x03,0x61,
32 0xa2,0x14,0x61,
33 0xa0,0x06,0x68,0x72,0x60,0x01,0x60,
34 0xa1,0x06,0x72,0x60,0x0a,0x02,0x60,
35 0x74,0x61,0x01,0x61,
36 0xa4,0x60
37 };
38 T_CHECK(tobi_parse(ll, sizeof(ll), 0, &r));
39 T_CHECK(tobi_cf_recover(r.root, &r.diag));
40 tobi_ir *ll_method = r.root->child[0];
41 T_CHECK(ll_method->kind == TOBI_IR_METHOD);
42 T_CHECK(strcmp(ll_method->name, "LL00") == 0);
43 tobi_ir *ll_block = ll_method->child[0];
44 T_CHECK(ll_block->child_len == 4);
45 T_CHECK(ll_block->child[2]->kind == TOBI_IR_WHILE);
46 T_CHECK(ll_block->child[2]->child[1]->child[0]->kind == TOBI_IR_IF);
47 dot = tobi_cf_dot(r.root);
48 T_STR(dot, "LL00");
49 T_STR(dot, "while");
50 T_STR(dot, "back");
51 free(dot);
52 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_AST);
53 T_STR(dot, "digraph tobi_ast");
54 T_STR(dot, "LL00");
55 T_STR(dot, "expr");
56 free(dot);
57 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE);
58 T_STR(dot, "digraph tobi_namespace");
59 T_STR(dot, "LL00");
60 T_STR(dot, "method");
61 free(dot);
62 dot = tobi_graph_dot_labels(r.root, &r.ns, TOBI_GRAPH_AST, TOBI_GRAPH_LABEL_FULL);
63 T_STR(dot, "source=raw");
64 T_STR(dot, "len=");
65 free(dot);
66 dot = tobi_graph_dot_labels(r.root, &r.ns, TOBI_GRAPH_CFG, TOBI_GRAPH_LABEL_NONE);
67 T_STR(dot, "digraph tobi_cfg");
68 T_CHECK(strstr(dot, "LL00") == NULL);
69 T_CHECK(strstr(dot, "off=0x") == NULL);
70 free(dot);
71 tobi_parse_result_free(&r);
72
73 uint8_t ns_call[] = {
74 0x14,0x08,'C','A','L','0',0x01,0xa4,0x68,
75 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05
76 };
77 T_CHECK(tobi_parse(ns_call, sizeof(ns_call), 0, &r));
78 T_CHECK(tobi_cf_recover(r.root, &r.diag));
79 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE);
80 T_STR(dot, "USE0");
81 T_STR(dot, "CAL0");
82 T_STR(dot, "call");
83 free(dot);
84 tobi_parse_result_free(&r);
85
86 uint8_t ns_field[] = {
87 0x5b,0x80,'R','E','G','0',0x01,0x0a,0x10,0x0a,0x04,
88 0x5b,0x81,0x0b,'R','E','G','0',0x00,'F','L','D','0',0x08
89 };
90 T_CHECK(tobi_parse(ns_field, sizeof(ns_field), 0, &r));
91 T_CHECK(tobi_cf_recover(r.root, &r.diag));
92 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE);
93 T_STR(dot, "FLD0");
94 T_STR(dot, "REG0");
95 T_STR(dot, "region");
96 free(dot);
97 tobi_parse_result_free(&r);
98
99 uint8_t ns_alias[] = {
100 0x08,'C','A','L','0',0x01,
101 0x06,'C','A','L','0','A','L','S','0'
102 };
103 T_CHECK(tobi_parse(ns_alias, sizeof(ns_alias), 0, &r));
104 T_CHECK(tobi_cf_recover(r.root, &r.diag));
105 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE);
106 T_STR(dot, "ALS0");
107 T_STR(dot, "alias");
108 free(dot);
109 tobi_parse_result_free(&r);
110
111 uint8_t ns_external[] = {0x15,'C','A','L','X',0x08,0x01};
112 T_CHECK(tobi_parse(ns_external, sizeof(ns_external), 0, &r));
113 T_CHECK(tobi_cf_recover(r.root, &r.diag));
114 dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE);
115 T_STR(dot, "CALX");
116 T_STR(dot, "external");
117 free(dot);
118 tobi_parse_result_free(&r);
119
120 uint8_t amb[] = {0xa0,0x03,0x01,0xa1};
121 T_CHECK(tobi_parse(amb, sizeof(amb), 0, &r));
122 T_CHECK(r.root->child_len == 1);
123 T_CHECK(r.root->child[0]->kind == TOBI_IR_IF);
124 T_CHECK(tobi_ir_find_child(r.root->child[0]->child[1], TOBI_IR_UNKNOWN) != NULL);
125 T_CHECK(tobi_cf_recover(r.root, &r.diag));
126 T_CHECK(tobi_ir_find_child(r.root->child[0]->child[1], TOBI_IR_DIAG) != NULL);
127 tobi_parse_result_free(&r);
128 return 0;
129}