ACPI AML decompiler w/ CFG recovery and structured pseudocode
1#include "t.h"
2
3#include "cf.h"
4#include "dc.h"
5#include "js.h"
6#include "p.h"
7#include "str.h"
8
9static void snap_node(tobi_sb *sb, const tobi_ir *n) {
10 tobi_sb_printf(sb, "%zu:%zu:", n->id, n->parent_id);
11 if (n->parent_id == 0) {
12 tobi_sb_add(sb, "-");
13 } else {
14 tobi_sb_printf(sb, "%zu", n->parent_index);
15 }
16 tobi_sb_printf(sb, ":%s", tobi_ir_kind_name(n->kind));
17 if (n->name) {
18 tobi_sb_printf(sb, ":%s", n->name);
19 }
20 if (n->scope) {
21 tobi_sb_printf(sb, ":scope=%s", n->scope);
22 }
23 tobi_sb_ch(sb, '\n');
24 for (size_t i = 0; i < n->child_len; i++) {
25 snap_node(sb, n->child[i]);
26 }
27}
28
29static char *snapshot(const tobi_ir *root) {
30 tobi_sb sb;
31 tobi_sb_init(&sb);
32 snap_node(&sb, root);
33 return tobi_sb_take(&sb);
34}
35
36int t_snap(void) {
37 uint8_t m0[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60};
38 tobi_parse_result r;
39 T_CHECK(tobi_parse(m0, sizeof(m0), 0, &r));
40 T_CHECK(tobi_cf_recover(r.root, &r.diag));
41 char *s = snapshot(r.root);
42 const char *want =
43 "1:0:-:root:scope=\\\n"
44 "2:1:0:method:MTH0\n"
45 "3:2:0:block:scope=\\MTH0\n"
46 "4:3:0:store\n"
47 "5:4:0:integer\n"
48 "6:4:1:ref:Local0\n"
49 "7:3:1:return\n"
50 "8:7:0:ref:Local0\n";
51 T_CHECK(strcmp(s, want) == 0);
52 free(s);
53
54 char *j = tobi_js_emit(&r);
55 T_STR(j, "\"id\":1");
56 T_STR(j, "\"parent_id\":1");
57 T_STR(j, "\"parent_index\":0");
58 T_STR(j, "\"scope\":\"\\\\MTH0\"");
59 T_CHECK(strstr(j, ",}") == NULL);
60 T_CHECK(strstr(j, ",]") == NULL);
61 free(j);
62
63 char *d = tobi_dc_emit(r.root, &r.diag);
64 const char *dwant =
65 "method MTH0(args=1, serialized=false, sync=0) {\n"
66 " Local0 = 0x2a;\n"
67 " return Local0;\n"
68 "}\n";
69 T_CHECK(strcmp(d, dwant) == 0);
70 free(d);
71 tobi_parse_result_free(&r);
72
73 uint8_t nested[] = {
74 0x10,0x14,'\\','_','S','B','_',0x5b,0x82,0x0c,'D','E','V','0',
75 0x14,0x06,'M','0','0','0',0x00
76 };
77 T_CHECK(tobi_parse(nested, sizeof(nested), 0, &r));
78 T_CHECK(strcmp(r.root->scope, "\\") == 0);
79 T_CHECK(strcmp(r.root->child[0]->child[0]->scope, "\\_SB_") == 0);
80 T_CHECK(strcmp(r.root->child[0]->child[0]->child[0]->child[0]->scope, "\\_SB_.DEV0") == 0);
81 T_CHECK(strcmp(r.root->child[0]->child[0]->child[0]->child[0]->child[0]->child[0]->scope,
82 "\\_SB_.DEV0.M000") == 0);
83 T_CHECK(r.root->child[0]->id == 2);
84 T_CHECK(r.root->child[0]->child[0]->parent_id == r.root->child[0]->id);
85 tobi_parse_result_free(&r);
86 return 0;
87}