ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

Select the types of activity you want to include in your feed.

Emit precedence aware AML pseudocode expressions

+151 -50
+139 -50
src/dc.c
··· 4 4 #include "str.h" 5 5 6 6 #include <stdio.h> 7 + #include <string.h> 7 8 8 9 static void indent(tobi_sb *sb, unsigned n) { 9 10 for (unsigned i = 0; i < n; i++) { ··· 16 17 17 18 static const char *binop(const char *name) { 18 19 if (!name) { 19 - return "?"; 20 + return NULL; 21 + } 22 + if (strcmp(name, "eq") == 0) return "=="; 23 + if (strcmp(name, "gt") == 0) return ">"; 24 + if (strcmp(name, "lt") == 0) return "<"; 25 + if (strcmp(name, "add") == 0) return "+"; 26 + if (strcmp(name, "sub") == 0) return "-"; 27 + if (strcmp(name, "mul") == 0) return "*"; 28 + if (strcmp(name, "div") == 0) return "/"; 29 + if (strcmp(name, "mod") == 0) return "%"; 30 + if (strcmp(name, "shl") == 0) return "<<"; 31 + if (strcmp(name, "shr") == 0) return ">>"; 32 + if (strcmp(name, "and") == 0) return "&"; 33 + if (strcmp(name, "or") == 0) return "|"; 34 + if (strcmp(name, "xor") == 0) return "^"; 35 + if (strcmp(name, "land") == 0) return "&&"; 36 + if (strcmp(name, "lor") == 0) return "||"; 37 + return NULL; 38 + } 39 + 40 + static const char *unop(const char *name) { 41 + if (!name) { 42 + return NULL; 43 + } 44 + if (strcmp(name, "lnot") == 0) return "!"; 45 + if (strcmp(name, "not") == 0) return "~"; 46 + return NULL; 47 + } 48 + 49 + static int op_prec(const char *name) { 50 + if (!name) { 51 + return 0; 52 + } 53 + if (strcmp(name, "lor") == 0) return 1; 54 + if (strcmp(name, "land") == 0) return 2; 55 + if (strcmp(name, "or") == 0) return 3; 56 + if (strcmp(name, "xor") == 0) return 4; 57 + if (strcmp(name, "and") == 0) return 5; 58 + if (strcmp(name, "eq") == 0 || strcmp(name, "gt") == 0 || strcmp(name, "lt") == 0) return 6; 59 + if (strcmp(name, "shl") == 0 || strcmp(name, "shr") == 0) return 7; 60 + if (strcmp(name, "add") == 0 || strcmp(name, "sub") == 0) return 8; 61 + if (strcmp(name, "mul") == 0 || strcmp(name, "div") == 0 || strcmp(name, "mod") == 0) return 9; 62 + if (unop(name)) return 10; 63 + return 0; 64 + } 65 + 66 + static int op_right_needs_group(const char *name) { 67 + if (!name) { 68 + return 1; 20 69 } 21 - if (name[0] == 'e' && name[1] == 'q') return "=="; 22 - if (name[0] == 'g' && name[1] == 't') return ">"; 23 - if (name[0] == 'l' && name[1] == 't') return "<"; 24 - if (name[0] == 'a' && name[1] == 'd') return "+"; 25 - if (name[0] == 's' && name[1] == 'u') return "-"; 26 - if (name[0] == 'm' && name[1] == 'u') return "*"; 27 - if (name[0] == 'd' && name[1] == 'i') return "/"; 28 - if (name[0] == 'a' && name[1] == 'n') return "&"; 29 - if (name[0] == 'o' && name[1] == 'r') return "|"; 30 - if (name[0] == 'x' && name[1] == 'o') return "^"; 31 - if (name[0] == 'l' && name[1] == 'a') return "&&"; 32 - if (name[0] == 'l' && name[1] == 'o') return "||"; 33 - return name; 70 + return !(strcmp(name, "add") == 0 || strcmp(name, "mul") == 0 || 71 + strcmp(name, "and") == 0 || strcmp(name, "or") == 0 || 72 + strcmp(name, "xor") == 0 || strcmp(name, "land") == 0 || 73 + strcmp(name, "lor") == 0); 34 74 } 35 75 36 - static void expr(tobi_sb *sb, const tobi_ir *n) { 76 + static void expr_prec(tobi_sb *sb, const tobi_ir *n, int parent_prec) { 37 77 if (!n) { 38 78 tobi_sb_add(sb, "<missing>"); 39 79 return; ··· 41 81 switch (n->kind) { 42 82 case TOBI_IR_INTEGER: 43 83 tobi_sb_printf(sb, "0x%llx", (unsigned long long)n->value); 44 - break; 84 + return; 45 85 case TOBI_IR_STRING: 46 86 tobi_sb_ch(sb, '"'); 47 87 if (n->str) { ··· 53 93 } 54 94 } 55 95 tobi_sb_ch(sb, '"'); 56 - break; 96 + return; 57 97 case TOBI_IR_REF: 58 98 tobi_sb_add(sb, n->name ? n->name : "<ref>"); 59 - break; 99 + return; 60 100 case TOBI_IR_CALL: 61 101 tobi_sb_add(sb, n->name ? n->name : "<call>"); 62 102 tobi_sb_ch(sb, '('); ··· 64 104 if (i) { 65 105 tobi_sb_add(sb, ", "); 66 106 } 67 - expr(sb, n->child[i]); 107 + expr_prec(sb, n->child[i], 0); 68 108 } 69 109 tobi_sb_ch(sb, ')'); 70 - break; 71 - case TOBI_IR_EXPR: 72 - if (n->child_len == 1) { 73 - tobi_sb_printf(sb, "%s(", n->name ? n->name : "op"); 74 - expr(sb, n->child[0]); 75 - tobi_sb_ch(sb, ')'); 76 - } else if (n->child_len >= 2) { 77 - tobi_sb_ch(sb, '('); 78 - expr(sb, n->child[0]); 79 - tobi_sb_printf(sb, " %s ", binop(n->name)); 80 - expr(sb, n->child[1]); 81 - tobi_sb_ch(sb, ')'); 82 - } else { 83 - tobi_sb_add(sb, n->name ? n->name : "<expr>"); 110 + return; 111 + case TOBI_IR_EXPR: { 112 + const char *op = binop(n->name); 113 + int prec = op_prec(n->name); 114 + if (op && n->child_len >= 2 && prec > 0) { 115 + int paren = prec < parent_prec; 116 + if (paren) { 117 + tobi_sb_ch(sb, '('); 118 + } 119 + expr_prec(sb, n->child[0], prec); 120 + tobi_sb_printf(sb, " %s ", op); 121 + expr_prec(sb, n->child[1], prec + op_right_needs_group(n->name)); 122 + if (paren) { 123 + tobi_sb_ch(sb, ')'); 124 + } 125 + return; 126 + } 127 + op = unop(n->name); 128 + if (op && n->child_len == 1 && prec > 0) { 129 + int paren = prec < parent_prec; 130 + if (paren) { 131 + tobi_sb_ch(sb, '('); 132 + } 133 + tobi_sb_add(sb, op); 134 + expr_prec(sb, n->child[0], prec); 135 + if (paren) { 136 + tobi_sb_ch(sb, ')'); 137 + } 138 + return; 84 139 } 85 - break; 140 + tobi_sb_printf(sb, "%s(", n->name ? n->name : "op"); 141 + for (size_t i = 0; i < n->child_len; i++) { 142 + if (i) { 143 + tobi_sb_add(sb, ", "); 144 + } 145 + expr_prec(sb, n->child[i], 0); 146 + } 147 + tobi_sb_ch(sb, ')'); 148 + return; 149 + } 86 150 case TOBI_IR_BUFFER: 87 151 tobi_sb_printf(sb, "Buffer[%s]", n->str ? n->str : ""); 88 - break; 152 + return; 89 153 case TOBI_IR_PACKAGE: 90 154 tobi_sb_ch(sb, '{'); 91 155 for (size_t i = 0; i < n->child_len; i++) { 92 156 if (i) { 93 157 tobi_sb_add(sb, ", "); 94 158 } 95 - expr(sb, n->child[i]); 159 + expr_prec(sb, n->child[i], 0); 96 160 } 97 161 tobi_sb_ch(sb, '}'); 98 - break; 162 + return; 99 163 case TOBI_IR_STORE: 100 164 if (n->child_len >= 2) { 101 - expr(sb, n->child[1]); 165 + expr_prec(sb, n->child[1], 0); 102 166 tobi_sb_add(sb, " = "); 103 - expr(sb, n->child[0]); 167 + expr_prec(sb, n->child[0], 0); 104 168 } else { 105 169 tobi_sb_add(sb, "store(?)"); 106 170 } 107 - break; 171 + return; 108 172 case TOBI_IR_UNKNOWN: 109 173 tobi_sb_printf(sb, "unknown_0x%x", n->raw_op); 110 - break; 174 + return; 111 175 default: 112 176 tobi_sb_add(sb, n->name ? n->name : tobi_ir_kind_name(n->kind)); 113 - break; 177 + return; 178 + } 179 + } 180 + 181 + static void expr(tobi_sb *sb, const tobi_ir *n) { 182 + expr_prec(sb, n, 0); 183 + } 184 + 185 + static int expr_has_target(const tobi_ir *n) { 186 + if (!n || n->kind != TOBI_IR_EXPR || !n->name) { 187 + return 0; 114 188 } 189 + if (strcmp(n->name, "div") == 0) { 190 + return n->child_len >= 4; 191 + } 192 + return binop(n->name) && n->child_len >= 3; 193 + } 194 + 195 + static void expr_target_stmt(tobi_sb *sb, const tobi_ir *n) { 196 + if (strcmp(n->name, "div") == 0 && n->child_len >= 4) { 197 + expr(sb, n->child[2]); 198 + tobi_sb_add(sb, ", "); 199 + expr(sb, n->child[3]); 200 + tobi_sb_add(sb, " = divmod("); 201 + expr(sb, n->child[0]); 202 + tobi_sb_add(sb, ", "); 203 + expr(sb, n->child[1]); 204 + tobi_sb_ch(sb, ')'); 205 + return; 206 + } 207 + expr(sb, n->child[2]); 208 + tobi_sb_add(sb, " = "); 209 + expr(sb, n); 115 210 } 116 211 117 212 static void block(tobi_sb *sb, const tobi_ir *b, unsigned ind) { ··· 199 294 case TOBI_IR_EXPR: 200 295 case TOBI_IR_CALL: 201 296 indent(sb, ind); 202 - if (n->child_len >= 3 && n->kind == TOBI_IR_EXPR) { 203 - expr(sb, n->child[2]); 204 - tobi_sb_add(sb, " = "); 205 - tobi_sb_ch(sb, '('); 206 - expr(sb, n->child[0]); 207 - tobi_sb_printf(sb, " %s ", binop(n->name)); 208 - expr(sb, n->child[1]); 209 - tobi_sb_ch(sb, ')'); 297 + if (expr_has_target(n)) { 298 + expr_target_stmt(sb, n); 210 299 } else { 211 300 expr(sb, n); 212 301 }
+12
test/t_dc.c
··· 24 24 T_STR(s, "unknown opcode 0xfe at 0x0"); 25 25 free(s); 26 26 tobi_parse_result_free(&r); 27 + uint8_t exprm[] = { 28 + 0x14,0x19,'E','X','P','R',0x02, 29 + 0x70,0x72,0x68,0x77,0x69,0x0a,0x02,0x60,0x61,0x62, 30 + 0xa4,0x91,0x95,0x60,0x61,0x93,0x62,0x0a,0x00 31 + }; 32 + T_CHECK(tobi_parse(exprm, sizeof(exprm), 0, &r)); 33 + s = tobi_dc_emit(r.root, &r.diag); 34 + T_STR(s, "Local2 = Arg0 + Arg1 * 0x2;"); 35 + T_STR(s, "return Local0 < Local1 || Local2 == 0x0;"); 36 + T_CHECK(strstr(s, "Arg0 + (Arg1 * 0x2)") == NULL); 37 + free(s); 38 + tobi_parse_result_free(&r); 27 39 return 0; 28 40 }