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 / test / t_cli.c
11 kB 357 lines
1#include "t.h" 2 3#include <errno.h> 4#include <fcntl.h> 5#include <sys/wait.h> 6#include <unistd.h> 7 8#ifndef TOBI_BIN 9#define TOBI_BIN "./tobi" 10#endif 11#ifndef TOBI_SRC_DIR 12#define TOBI_SRC_DIR "." 13#endif 14 15static char *empty_text(void) { 16 char *buf = malloc(1); 17 if (!buf) { 18 abort(); 19 } 20 buf[0] = '\0'; 21 return buf; 22} 23 24static int write_blob(const char *path, const unsigned char *data, size_t len) { 25 FILE *fp = fopen(path, "wb"); 26 if (!fp) { 27 return 0; 28 } 29 int ok = fwrite(data, 1, len, fp) == len; 30 return fclose(fp) == 0 && ok; 31} 32 33static char *read_text(const char *path) { 34 FILE *fp = fopen(path, "rb"); 35 if (!fp) { 36 return empty_text(); 37 } 38 if (fseek(fp, 0, SEEK_END) != 0) { 39 fclose(fp); 40 return empty_text(); 41 } 42 long n = ftell(fp); 43 if (n < 0) { 44 fclose(fp); 45 return empty_text(); 46 } 47 rewind(fp); 48 char *buf = malloc((size_t)n + 1u); 49 if (!buf) { 50 fclose(fp); 51 abort(); 52 } 53 size_t got = fread(buf, 1, (size_t)n, fp); 54 buf[got] = '\0'; 55 fclose(fp); 56 return buf; 57} 58 59static int write_all_fd(int fd, const unsigned char *data, size_t len) { 60 size_t off = 0; 61 while (off < len) { 62 ssize_t n = write(fd, data + off, len - off); 63 if (n < 0) { 64 if (errno == EINTR) { 65 continue; 66 } 67 return 0; 68 } 69 off += (size_t)n; 70 } 71 return 1; 72} 73 74static char *read_all_fd(int fd) { 75 size_t cap = 4096; 76 size_t len = 0; 77 char *buf = malloc(cap); 78 if (!buf) { 79 abort(); 80 } 81 for (;;) { 82 if (len + 1 == cap) { 83 cap *= 2u; 84 char *nb = realloc(buf, cap); 85 if (!nb) { 86 free(buf); 87 abort(); 88 } 89 buf = nb; 90 } 91 ssize_t n = read(fd, buf + len, cap - len - 1u); 92 if (n < 0) { 93 if (errno == EINTR) { 94 continue; 95 } 96 free(buf); 97 return empty_text(); 98 } 99 if (n == 0) { 100 break; 101 } 102 len += (size_t)n; 103 } 104 buf[len] = '\0'; 105 return buf; 106} 107 108static char *run_capture_argv(const char *const argv[], const unsigned char *input, size_t input_len, int *status) { 109 int out_pipe[2]; 110 int in_pipe[2] = {-1, -1}; 111 if (pipe(out_pipe) != 0) { 112 *status = 99; 113 return empty_text(); 114 } 115 if (input && pipe(in_pipe) != 0) { 116 close(out_pipe[0]); 117 close(out_pipe[1]); 118 *status = 99; 119 return empty_text(); 120 } 121 pid_t pid = fork(); 122 if (pid < 0) { 123 close(out_pipe[0]); 124 close(out_pipe[1]); 125 if (input) { 126 close(in_pipe[0]); 127 close(in_pipe[1]); 128 } 129 *status = 99; 130 return empty_text(); 131 } 132 if (pid == 0) { 133 if (input) { 134 dup2(in_pipe[0], STDIN_FILENO); 135 } else { 136 int devnull = open("/dev/null", O_RDONLY); 137 if (devnull >= 0) { 138 dup2(devnull, STDIN_FILENO); 139 close(devnull); 140 } 141 } 142 dup2(out_pipe[1], STDOUT_FILENO); 143 int devnull = open("/dev/null", O_WRONLY); 144 if (devnull >= 0) { 145 dup2(devnull, STDERR_FILENO); 146 close(devnull); 147 } 148 close(out_pipe[0]); 149 close(out_pipe[1]); 150 if (input) { 151 close(in_pipe[0]); 152 close(in_pipe[1]); 153 } 154 execv(argv[0], (char *const *)argv); 155 _exit(127); 156 } 157 close(out_pipe[1]); 158 if (input) { 159 close(in_pipe[0]); 160 if (!write_all_fd(in_pipe[1], input, input_len)) { 161 close(in_pipe[1]); 162 close(out_pipe[0]); 163 (void)waitpid(pid, NULL, 0); 164 *status = 99; 165 return empty_text(); 166 } 167 close(in_pipe[1]); 168 } 169 char *buf = read_all_fd(out_pipe[0]); 170 close(out_pipe[0]); 171 int rc = 0; 172 if (waitpid(pid, &rc, 0) < 0) { 173 free(buf); 174 *status = 99; 175 return empty_text(); 176 } 177 *status = WIFEXITED(rc) ? WEXITSTATUS(rc) : 99; 178 return buf; 179} 180 181int t_cli(void) { 182 int st = 0; 183 char path[512]; 184 snprintf(path, sizeof(path), "%s/sam/m0.aml", TOBI_SRC_DIR); 185 const char *argv_default[] = {TOBI_BIN, path, NULL}; 186 char *s = run_capture_argv(argv_default, NULL, 0, &st); 187 T_CHECK(st == 0); 188 T_STR(s, "method MTH0"); 189 T_STR(s, "return Local0"); 190 free(s); 191 const char *argv_dis[] = {TOBI_BIN, "--dis", path, NULL}; 192 s = run_capture_argv(argv_dis, NULL, 0, &st); 193 T_CHECK(st == 0); 194 T_STR(s, "0x0000"); 195 T_STR(s, "MethodOp"); 196 free(s); 197 const char *argv_json[] = {TOBI_BIN, "--json", path, NULL}; 198 s = run_capture_argv(argv_json, NULL, 0, &st); 199 T_CHECK(st == 0); 200 T_STR(s, "\"ir\""); 201 T_STR(s, "\"kind\":\"method\""); 202 T_STR(s, path); 203 T_CHECK(strstr(s, "\"source\":\"raw\"") == NULL); 204 free(s); 205 const char *argv_dot[] = {TOBI_BIN, "--dot", path, NULL}; 206 s = run_capture_argv(argv_dot, NULL, 0, &st); 207 T_CHECK(st == 0); 208 T_STR(s, "digraph tobi_cfg"); 209 T_STR(s, "method"); 210 free(s); 211 const char *argv_ast[] = {TOBI_BIN, "--graph", "ast", path, NULL}; 212 s = run_capture_argv(argv_ast, NULL, 0, &st); 213 T_CHECK(st == 0); 214 T_STR(s, "digraph tobi_ast"); 215 T_STR(s, "MTH0"); 216 free(s); 217 const char *argv_ns[] = {TOBI_BIN, "--graph", "namespace", path, NULL}; 218 s = run_capture_argv(argv_ns, NULL, 0, &st); 219 T_CHECK(st == 0); 220 T_STR(s, "digraph tobi_namespace"); 221 T_STR(s, "MTH0"); 222 free(s); 223 const char *argv_full_labels[] = {TOBI_BIN, "--graph", "ast", "--graph-labels", "full", path, NULL}; 224 s = run_capture_argv(argv_full_labels, NULL, 0, &st); 225 T_CHECK(st == 0); 226 T_STR(s, "source="); 227 T_STR(s, "len="); 228 free(s); 229 const char *argv_no_labels[] = {TOBI_BIN, "--dot", "--graph-labels", "none", path, NULL}; 230 s = run_capture_argv(argv_no_labels, NULL, 0, &st); 231 T_CHECK(st == 0); 232 T_STR(s, "digraph tobi_cfg"); 233 T_CHECK(strstr(s, "MTH0") == NULL); 234 T_CHECK(strstr(s, "off=0x") == NULL); 235 free(s); 236 { 237 const char *out_path = "/tmp/tobi_cli_graph.dot"; 238 const char *argv_out[] = {TOBI_BIN, "--dot", path, "-o", out_path, NULL}; 239 s = run_capture_argv(argv_out, NULL, 0, &st); 240 T_CHECK(st == 0); 241 T_CHECK(s[0] == '\0'); 242 free(s); 243 s = read_text(out_path); 244 T_STR(s, "digraph tobi_cfg"); 245 free(s); 246 } 247 { 248 unsigned char stdin_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 249 const char *argv_stdin[] = {TOBI_BIN, "--json", "-", NULL}; 250 s = run_capture_argv(argv_stdin, stdin_file, sizeof(stdin_file), &st); 251 T_CHECK(st == 0); 252 T_STR(s, "\"source\":\"<stdin>\""); 253 T_STR(s, "MTH0"); 254 free(s); 255 } 256 { 257 unsigned char user_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 258 const char *space_path = "/tmp/tobi cli space.aml"; 259 T_CHECK(write_blob(space_path, user_file, sizeof(user_file))); 260 const char *argv_space[] = {TOBI_BIN, "--json", space_path, NULL}; 261 s = run_capture_argv(argv_space, NULL, 0, &st); 262 T_CHECK(st == 0); 263 T_STR(s, space_path); 264 free(s); 265 } 266 { 267 unsigned char user_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 268 char long_path[240] = "/tmp/tobi_cli_"; 269 size_t pos = strlen(long_path); 270 memset(long_path + pos, 'a', 150); 271 strcpy(long_path + pos + 150, ".aml"); 272 T_CHECK(write_blob(long_path, user_file, sizeof(user_file))); 273 const char *argv_long[] = {TOBI_BIN, "--json", long_path, NULL}; 274 s = run_capture_argv(argv_long, NULL, 0, &st); 275 T_CHECK(st == 0); 276 T_STR(s, long_path); 277 free(s); 278 } 279 { 280 unsigned char user_file[] = { 281 0x14,0x24,'L','L','0','0',0x01, 282 0x70,0x00,0x60, 283 0x70,0x0a,0x03,0x61, 284 0xa2,0x14,0x61, 285 0xa0,0x06,0x68,0x72,0x60,0x01,0x60, 286 0xa1,0x06,0x72,0x60,0x0a,0x02,0x60, 287 0x74,0x61,0x01,0x61, 288 0xa4,0x60 289 }; 290 const char *user_path = "/tmp/tobi_cli_user_dot.aml"; 291 T_CHECK(write_blob(user_path, user_file, sizeof(user_file))); 292 const char *argv_user_dot[] = {TOBI_BIN, "--dot", user_path, NULL}; 293 s = run_capture_argv(argv_user_dot, NULL, 0, &st); 294 T_CHECK(st == 0); 295 T_STR(s, "digraph tobi_cfg"); 296 T_STR(s, "LL00"); 297 T_STR(s, "while"); 298 T_STR(s, "back"); 299 free(s); 300 } 301 const char *argv_raw[] = {TOBI_BIN, "--raw", path, NULL}; 302 s = run_capture_argv(argv_raw, NULL, 0, &st); 303 T_CHECK(st == 0); 304 T_STR(s, "checksum_sum=0x00"); 305 T_STR(s, "checksum_valid=false"); 306 free(s); 307 { 308 unsigned char use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05}; 309 unsigned char cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68}; 310 const char *use_path = "/tmp/tobi_cli_use.aml"; 311 const char *cal_path = "/tmp/tobi_cli_cal.aml"; 312 T_CHECK(write_blob(use_path, use_file, sizeof(use_file))); 313 T_CHECK(write_blob(cal_path, cal_file, sizeof(cal_file))); 314 const char *argv_multi[] = {TOBI_BIN, use_path, cal_path, NULL}; 315 s = run_capture_argv(argv_multi, NULL, 0, &st); 316 T_CHECK(st == 0); 317 T_STR(s, "method USE0"); 318 T_STR(s, "CAL0(0x5)"); 319 free(s); 320 } 321 const char *argv_help[] = {TOBI_BIN, "--help", NULL}; 322 s = run_capture_argv(argv_help, NULL, 0, &st); 323 T_CHECK(st == 0); 324 T_STR(s, "usage: tobi"); 325 free(s); 326 const char *argv_version[] = {TOBI_BIN, "--version", NULL}; 327 s = run_capture_argv(argv_version, NULL, 0, &st); 328 T_CHECK(st == 0); 329 T_STR(s, "tobi 0.1.0"); 330 free(s); 331 const char *argv_conflict[] = {TOBI_BIN, "--json", "--dis", path, NULL}; 332 s = run_capture_argv(argv_conflict, NULL, 0, &st); 333 T_CHECK(st == 2); 334 free(s); 335 const char *argv_bad_opt[] = {TOBI_BIN, "--definitely-not-real", NULL}; 336 s = run_capture_argv(argv_bad_opt, NULL, 0, &st); 337 T_CHECK(st == 2); 338 free(s); 339 const char *argv_bad_graph[] = {TOBI_BIN, "--graph", "nope", path, NULL}; 340 s = run_capture_argv(argv_bad_graph, NULL, 0, &st); 341 T_CHECK(st == 2); 342 free(s); 343 const char *argv_bad_graph_labels[] = {TOBI_BIN, "--graph-labels", "verbose", path, NULL}; 344 s = run_capture_argv(argv_bad_graph_labels, NULL, 0, &st); 345 T_CHECK(st == 2); 346 free(s); 347 const char *argv_missing_graph[] = {TOBI_BIN, "--graph", NULL}; 348 s = run_capture_argv(argv_missing_graph, NULL, 0, &st); 349 T_CHECK(st == 2); 350 free(s); 351 snprintf(path, sizeof(path), "%s/sam/bad0.aml", TOBI_SRC_DIR); 352 const char *argv_strict[] = {TOBI_BIN, "--strict", path, NULL}; 353 s = run_capture_argv(argv_strict, NULL, 0, &st); 354 T_CHECK(st != 0); 355 free(s); 356 return 0; 357}