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
10 kB 340 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 { 224 const char *out_path = "/tmp/tobi_cli_graph.dot"; 225 const char *argv_out[] = {TOBI_BIN, "--dot", path, "-o", out_path, NULL}; 226 s = run_capture_argv(argv_out, NULL, 0, &st); 227 T_CHECK(st == 0); 228 T_CHECK(s[0] == '\0'); 229 free(s); 230 s = read_text(out_path); 231 T_STR(s, "digraph tobi_cfg"); 232 free(s); 233 } 234 { 235 unsigned char stdin_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 236 const char *argv_stdin[] = {TOBI_BIN, "--json", "-", NULL}; 237 s = run_capture_argv(argv_stdin, stdin_file, sizeof(stdin_file), &st); 238 T_CHECK(st == 0); 239 T_STR(s, "\"source\":\"<stdin>\""); 240 T_STR(s, "MTH0"); 241 free(s); 242 } 243 { 244 unsigned char user_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 245 const char *space_path = "/tmp/tobi cli space.aml"; 246 T_CHECK(write_blob(space_path, user_file, sizeof(user_file))); 247 const char *argv_space[] = {TOBI_BIN, "--json", space_path, NULL}; 248 s = run_capture_argv(argv_space, NULL, 0, &st); 249 T_CHECK(st == 0); 250 T_STR(s, space_path); 251 free(s); 252 } 253 { 254 unsigned char user_file[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; 255 char long_path[240] = "/tmp/tobi_cli_"; 256 size_t pos = strlen(long_path); 257 memset(long_path + pos, 'a', 150); 258 strcpy(long_path + pos + 150, ".aml"); 259 T_CHECK(write_blob(long_path, user_file, sizeof(user_file))); 260 const char *argv_long[] = {TOBI_BIN, "--json", long_path, NULL}; 261 s = run_capture_argv(argv_long, NULL, 0, &st); 262 T_CHECK(st == 0); 263 T_STR(s, long_path); 264 free(s); 265 } 266 { 267 unsigned char user_file[] = { 268 0x14,0x24,'L','L','0','0',0x01, 269 0x70,0x00,0x60, 270 0x70,0x0a,0x03,0x61, 271 0xa2,0x14,0x61, 272 0xa0,0x06,0x68,0x72,0x60,0x01,0x60, 273 0xa1,0x06,0x72,0x60,0x0a,0x02,0x60, 274 0x74,0x61,0x01,0x61, 275 0xa4,0x60 276 }; 277 const char *user_path = "/tmp/tobi_cli_user_dot.aml"; 278 T_CHECK(write_blob(user_path, user_file, sizeof(user_file))); 279 const char *argv_user_dot[] = {TOBI_BIN, "--dot", user_path, NULL}; 280 s = run_capture_argv(argv_user_dot, NULL, 0, &st); 281 T_CHECK(st == 0); 282 T_STR(s, "digraph tobi_cfg"); 283 T_STR(s, "LL00"); 284 T_STR(s, "while"); 285 T_STR(s, "back"); 286 free(s); 287 } 288 const char *argv_raw[] = {TOBI_BIN, "--raw", path, NULL}; 289 s = run_capture_argv(argv_raw, NULL, 0, &st); 290 T_CHECK(st == 0); 291 T_STR(s, "checksum_sum=0x00"); 292 T_STR(s, "checksum_valid=false"); 293 free(s); 294 { 295 unsigned char use_file[] = {0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05}; 296 unsigned char cal_file[] = {0x14,0x08,'C','A','L','0',0x01,0xa4,0x68}; 297 const char *use_path = "/tmp/tobi_cli_use.aml"; 298 const char *cal_path = "/tmp/tobi_cli_cal.aml"; 299 T_CHECK(write_blob(use_path, use_file, sizeof(use_file))); 300 T_CHECK(write_blob(cal_path, cal_file, sizeof(cal_file))); 301 const char *argv_multi[] = {TOBI_BIN, use_path, cal_path, NULL}; 302 s = run_capture_argv(argv_multi, NULL, 0, &st); 303 T_CHECK(st == 0); 304 T_STR(s, "method USE0"); 305 T_STR(s, "CAL0(0x5)"); 306 free(s); 307 } 308 const char *argv_help[] = {TOBI_BIN, "--help", NULL}; 309 s = run_capture_argv(argv_help, NULL, 0, &st); 310 T_CHECK(st == 0); 311 T_STR(s, "usage: tobi"); 312 free(s); 313 const char *argv_version[] = {TOBI_BIN, "--version", NULL}; 314 s = run_capture_argv(argv_version, NULL, 0, &st); 315 T_CHECK(st == 0); 316 T_STR(s, "tobi 0.1.0"); 317 free(s); 318 const char *argv_conflict[] = {TOBI_BIN, "--json", "--dis", path, NULL}; 319 s = run_capture_argv(argv_conflict, NULL, 0, &st); 320 T_CHECK(st == 2); 321 free(s); 322 const char *argv_bad_opt[] = {TOBI_BIN, "--definitely-not-real", NULL}; 323 s = run_capture_argv(argv_bad_opt, NULL, 0, &st); 324 T_CHECK(st == 2); 325 free(s); 326 const char *argv_bad_graph[] = {TOBI_BIN, "--graph", "nope", path, NULL}; 327 s = run_capture_argv(argv_bad_graph, NULL, 0, &st); 328 T_CHECK(st == 2); 329 free(s); 330 const char *argv_missing_graph[] = {TOBI_BIN, "--graph", NULL}; 331 s = run_capture_argv(argv_missing_graph, NULL, 0, &st); 332 T_CHECK(st == 2); 333 free(s); 334 snprintf(path, sizeof(path), "%s/sam/bad0.aml", TOBI_SRC_DIR); 335 const char *argv_strict[] = {TOBI_BIN, "--strict", path, NULL}; 336 s = run_capture_argv(argv_strict, NULL, 0, &st); 337 T_CHECK(st != 0); 338 free(s); 339 return 0; 340}