ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

tobi / src / da.c
8.0 kB 233 lines
1#include "da.h" 2 3#include "nm.h" 4#include "op.h" 5#include "rd.h" 6#include "str.h" 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11 12static void raw_bytes(tobi_sb *sb, const tobi_rd *rd, size_t start, size_t end) { 13 tobi_sb_add(sb, " raw="); 14 size_t n = end > start ? end - start : 0; 15 size_t max = n > 8 ? 8 : n; 16 for (size_t i = 0; i < max && start + i < rd->len; i++) { 17 tobi_sb_printf(sb, "%02x", rd->data[start + i]); 18 if (i + 1 < max) { 19 tobi_sb_ch(sb, ' '); 20 } 21 } 22 if (n > max) { 23 tobi_sb_add(sb, " ..."); 24 } 25} 26 27static void skip_simple_arg(tobi_rd *rd) { 28 uint8_t op = 0; 29 if (!tobi_rd_u8(rd, &op)) { 30 return; 31 } 32 if (op == 0x0a) { 33 (void)tobi_rd_skip(rd, 1); 34 } else if (op == 0x0b) { 35 (void)tobi_rd_skip(rd, 2); 36 } else if (op == 0x0c) { 37 (void)tobi_rd_skip(rd, 4); 38 } else if (op == 0x0e) { 39 (void)tobi_rd_skip(rd, 8); 40 } else if (op == 0x0d) { 41 while (tobi_rd_left(rd) > 0) { 42 uint8_t c = 0; 43 (void)tobi_rd_u8(rd, &c); 44 if (c == 0) { 45 break; 46 } 47 } 48 } 49} 50 51static void walk(tobi_sb *sb, tobi_rd *rd, unsigned depth) { 52 if (depth > 64) { 53 tobi_sb_printf(sb, "0x%04zx: <nesting limit>\n", tobi_rd_off(rd)); 54 rd->pos = rd->len; 55 return; 56 } 57 while (tobi_rd_left(rd) > 0) { 58 size_t start = rd->pos; 59 size_t off = tobi_rd_off(rd); 60 uint8_t op = 0; 61 if (!tobi_rd_u8(rd, &op)) { 62 break; 63 } 64 uint16_t code = op; 65 const tobi_op *meta = NULL; 66 if (op == 0x5b) { 67 uint8_t ext = 0; 68 if (!tobi_rd_u8(rd, &ext)) { 69 tobi_sb_printf(sb, "0x%04zx: ExtOpPrefix truncated raw=5b\n", off); 70 return; 71 } 72 code = (uint16_t)(0x5b00u | ext); 73 meta = tobi_op_find_ext(ext); 74 } else { 75 meta = tobi_op_find(op); 76 } 77 if (!meta && (op == '\\' || op == '^' || op == 0x2e || op == 0x2f || tobi_nm_is_lead(op))) { 78 rd->pos = start; 79 char *nm = NULL; 80 if (tobi_nm_namestring(rd, &nm)) { 81 tobi_sb_printf(sb, "0x%04zx: NameString name=%s", off, nm); 82 raw_bytes(sb, rd, start, rd->pos); 83 tobi_sb_ch(sb, '\n'); 84 free(nm); 85 continue; 86 } 87 rd->pos = start + 1; 88 } 89 const char *name = meta ? meta->name : "UnknownOp"; 90 const char *operands = tobi_op_operands(code); 91 int decoded_pseudo = 0; 92 char extra[128]; 93 extra[0] = '\0'; 94 if (op == 0x0a) { 95 uint8_t v = 0; 96 if (tobi_rd_u8(rd, &v)) { 97 (void)snprintf(extra, sizeof(extra), " value=0x%x", (unsigned)v); 98 } 99 } else if (op == 0x0b) { 100 uint16_t v = 0; 101 if (tobi_rd_u16(rd, &v)) { 102 (void)snprintf(extra, sizeof(extra), " value=0x%x", (unsigned)v); 103 } 104 } else if (op == 0x0c) { 105 uint32_t v = 0; 106 if (tobi_rd_u32(rd, &v)) { 107 (void)snprintf(extra, sizeof(extra), " value=0x%x", (unsigned)v); 108 } 109 } else if (op == 0x0e) { 110 uint64_t v = 0; 111 if (tobi_rd_u64(rd, &v)) { 112 (void)snprintf(extra, sizeof(extra), " value=0x%llx", (unsigned long long)v); 113 } 114 } else if (op == 0x0d) { 115 size_t s = rd->pos; 116 while (rd->pos < rd->len && rd->data[rd->pos] != 0) { 117 rd->pos++; 118 } 119 size_t n = rd->pos - s; 120 if (rd->pos < rd->len) { 121 rd->pos++; 122 } 123 (void)snprintf(extra, sizeof(extra), " strlen=%zu", n); 124 } else if (op >= 0x60 && op <= 0x67) { 125 (void)snprintf(extra, sizeof(extra), " name=Local%u", (unsigned)(op - 0x60)); 126 name = "LocalObj"; 127 decoded_pseudo = 1; 128 } else if (op >= 0x68 && op <= 0x6e) { 129 (void)snprintf(extra, sizeof(extra), " name=Arg%u", (unsigned)(op - 0x68)); 130 name = "ArgObj"; 131 decoded_pseudo = 1; 132 } else if (op == 0x08 || op == 0x06 || code == 0x5b80 || code == 0x5b01 || code == 0x5b02) { 133 char *nm = NULL; 134 if (tobi_nm_namestring(rd, &nm)) { 135 (void)snprintf(extra, sizeof(extra), " name=%s", nm); 136 free(nm); 137 } 138 if (op == 0x06) { 139 char *dst = NULL; 140 if (tobi_nm_namestring(rd, &dst)) { 141 size_t used = strlen(extra); 142 (void)snprintf(extra + used, sizeof(extra) - used, " target=%s", dst); 143 free(dst); 144 } 145 } 146 } 147 tobi_sb_printf(sb, "0x%04zx: %s", off, name); 148 if (operands && operands[0]) { 149 tobi_sb_printf(sb, " operands=%s", operands); 150 } 151 if (meta && meta->has_pkg_len) { 152 size_t pkg_start = rd->pos; 153 size_t pkg_len = 0; 154 size_t enc = 0; 155 if (!tobi_rd_pkg_len(rd, &pkg_len, &enc)) { 156 raw_bytes(sb, rd, start, rd->pos); 157 tobi_sb_add(sb, " malformed-pkglen\n"); 158 return; 159 } 160 size_t body_start = rd->pos; 161 size_t end = pkg_start + pkg_len; 162 if (end > rd->len || end < body_start) { 163 end = rd->len; 164 tobi_sb_add(sb, " truncated"); 165 } 166 tobi_sb_printf(sb, " pkglen=%zu", pkg_len); 167 if (code == 0x10 || code == 0x14 || code == 0x5b82 || code == 0x5b83 || code == 0x5b81) { 168 tobi_rd copy = *rd; 169 char *nm = NULL; 170 if (tobi_nm_namestring(&copy, &nm)) { 171 tobi_sb_add(sb, " name="); 172 tobi_sb_add(sb, nm); 173 free(nm); 174 } 175 } 176 raw_bytes(sb, rd, start, body_start); 177 tobi_sb_ch(sb, '\n'); 178 tobi_rd sub; 179 tobi_rd_init(&sub, rd->data + body_start, end - body_start, rd->base + body_start); 180 if (code == 0x11) { 181 skip_simple_arg(&sub); 182 tobi_sb_printf(sb, "0x%04zx: BufferData len=%zu ", tobi_rd_off(&sub), tobi_rd_left(&sub)); 183 raw_bytes(sb, &sub, sub.pos, sub.len); 184 tobi_sb_ch(sb, '\n'); 185 } else if (code == 0x14) { 186 char *nm = NULL; 187 if (tobi_nm_namestring(&sub, &nm)) { 188 free(nm); 189 (void)tobi_rd_skip(&sub, 1); 190 } 191 } else if (code == 0x10 || code == 0x5b82) { 192 char *nm = NULL; 193 if (tobi_nm_namestring(&sub, &nm)) { 194 free(nm); 195 } 196 } else if (code == 0x5b81) { 197 char *nm = NULL; 198 if (tobi_nm_namestring(&sub, &nm)) { 199 free(nm); 200 (void)tobi_rd_skip(&sub, 1); 201 } 202 } else if (code == 0xa0 || code == 0xa2) { 203 (void)tobi_rd_skip(&sub, 1); 204 } 205 if (code != 0x11) { 206 walk(sb, &sub, depth + 1); 207 } 208 rd->pos = end; 209 } else { 210 tobi_sb_add(sb, extra); 211 raw_bytes(sb, rd, start, rd->pos); 212 if (!meta && !decoded_pseudo) { 213 tobi_sb_printf(sb, " opcode=0x%x", (unsigned)code); 214 } 215 tobi_sb_ch(sb, '\n'); 216 } 217 } 218} 219 220char *tobi_da_emit(const uint8_t *data, size_t len, const tobi_input_meta *meta) { 221 tobi_sb sb; 222 tobi_sb_init(&sb); 223 size_t off = meta ? meta->aml_off : 0; 224 size_t alen = meta ? meta->aml_len : len; 225 if (off > len || alen > len - off) { 226 off = 0; 227 alen = len; 228 } 229 tobi_rd rd; 230 tobi_rd_init(&rd, data + off, alen, off); 231 walk(&sb, &rd, 0); 232 return tobi_sb_take(&sb); 233}